UnboundID LDAP SDK for Java 5.0.1

The UnboundID LDAP SDK for Java is a fast, powerful, user-friendly, and completely free Java library for communicating with LDAP directory servers and performing other LDAP-related processing. We have just released version 5.0.1 of the LDAP SDK, and it is available for download from GitHub and SourceForge, as well as from the Maven Central Repository. The release notes are available online at https://docs.ldap.com/ldap-sdk/docs/release-notes.html.

This is a minor release that was primarily created in service of an upcoming release of the Ping Identity Directory Server, as it fixes an issue in a tool that only impacts that new release. Nevertheless, there are a couple of additional updates, so we’re making it publicly available.

The changes over the previous 5.0.0 release include:

  • We added a new LDAP connection logger API that can be used to keep a record of processing performed by the LDAP SDK, including successful and failed connection attempts, operation requests and responses (including non-final responses like search result entries, search result references, and intermediate responses), and disconnects. The LDAP SDK includes a connection logger instance that formats messages as JSON objects, but it’s an extensible API, so you’re free to create your own implementation using whatever format you want.
  • We have updated the LDAP command-line tool framework to make it possible to specify the address of the target directory server(s) using either –host or –address as an alternative to the existing –hostname argument.
  • We fixed an issue that prevented the collect-support-data tool from running properly in local mode when using a secure connection (either SSL or StartTLS). This functionality only applies to an upcoming release of the Ping Identity Directory Server, so existing installations should not have been affected, and new installations will have the fix.
  • We made minor updates to the usage output for several command-line tools to improve wording and fix typos. We also fixed typos in other messages used throughout the LDAP SDK.

UnboundID LDAP SDK for Java 5.0.0, now available under the Apache License

The UnboundID LDAP SDK for Java is a fast, powerful, user-friendly, and completely free Java library for communicating with LDAP directory servers and performing other LDAP-related processing. We have just released version 5.0.0 of the LDAP SDK, and it is available for download from GitHub and SourceForge, as well as from the Maven Central Repository. The release notes are available online at https://docs.ldap.com/ldap-sdk/docs/release-notes.html.

The most significant change in this new release is that the LDAP SDK is now available under the terms of the Apache License, Version 2.0, which is a very permissive OSI-approved open source license. Although it was already open source under the terms of the GNU GPLv2 and LGPLv2.1, the Apache License imposes fewer restrictions on how you can use the LDAP SDK. You are no longer required to offer to redistribute the source code (even if you want to use a modified version), and there’s no longer any concern about whether you need to keep the LDAP SDK jar file as a separate component. The Apache License is well respected and is often seen as more compatible and easier to use in non-open-source software than the GNU license, so we hope that this will make it easier to use in your applications, whether open source or proprietary. The LDAP SDK is still available for use under the terms of the GPLv2 and LGPLv2.1 (as well as the non-open-source UnboundID LDAP SDK Free Use License), but we recommend that new users consider using it under the Apache License.

Aside from adding the new license, we made several code changes in this release as well. They include:

  • The LDAP SDK offers an LDAPConnectionDetailsJSONSpecification class that allows you to define a JSON file with all of the settings needed to create and authenticate individual LDAP connections or connection pools. We’ve updated this class so that it’s now possible to indicate that when establishing a connection that is secured with SSL or StartTLS, the LDAP SDK should automatically trust any certificates signed by an authority in the JVM’s default set of trusted issuers. This was already the default behavior if you didn’t provide your own trust store (or choose to blindly trust all certificates, which isn’t recommended for production use), but it’s now possible to use this option in conjunction with a provided trust store so that it’s possible to trust a certificate either through that trust store or through the JVM’s default set of trusted issuers.
  • The KeyStoreKeyManager can be used to obtain a certificate from a key store file if one is needed during TLS negotiation. We have updated this class to provide an option to better validate that the key store can actually be used by this purpose with the settings that you provide. If you use this option and supply the alias of the certificate you wish to use, then the key manager will now verify that the alias exists in the key store, that it’s associated with a private key entry (as opposed to a trusted certificate entry, which only contains the public portion of a certificate and isn’t suitable for use if you need to present that certificate to the peer), and that all of the certificates in the chain are currently within their validity window. If you don’t specify a certificate alias, then the validation will make sure that the key store contains at least one private key entry in which all of the certificates in the chain are within their validity window.
  • The TrustStoreTrustManager can be used in the course of determining whether to trust a certificate presented by a peer during TLS negotiation. We have improved performance and concurrency for this trust manager by eliminating unnecessary synchronization that forced interaction with the trust store to be single-threaded.
  • We fixed an issue that could interfere with GSSAPI authentication if a JAAS login module configuration was loaded and cached by the JVM before the login attempt. In such cases, the cached configuration could be used instead of the one that was intended.
  • The LDAPDebuggerRequestHandler can be used to log detailed information about LDAP requests and responses that pass through an application using the LDAP SDK’s LDAPListener framework (including the in-memory directory server and the ldap-debugger command-line tool). We fixed an issue that could cause messages to be held up in an internal buffer rather than immediately written out as soon as they’re logged. In some cases, this could significantly delay the appearance of these messages or could prevent them from being written out at all if the amount of data to be logged was never enough to fill that internal buffer.
  • We added a new JSONAccessLogRequestHandler to the LDAPListener framework. This can log information about requests and responses as JSON objects, which are both human-readable and machine-parseable. While the existing AccessLogRequestHandler produces output that can be parsed programmatically to some extent, it is more optimized for human readability.
  • The LDAP SDK offers debugging logging support that can be helpful in diagnosing problems whose cause may not otherwise be readily apparent. Previously, the debug messages were logged in a form that was primarily intended to be human-readable rather than machine-parseable. They are now written in a JSON format that is both human-readable and machine-parseable.
  • The manage-certificates command-line tool provides a utility for interacting with certificate key and trust stores in the Java JKS format or the standard PKCS#12 format. When displaying detailed information about certificates in a key or trust store, the tool may not have been able to properly decode public key information for certificates with 384-bit elliptic curve public keys, and it also may not have been able to properly decode a subject alternative names extension that included one or more directoryName values. While it was still possible to display most of the information about the affected certificates, the updated version can now provide the full details about those elements.
  • The Ping Identity Directory Server includes a collect-support-data utility that can be used to gather a variety of information from a server installation that can be very useful for troubleshooting problems, tuning performance and scalability, and better understanding the environment in which the server is running. Previously, this utility could only be invoked by logging into the system on which the server instance is running and running the command-line tool. We have now added a couple of additional mechanisms for running the utility. It can now be invoked via an administrative task (either as an individual event that is requested by a remote client or as a recurring task that runs on a regular basis) that will create the resulting support data archive in a specified location on the system (which may be a shared filesystem for easier exfiltration). It can also be invoked via an extended operation that will run the tool and stream its output and the resulting support data archive back to the client in the form of intermediate response messages. Further, although the logic for actually collecting all of this support information remains in the server, we have added the collect-support-data command-line tool to the LDAP SDK so that it is easier to invoke the tool against a remote server without needing to install the server software on the client system.
  • The Ping Identity Directory Server provides a monitor backend that authorized clients can use to obtain a wealth of useful information about the state of the server, and the LDAP SDK includes support for retrieving and parsing the information in these monitor entries. We have updated the LDAP SDK’s support for the general monitor (that is, the top-level “cn=monitor” entry) to make it easier to obtain information about the cluster with which the server is associated, the location of the server instance, and a unique identifier that was generated for the server when the instance was initially configured.
  • The LDAP SDK offers a Version class that provides version information for the LDAP SDK, including the version number and information about the repository (e.g., the repository URL and revision ID) from which the LDAP SDK source code was obtained. This information was previously only offered as public static final constants, but referencing these constants from third-party applications could lead to unexpected behavior thanks to a “feature” of the Java compiler that will directly imbed the values of those constants (even if they come from a separate library) in the Java bytecode that it generates. This means that if your application references these LDAP SDK version constants and you compile it against one version of the LDAP SDK, then those version constants will be placed directly into the compiled bytecode. If you upgrade the LDAP SDK version that you use without recompiling your application (e.g., by just replacing the LDAP SDK jar file with a newer version), the code referencing the LDAP SDK version would still have the old values. To address this, we have updated the Version class to provide methods for obtaining the values of all the version constants. If you use these methods to obtain the values rather than referencing the constants directly, then you will always get the correct LDAP SDK version information even if you update the LDAP SDK without recompiling your application.

Ping Identity Directory Server 8.0.0.0

We have just released version 8.0.0.0 of the Ping Identity Directory Server, along with new releases of the related Directory Proxy Server, Data Synchronization Server, Metrics Engine, and Delegated User Admin products. The release notes include a comprehensive list of features, enhancements, and fixes, but here are some of the most notable changes included in the release:

  • We have expanded support for the manage-profile tool to include the Directory Proxy Server, Data Synchronization Server, and Data Governance Server products. This allows you to set up, update, or reconfigure a server using the information in a provided profile. The profile defines the configuration, schema, extensions, certificates, encryption settings, and all the other components needed to configure a server instance exactly the way you want it.
  • We have updated the Directory Proxy Server so that it can use the topology registry to automatically discover and start using Ping Identity Directory Server instances without needing to change the Directory Proxy Server configuration.
  • We have improved our support for integrating with third-party monitoring services like Splunk by updating the stats collector plugin to support sending data in StatsD format to a specified endpoint. We have also updated the periodic stats logger so that it supports generating JSON-formatted output. The former CSV output format is also still supported. And we have added a new “Status Health Summary” monitor entry that provides a summary of the server’s current assessment of its health, which especially simplifies monitoring with third-party monitoring over JMX.
  • We have updated the Directory Server so that it now supports SCIMv2 in addition to the existing SCIMv1 and Directory REST API options for REST-based access to directory data. Formerly, SCIMv2 was only available through the Data Governance Server.
  • We have added a new replace-certificate tool that makes it easier to replace a server’s listener or inter-server certificate. The tool offers a non-interactive mode that is suitable for scripting support, but it also has a full-featured interactive mode that can walk you through the process of obtaining and installing a new certificate. The interactive mode will also provide you with the necessary commands to achieve the same result in non-interactive mode.
  • We have dramatically improved our support for account status notifications. We have defined a couple of new notification types that can be raised whenever an entry is created or modified by a request that matches a given set of criteria. We have also defined many new properties that can be used in the notifications. And we have added a new multi-part email account status notification handler that can be used to send plain-text and/or HTML-formatted email messages whenever an appropriate event occurs within the server.
  • We have added a new password validator that leverages the Pwned Passwords service to make it easier to reject passwords that are known to have been compromised in data breaches.
  • We have added a new password storage scheme that uses the Argon2i password hashing algorithm, which was selected as the winner of a 2015 password hashing competition.
  • We have updated our support for the PBKDF2 password storage scheme so that it offers additional variants that leverage the 256-bit, 384-bit, and 512-bit SHA-2 digest algorithms. We have also updated the default salt length and iteration count values in accordance with NIST SP 800-63B recommendations.
  • We have improved the server’s support for generating passwords. We have added a new request control that can be included in add requests to have the server generate a password for the new entry and return it to the client in a corresponding response control. We have also added a new extended operation that can be used to request that the server generate one or more passwords that can be provided to the end user as new password suggestions when creating an account or changing a password.
  • We updated the Data Synchronization Server’s password sync agent for Active Directory so that it encodes passwords using a salted 256-bit SHA-2 digest rather than the previous salted SHA-1 digest. The SHA-1 digest can still be used if necessary for purposes of backward compatibility.
  • We updated the Data Synchronization Server’s create-sync-pipe-config tool to add support for using the PingOne for Customers service as a sync source or destination.
  • We updated Delegated Admin’s support for constructed attributes. Constructed attributes can now be made read-only, and they can also reference other constructed attributes. Constructed attribute values can now also be updated when any of their dependent attributes change.
  • We updated the HTTP external server configuration to make it possible to specify the alias of the certificate chain to be presented during mutual TLS negotiation.
  • We added a new JVM-default trust manager provider that can be used to automatically trust any certificate signed by one of the trusted issuers in the JVM’s default trust store.
  • We have added a new Server SDK API for sending email messages.
  • We updated the exec task to make it possible to specify the current working directory for the command that is being executed. The server previously always used the server root as the current working directory, and that is still the default if no alternate path is specified.
  • We updated the collect-support-data tool to add a --duration argument that will cause it to capture log content for the specified duration up to the current time.
  • We fixed an issue that prevented assured replication from being honored for requests received via SCIM or the Directory REST API.
  • We fixed an issue in which the restore tool might not have automatically restored all of the dependencies of an incremental backup.
  • We fixed an issue in which the Directory Proxy Server could incorrectly report a success result for an entry-balanced search operation in which all attempts in a backend set failed with a timeout.
  • We updated log file rotation listeners, including the summarize access log and copy log file listeners, so that they perform their processing in a background thread. This can help ensure that their processing does not temporarily block logging attempts on very busy servers.
  • We fixed an issue in which the verify-index tool could report spurious error messages when examining index keys containing multi-byte UTF-8 characters.
  • We fixed an issue in which escaped special characters in schema extensions may not be handled properly. This could cause unexpected or incorrect behavior in cases where those values are interpreted by the server (for example, in the X-VALUE-REGEX constraint in attribute type definitions).
  • We fixed an issue that could cause access log messages for bind and StartTLS operations to report the client connection policy that was previously in use for the connection rather than the new policy that was assigned as a result of the associated operation.

UnboundID LDAP SDK for Java 4.0.14

We have just released version 4.0.14 of the UnboundID LDAP SDK for Java. It is available for download from the releases page of our GitHub repository (https://github.com/pingidentity/ldapsdk/releases), from the Files page of our SourceForge repository (https://sourceforge.net/projects/ldap-sdk/files/), and from the Maven Central Repository (https://search.maven.org/search?q=g:com.unboundid%20AND%20a:unboundid-ldapsdk&core=gav).

The LDAP SDK release notes are available at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but the changes included in this release are as follows:

  • Fixed an issue in which LDAP URLs with consecutive percent-encoded bytes were not decoded correctly.
  • Fixed an issue that could cause the LDAP SDK to incorrectly handle data read from a server when the communication was protected with SASL integrity or confidentiality. Thanks to Boris Danilovich for reporting the problem and identifying the cause.
  • Fixed an issue that prevented the searchrate tool from running if neither a base DN pattern nor an LDAP URL pattern was provided.
  • Improved the logic that the LDAP SDK used when selecting the cipher suites to use when establishing a TLS-secured connection. Weaker suites are disabled, and the enabled suites are prioritized so that those offering forward secrecy and stronger encryption are preferred.
  • Added a new FullLDAPInterface that extends LDAPInterface and adds support for close, bind, and processExtendedOperation methods. The existing LDAPConnection, AbstractConnectionPool, and InMemoryDirectoryServer classes have been updated to implement this interface.
  • Added a new non-final MockableLDAPConnection class that makes it easier to mock an LDAPConnection instance. It implements FullLDAPInterface and wraps a provided LDAPConnection. If you create a MockableLDAPConnection subclass, then you may override any of the FullLDAPInterface methods to provide whatever logic you desire for them. Any non-overridden methods will invoke the corresponding method on the provided LDAPConnection instance.
  • Fixed a minor typo in the ldapsearch usage information

UnboundID LDAP SDK for Java 4.0.13

We have just released version 4.0.13 of the UnboundID LDAP SDK for Java. It is available for download from the releases page of our GitHub repository, from the Files page of our SourceForge repository, and from the Maven Central Repository.

This is a minor update that is primarily intended to serve the upcoming 8.0.0.0 release of the Ping Identity Directory Server, but it also includes some useful debugging enhancements and improvements in its support for X.509 certificates. The full release notes are available online, but the primary changes included in this release are as follows:

  • Added support for debugging connection pool interactions, including checking out and releasing connections, as well as establishing and closing connections for use in the pool.
  • Fixed an issue in the prompt trust manager that could cause it to incorrectly display a warning for some certificates with a basic constraints extension that included the optional path length constraint.
  • Updated the manage-certificates check-certificate-usability command to add an additional check to see whether the certificate at the root of the chain is found in the JVM’s default set of trusted issuer certificates. If it is not found, the tool will display a notice, but it will still complete with a success result.
  • Fixed an issue in manage-certificates that could prevent it from correctly showing the key agreement usage when displaying verbose information about a certificate with the key usage extension.
  • Fixed an issue that could prevent properly decoding an authority key identifier extension that included the optional authorityCertIssuer element in an X.509 certificate.
  • Made the ManageCertificates.readCertificatesFromFile method public so that it can be used outside of the LDAP SDK. This method can be used to read a set of PEM-encoded or DER-encoded X.509 certificates from a specified file.
  • Made the ManageCertificates.readCertificateSigningRequestFromFile method so that it can be used outside of the LDAP SDK. This method can be used to read a PEM-encoded or DER-encoded PKCS #10 certificate signing request from a file.
  • Updated the passphrase-encrypted output stream to provide an option to override the default key factory iteration count.
  • Updated support for the exec task to add an option to specify the path to use as the current working directory when invoking the specified command. Previously, the server would always use the server instance root directory, and that will still be the default if no alternate working directory is specified.
  • Added an additional StaticUtils.getEnvironmentVariable method variant that can be used to provide a default value that should be used if the specified environment variable is not set.
  • Added an additional StaticUtils.getStackTrace method variant that allows you to limit the number of stack frames to include from code before the call into the LDAP SDK. Also, updated StaticUtils.getExceptionMessage when invoked for a NullPointerException so that it now shows all frames from the LDAP SDK (and anything that the LDAP SDK calls), and up to three frames from the code before the call into the LDAP SDK.

UnboundID LDAP SDK for Java 4.0.12

We have just released version 4.0.12 of the UnboundID LDAP SDK for Java. It is available for download from the releases page of our GitHub repository (https://github.com/pingidentity/ldapsdk/releases), from the Files page of our SourceForge repository (https://sourceforge.net/projects/ldap-sdk/files/), and from the Maven Central Repository (https://search.maven.org/search?q=g:com.unboundid%20AND%20a:unboundid-ldapsdk&core=gav).

The LDAP SDK release notes are available at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but the changes included in this release are as follows:

  • Fixed an issue in the write timeout handler that could prevent it from properly cleaning up a timer task object for a connection if an attempt to establish that connection failed. This regression, which was introduced in the 4.0.11 release, could lead to a gradual increase in memory consumption over time.
  • Updated the write timeout handler so that it will now shut down its background thread after all LDAP connections have been closed.
  • Fixed an issue with the JVM-default trust manager that could cause it to incorrectly abort TLS negotiation if the server presented only a partial certificate chain, and if the last certificate in that partial chain was not included in the JVM’s default set of trusted issuers but was signed by one of those issuers.
  • Corrected the result code used in the LDAPException that is thrown when attempting to parse a malformed schema element. We now use the correct INVALID_ATTRIBUTE_SYNTAX result code instead of the INVALID_DN_SYNTAX result code that had been used by mistake.
  • Fixed an issue in the way that the persistence framework constructed LDAP attributes for its internal processing. While it would have properly selected an appropriate matching rule based on the data type of the corresponding Java field when constructing attribute type definitions for inclusion in the server schema, it neglected to use that matching rule for client-side matching involving those attributes, but instead always used a default “case-ignore string” matching behavior.
  • Updated the manage-certificates tool to use the SHA-1 digest algorithm instead of 256-bit SHA-2 when generating the subject key identifier extension for certificates and certificate signing requests. This makes it possible to work around a limitation in Microsoft certificate authorities, which are apparently unable to handle CSRs with 256-bit subject key identifiers.
  • Fixed an issue in the search-and-mod-rate tool in which the search durations reported by the tool included not only the time required to process the search, but also the time required for the associated modify operations. Further, if the tool was configured to limit the rate at which modify operations would be attempted, the reported search durations could also include any wait imposed by the rate limiter.
  • Added client-side support for the SCRAM-SHA-1, SCRAM-SHA-256, and SCRAM-SHA-512 SASL mechanisms.
  • Added client-side support for a “generate password” request and response controls. When included in an add request sent to the Ping Identity Directory Server, the request control indicates that the server should generate a password for the entry and return it to the client in the corresponding response control. The ldapmodify tool has been updated to provide support for this control.
  • Added client-side support for a “generate password” extended operation. When sent to the Ping Identity Directory Server, this operation will cause the server to generate one or more passwords that may be suggested to the end user when creating or updating a user entry.
  • Updated the transform-ldif tool to provide options to exclude LDIF records by change type, and to exclude LDIF records that do not have a changetype.
  • Updated the command-line argument parser to provide a better error message if the value the user provides to a string or Boolean value argument is not in the set of allowed values for that argument. The error message will now include a list of the allowed values.
  • Updated the command-line tool interactive mode processor so that when it prompts for a password, PIN, or other sensitive value that does not get echoed to the screen, it will now ask the user to confirm the value to help ensure that they entered it correctly.
  • Updated the command-line tool interactive mode processor so that when the user asks to see the set of arguments that will be used when running the tool, it will now display the full command rather than just listing the arguments. Further, if the command spans multiple lines, then all but the last line will now include a trailing backslash. This makes it more convenient to run the command non-interactively because it can simply be copied and pasted.
  • Updated the argument parser to provide a more convenient way to define mutually dependent argument sets, such that if any argument in the set is provided, then all of the other arguments will also be required.
  • Updated the argument parser to allow applications to define their own custom interactive mode rather than using the default one that the LDAP SDK provides.
  • Added a set of StaticUtils.linesToString convenience methods that can convert a list or array of strings to a single string that includes line breaks after each line.
  • Added a set of StaticUtils methods for obtaining all of the addresses associated with the network interfaces available on the system, and to get the canonical host names associated with those addresses.

Ping Identity Directory Server 7.3.0.1

Ping Identity Directory Server version 7.3.0.1 has been released, and it’s available for download now, along with the companion Directory Proxy Server, Data Synchronization Server, Metrics Engine, and Server SDK products. It is a patch release that primarily addresses minor issues.

Because of an unfortunate glitch in the way that we generated the documentation, the updated release notes aren’t available on the website but are only included in the download itself. Here’s a list of the changes in the release:

  • Added a “Server Status Timeline” monitor entry that tracks the server’s last 100 status changes and the times that they occurred.
  • Updated LDAP external server monitor entries to include attributes for tracking state changes to the associated server, including the number of times the health state has changed, and timestamps and messages for the most recent state changes.
  • Improved Delegated Admin support for constructed attributes. Constructed attributes can now be read-only. Added an “Update Constructed Attributes” list to the REST resource type, which allows constructed attributes to be updated when their dependent attributes change. We also now handle constructed attributes that reference other constructed attributes.
  • Fixed an issue that could prevent switching between servers in the management console.
  • Fixed an issue that could require a large amount of memory when replaying a large subtree delete operation via replication. Also fixed a related issue that could cause the server to write a large number of mild error messages to the replication log.
  • Fixed an issue in which Delegated Admin may not behave correctly if the name of the REST resource type was not the same as the name for the resource endpoint.
  • Fixed an issue in which Delegated Admin search results could be truncated if the Directory Server was configured to disable syntax enforcement for an attribute type with a Boolean or integer syntax, and if an entry was encountered with an attribute of that type that had a value that did not conform to that syntax. The offending values are now omitted from the results, and a warning message is recorded in the server’s error log.
  • Fixed an issue in the Directory Proxy Server that could prevent the use of a custom entry placement algorithm (created with the Server SDK) in a version of the server built with alternate branding (for a reseller).
  • Updated the Groovy scripting language (that we use to support scripted extensions) to version 2.5.7.

Ping Identity Directory Server 7.3.0.0

We have just released version 7.3.0.0 of the Ping Identity Directory Server, and it’s available for download now, along with the companion Directory Proxy Server, Data Synchronization Server, Metrics Engine, and Server SDK products. The release notes contain a blow-by-blow listing of the new features, enhancements, and fixes that it contains, but here are some of the highlights:

  • Added support for Red Hat Enterprise Linux 7.6, CentOS 7.6, Amazon Linux 2, and Windows Server 2019.
  • Added support for Docker 18.09.0 on Ubuntu 18.04 LTS.
  • Enable support for TLSv1.3 by default on JVMs that support it (which should be Java 11 and higher).
  • Added support for server profiles and a new manage-profile tool that can help install and manage the server using the DevOps “infrastructure as code” principle. A server profile can encapsulate the setup commands, configuration changes, Server SDK extensions, additional server root files, and other components of an installation, and it can be used in conjunction with orchestration frameworks to create a new instance with a given profile or to update an existing instance (for example, in a Blue/Green deployment) to apply a new profile.
  • Updated the server to support encrypting the contents of PIN files needed to unlock the certificate key and trust stores. If data encryption is enabled during setup, then the default PIN files will be automatically encrypted. We also updated the command-line tool framework so that files containing passwords can be encrypted, as well as the entire tools.properties file.
  • Added a cipher stream provider that can be used to protect the contents of the encryption settings database with a key from the Amazon Key Management Service.
  • Added a cipher stream provider that can be used to protect the contents of the encryption settings database with a passphrase obtained from a HashiCorp Vault server.
  • Added a pass-through authentication plugin that can make it possible to authenticate accounts with credentials from the PingOne for Customers service.
  • Added support for insignificant configuration archive attributes. Updates to the configuration that only involve one or more of these attributes may not be permanently stored in the configuration archive to prevent it from growing too large over time. For example, if last login time tracking is enabled and does not explicitly exclude root users, then any time a root user authenticated, their entry could be updated with the new last login time, and that update could have previously been stored in the configuration archive. Such updates will no longer be archived by default.
  • Enabled assured replication by default for all add, delete, and modify DN operations. Enabled assured replication by default for all modify operations that alter passwords or key password policy state attributes. With these changes, the server will now delay the response to a matching write operation until it has confirmed that the change has been replicated to all local servers, up to a maximum delay of one second.
  • Updated the server to automatically remove references to obsolete replicas. A replica is obsolete when it has been disabled and all changes from it are older than the replication purge delay.
  • Updated the changelog and replication databases to add a target-database-size configuration property that makes it possible to control purging based on the size of the database in addition to the age of the changes that they contain.
  • Updated the behavior the server exhibits when it encounters a database reference to an attribute type definition that has been removed from the schema. In the 7.2 release, the server could fail when attempting to open a backend with a reference to a nonexistent attribute type. The server will now try to prevent the removal of attribute type definitions that are referenced by one or more backends, but if it does encounter a reference to a no-longer-existent attribute type, it will raise an administrative alert and continue processing the operation under the assumption that the missing attribute type uses a directory string syntax with case-ignore matching.
  • Added an HTTP servlet extension that can be used to retrieve the server’s current availability state. It accepts GET, POST, or HEAD requests sent to a specified endpoint and returns a minimal response whose HTTP status code may be used to determine whether the server considers itself to be AVAILABLE, DEGRADED, or UNAVAILABLE. This may be useful when routing HTTP requests through a load-balancer that can use requests of this type to assess the health of backend servers. It may also be helpful for orchestration frameworks that may wish to destroy and replace instances that become unavailable.
  • Added support for new plugin types that can be used to clean up directory entries for expired or inactive PingFederate persistent sessions.
  • Updated the server to prevent creating virtual attributes that attempt to generate values for the aci or ds-cfg-global-aci attribute types, as access control rules cannot be defined as virtual attributes. Also, prevented creating virtual attributes that attempt to generate values for the member or uniqueMember attribute types, as static group membership cannot be altered using virtual attributes.
  • Added logging for DNS lookups that take longer than a warning threshold (10 seconds by default). DNS resolution timing is also available in a new monitor entry.
  • Updated the topology management framework to make it easier to diagnose connection errors, including adding monitoring information for all failed outbound connections, and raising alarms and alerts when a server fails to connect to a peer server within a configured grace period.
  • Updated the dsreplication tool so that it can work with a node that is currently out of sync with the topology master.
  • Updated the dsreplication tool to allow removing a defunct server even if that server is currently online. Also, added the ability to automatically retry a failed attempt to remove a defunct server.
  • Updated the server to automatically remove a server from the topology when dsreplication disable is used to disable replication for the last non-schema domain.
  • Updated the encrypt-file tool to display a notice recommending the use of the --decompress-input argument when decrypting a file that also appears to be GZIP-compressed.
  • Updated the result code map to make it possible to override the default result code that the server returns when a client tries to perform a password-based bind against an account that does not have a password.
  • Updated the ldapdelete command-line tool to add support for client-side subtree delete, following referrals, deleting entries that match search filters, recording failures in a rejects file, rate limiting, and a variety of additional controls.
  • Updated the HTTP configuration so that the server no longer includes stack traces in generated error pages by default.
  • Updated the “Debug Trace Logger” and “File-Based Trace Logger” log publishers so that they exclude Admin Console activity by default.
  • Updated trace log publishers to support recording events related to access token validation.
  • Updated the file retention recurring task so that it no longer logs an informational message if there are no matching files to delete.
  • Added a correlation-id-response-header property to HTTP servlet extension configuration objects that can be used to set the response header used for correlation IDs. If set for a servlet extension, this value will override the value that would have otherwise been inherited from the HTTP connection handler.
  • Added an indent-ldap-filter tool that can make it easier to visualize the structure and components of a complex search filter.
  • Updated the setup utility to add a --skipHostnameCheck argument that can be used to bypass validation of the provided server hostname.
  • Updated the docs/build-info.txt endpoint to remove version information. That version information is now available in the build-info.txt file in the server root directory.
  • Updated the Directory Proxy Server to change the default load-balancing algorithm that it uses for directing client requests to backend servers. Previously, it always used a fewest operations strategy to send each request to the server with the smallest number of outstanding requests. The new strategy still chooses the server with the fewest outstanding operations for read operations but uses a failover strategy to consistently send write operations to the same server. When combined with the Directory Server’s default use of assured replication, this load-balancing strategy can dramatically reduce the likelihood of replication or uniqueness conflicts while minimizing the performance impact of a purely failover-based approach.
  • Updated the Directory Proxy Server to reduce the default maximum connection age from one hour to ten minutes. This should help avoid problems resulting from firewalls or other networking equipment that silently close connections that have been open for too long.
  • Update the Directory Proxy Server to add an index-priming-idle-listener-timeout property to the entry-balancing request processor configuration. This property specifies the maximum length of time that the server will wait for a response to an attempt to prime the global index before it will give up and retry the attempt.
  • Updated the Directory Proxy Server to reduce the likelihood of lock contention in health checks used to check the status of replication in a backend server.
  • Updated the Data Synchronization Server to support the PingOne for Customers service as a sync source. It was already possible to use PingOne for Customers as a sync destination.
  • Updated the Data Synchronization Server’s support for PingOne for Customers as a sync destination so that it is possible to specify a default population using the name of the population as an alternative to its ID. Population names can also be used in attribute mappings.
  • Updated the Data Synchronization Server to support Apache Kafka as a sync destination. Changes are provided as JSON-formatted representations of the entries before and after the change was applied.
  • Updated the Data Synchronization Server to make it possible to impose a rate limit on a sync pipe so that it does not adversely impact the performance of the destination server.
  • Updated the Data Synchronization Server to make it easier to construct JSON objects to store in the value of a specified attribute in the sync destination.
  • Updated the Data Synchronization Server to support LDAP filters that use extensible-match or approximate-match components. The Data Synchronization Server supports the same set of matching rules as the Directory Server.
  • Updated the Data Synchronization Server to add an attribute-comparison-method configuration property to sync classes. This property can be used to indicate whether to perform syntax-based or byte-for-byte comparisons when identifying what content was updated by a change.
  • Updated the Data Synchronization Server to add base64-encode-value and base64-decode-value properties to direct attribute mappings to facilitate synchronizing binary data.
  • Updated the Delegated Administration configuration. Delegated Admin Resource Types have been removed and replaced by REST Resource Types. Delegated Administrators and Delegated Group Administrators were removed and replaced by Delegated Admin Rights and Delegated Admin Resource Rights. When updating an existing server, older definitions will automatically be converted to their appropriate new versions.
  • Updated the Server SDK to make it easier to read and write data encrypted with keys from the server’s encryption settings database, and for obtaining information about the set of encryption settings definitions available in the server.
  • Updated the Server SDK to make it possible for a pre-parse bind plugin to convert a bind request from simple to SASL, or vice-versa. Added an example SASL mechanism handler that can be used to provide details of a successful or failed bind using attachments to an internal operation. Fixed an issue in the SASL bind result factory that could prevent a matched DN from being included in the response. Added the ability to include additional text in the access log message for an operation without having that text included in the response to the client.
  • Updated the Server SDK to provide support for access token validators for all types of products. It was previously only available for the Data Governance Server.
  • Improved the diagnostic message that the server returns when rejecting a proxied authorization attempt because the target account’s password policy state does not permit that user to authenticate.
  • Fixed an issue in which the server could incorrectly reject an attempt to change a user’s password in a single modify operation that included a delete modification with no values (indicating that all existing password values should be removed) followed by an add modification to supply the desired new password.
  • Fixed an issue that could cause an error when generating an encrypted LDIF export of a data set with a very large number of non-leaf entries. In such cases, the data is written to multiple files that are merged at the end of the process, but a problem could have prevented those files from being properly merged. This did not affect the usability or integrity of the exported data; it merely required the administrator to explicitly specify each of the files in the appropriate order when performing the import.
  • Fixed an issue in the access control handler in which it could incorrectly require the “export” and “import” rights for a modify DN request that includes a newSuperior that matches the DN of the entry’s current parent (which matches the behavior it exhibited for modify DN requests that did not include the newSuperior element). The export and import rights should only be required if the entry is being moved beneath a new parent.
  • Fixed an issue that could allow a modify operation to alter an entry in a way that left it without one or more of the superior object classes that it should have.
  • Fixed an issue in which changes to a dynamic group’s memberURL attribute sometimes did not take effect until after a restart.
  • Fixed an issue in which the server may not enter lockdown mode if it is missing replication changes that are no longer available in the topology, and if it has been restarted without addressing that problem.
  • Fixed an issue that could interfere with the operation of the stop-server.bat command on Windows systems configured with a locale that uses a comma instead of a period as the decimal separator.
  • Fixed issues that could interfere with the parsability of the periodic stats logger output when the server is run on systems configured with a locale that uses a comma instead of a period as the decimal separator.
  • Fixed an issue in which certain component initialization failure messages were written with a log level that was too low to prevent them from being recorded in the server’s error log by default, making it difficult to diagnose problems with those components.
  • Fixed the ordering of the consent-service-cfg.dsconfig batch commands so that bearer token authentication is enabled after the unprivileged consent on which it depends.
  • Fixed an issue that could cause a negative etime to appear in the access log when using assured replication.
  • Fixed an issue that could prevent dsreplication disable from removing replica IDs from the topology when one or more replication domains are disabled.
  • Fixed an issue that could cause the server to report an error when enabling or disabling a backend if there were any disabled notification managers defined in the server.
  • Fixed an issue in which the Directory Proxy Server could reject add attempts if all servers in an entry-balancing backend set had a health check state of DEGRADED or UNAVAILABLE.
  • Fixed an issue in which backups of the encryption settings database could be encrypted with a key from the encryption settings database.
  • Fixed an issue that could interfere with the ability to assign privileges via the mirror virtual attribute if the values to mirror were contained in another entry and were not accessible to unauthenticated clients.
  • Fixed an issue that could interfere with the ability to delete an entry containing uncached content if the LDAP changelog was enabled and configured to record changes in reversible form.
  • Fixed an issue that could prevent JMX clients from establishing SSL-encrypted connections.
  • Fixed an issue that could prevent HTTP-based connections from being associated with a client connection policy.
  • Fixed an issue in which a SCIM client was not permitted to add a member to a groupOfNames or groupOfEntries group.
  • Fixed an issue in which the startIndex value for a SCIM request could be incorrect if the server was configured with more than one base DN in the scim-resources.xml file.
  • Fixed an issue in which the config-diff tool may not identify differences that result from changing the order of values in an order-dependent property.
  • Fixed an issue in the Data Synchronization Server in which operational attributes may not be requested from an LDAP sync source if the LDAP filter was a nested filter.
  • Fixed an issue in the Data Synchronization Server in which a resync attempt could fail against Active Directory or PingOne for Customers when run with multiple passes.
  • Fixed an issue with the client-side validation properties that the haystack password validator would return in a get password quality requirements extended response. The values were human-readable descriptions of the validation properties rather than machine-parsable values.
  • Fixed an issue that could cause the server to encounter an internal error when processing a set subtree accessibility extended operation against an empty backend.
  • Fixed an issue in which a cryptographic error could interfere with inter-server authentication for sharing mirrored configuration data.
  • Fixed an installer issue in which the Admin Console’s trust store type could be set incorrectly if it was different from the key store type.
  • Disabled the fingerprint and subject attribute to user attribute certificate mappers by default for new installations (upgrades of existing installations will not be affected). These certificate mappers are rarely used and require the server to be configured with additional indexing before they can be used, and the lack of those indexes caused internal errors to be raised in the server on startup.

Managing Password Policy State in the Ping Identity Directory Server

The Ping Identity Directory Server offers a wealth of password policy functionality, and a lot of them require maintaining some kind of state information in the user’s entry. This includes things like:

  • The password policy by which the user is governed
  • The encoded passwords for the user
  • Whether the user’s account has been administratively disabled
  • When the user’s account will become active or will be deactivated
  • When the user’s password was last changed
  • When the user was first warned about an upcoming password expiration
  • Whether the user will be forced to change their password before being allowed to perform any other operations
  • A history of previous passwords for the user
  • Information about recent failed authentication attempts
  • Information about any grace logins used
  • The time the user last authenticated
  • The address of the client from which the user last authenticated
  • A retired password for the user

It’s often the case that an administrator application may want to obtain information about a user’s password policy state or to alter that state in some way. In this post, I’ll describe some of the options that the Ping Identity Directory Server provides to accomplish this.

Direct Manipulation of Operational Attributes

The password policy state for a user is maintained with operational attributes in the user’s entry, operating in conjunction with the password policy that governs that user. As such, you’d think that just altering the values of these attributes would be the best way to alter a user’s password policy state.

That is true for some of these password policy state attributes. The following attributes are supported for direct manipulation by applications and administrators:

  • ds-pwp-password-policy-dn — Specifies the DN of the configuration entry for the password policy that governs the user. If this is not specified, the user will be governed by the server’s default password policy. If it specifies the DN of an entry that does not exist or is not a password policy, then the user will not be permitted to authenticate.
  • ds-pwp-account-disabled — Indicates whether the user’s account is administratively disabled. If the attribute exists and has a value of TRUE, then the user account will be disabled and unable to authenticate. If the attribute is missing or has a value of FALSE, then the user account will not be considered disabled.
  • ds-pwp-account-expiration-time — Specifies a date and time (in generalized time format) that the user account will be considered expired and no longer able to authenticate. If this is not specified, the account will not expire. Note that account expiration is not the same as password expiration; account expiration is used for temporary accounts (e.g., for a contractor), whereas password expiration is used to require users to periodically change their passwords.
  • ds-pwp-account-activation-time — Specifies a date and time (in generalized time format) that the user account will become active. If this is specified, then the user will not be permitted to authenticate until after this time.

However, other operational attributes used to maintain password policy state are not directly writable by applications or administrator. These attribute type definitions are marked with the NO-USER-MODIFICATION constraint in the schema and are not considered part of the public interface that we expose. We may change the value format for these attributes, or even the attribute types, between releases without any prior warning. If you need to alter the password policy state in some other way, then you’ll need to use a different approach.

Resetting the User’s Password

There are several reasons that a user may not be allowed to authenticate. Some of them are directly controllable by an administrator using the operational attributes specified above. However, there are a number of other conditions that are not as directly controllable by administrators. These include:

  • The user’s password is expired
  • The user’s account has been locked because of too many failed authentication attempts
  • The user’s account has been locked because it has been too long since they last authenticated
  • The user’s account has been locked because they did not choose a new password soon enough after an administrative reset

Each of these conditions can be resolved by simply resetting the user’s password. Once the password has been reset, the account should immediately become usable.

Note that if the password is expired but the user still knows the right value, and if the allow-expired-password-changes property is set to true in the password policy that governs the user, then the user could change their own password using the password modify extended operation. This would presumably happen over an unauthenticated connection, but where the request includes the current password for the target user so it will be authorized as that user.

Also note that if the user’s account is only temporarily locked as a result of too many failed authentication attempts, then the user could just wait out the lockout specified by the lockout-duration property in the password policy. If they provide the correct password after the lockout duration has elapsed, they should be permitted to authenticate.

The Password Policy State Extended Operation

The password policy state extended operation is the Swiss Army knife of password policy state management in the Ping Identity Directory Server. Unlike the attributes that are used to actually store the information, this extended operation does provide a documented, stable, and supported interface for low-level manipulation of a user’s password policy state.

If you’re using the UnboundID LDAP SDK for Java, you can access this operation through the PasswordPolicyStateExtendedRequest, PasswordPolicyStateExtendedResult, and PasswordPolicyStateOperation classes, and the Javadoc for the request class has an example that demonstrates its use. If you’re using another API, then the Javadoc for the request class is still useful because it describes the OID and the value encoding for the operation.

Things that you can do with the password policy state extended operation include:

  • Retrieve the DN of the password policy that governs an account
  • Get, set, and clear the disabled state for an account
  • Get, set, and clear an account’s expiration time
  • Retrieve the length of time in seconds until an account will expire
  • Determine whether an account is expired
  • Get, set, and clear an account’s activation time
  • Retrieve the length of time in seconds until an account will become active
  • Determine whether an account is not yet active
  • Get, set, and clear the time that an account’s password was last changed
  • Determine whether an account’s password is currently expired
  • Retrieve the time that an account’s password will expire
  • Retrieve the length of time in seconds until an account’s password will expire
  • Retrieve the length of time in seconds until the account will be eligible to receive a warning about an upcoming password expiration
  • Get, set, and clear the time that an account was first warned about an upcoming password expiration
  • Get and set an account’s failure lockout state
  • Retrieve the time that an account was locked because of too many authentication failures
  • Get, update, set, and clear the set of authentication failure times for an account
  • Retrieve the length of time in seconds until a temporarily failure-locked account will be unlocked
  • Retrieve the number of failed authentication attempts until an account will be locked
  • Get, set, and clear an account’s last login time
  • Get, set, and clear an account’s last login IP address
  • Determine whether an account is currently locked because it has been too long since it last authenticated
  • Get the time that an account will be locked because it has been too long since it last authenticated
  • Retrieve the length of time in seconds until an account will be locked because it has been too long since it last authenticated
  • Get, set, and clear the “must change password” state for an account
  • Determine whether an account is currently locked because they failed to change their password in a timely manner after an administrative reset
  • Retrieve the time that an account was locked because they failed to change their password in a timely manner after an administrative reset
  • Retrieve the length of time in seconds until an account will be locked because they failed to change their password in a timely manner after an administrative reset
  • Get, update, set, and clear the set of grace login use times for an account
  • Retrieve the number of remaining grace logins for an account
  • Get, set, and clear the most recent “require change by time” value with which an account has complied
  • Retrieve the length of time in seconds that an account has to comply with a “require change by time” constraint in the password policy
  • Get the number of passwords in an account’s password history
  • Clear an account’s password history
  • Indicate whether an account has a retired password
  • Retrieve the time that an account’s former password was retired
  • Retrieve the time that an account’s retired password will stop being valid
  • Purge an account’s retired password
  • Retrieve a set of account usability errors, warnings, and notices
  • Determine whether an account is usable
  • Retrieves the set of SASL mechanisms that an account may use to authenticate
  • Retrieves the set of OTP delivery mechanisms that are available for an account
  • Determine whether an account has at least one TOTP shared secret
  • Add, remove, set, and clear the set of TOTP shared secrets for an account
  • Determine whether an account has at least one YubiKey OTP device registered
  • Get, update, set, and clear the public IDs of any YubiKey OTP devices that have been registered for an account
  • Determine whether an account has a static password set

The manage-account Command-Line Tool

While the password policy state extended operation is very powerful and flexible, you kind of need to write code to be able to use it. That’s fine if you’re writing an application that needs to be able to do this kind of thing, but not so much if you’re an administrator that just needs to update a user account. Fortunately, we offer a manage-account tool that gives you all of the functionality of the password policy state extended operation in a simple command-line utility.

This tool uses subcommands to indicate which password policy state functionality you want to invoke. The --helpSubcommands argument can be used to obtain a list of all of the available subcommands, but many of them are of the form “get-{property}”, “set-{property}”, or “clear-{property}”, like “get-account-is-disabled”, “set-account-is-disabled”, or “clear-account-is-disabled”. There’s also a “get-all” subcommand that displays the values of all password policy state attributes for a user.

The manage-account tool can operate on one or more entries, specifying them by DN (using the --targetDN or --dnInputFile arguments), by user ID (via the --targetUserID or --userIDInputFile arguments), or by an arbitrary filter (using the --targetFilter and --filterInputFile arguments). It can use multiple threads to process changes to multiple entries concurrently.

For example, to retrieve a list of all password policy state properties for a user, you might want to use a command like:

$ bin/manage-account --hostname ds.example.com \
     --port 636 \
     --useSSL \
     --bindDN uid=admin,dc=example,dc=com \
     --targetDN uid=test.user,ou=People,dc=example,dc=com
Enter the bind password:

dn: uid=test.user,ou=People,dc=example,dc=com
base-command-line: manage-account get-all --targetDN uid=test.user,ou=People,dc=example,dc=com
result-code: 0
result-code-name: success
get-password-policy-dn: cn=Default Password Policy,cn=Password Policies,cn=config
get-account-is-usable: true
get-account-usability-notice-messages:
get-account-usability-warning-messages:
get-account-usability-error-messages:
get-password-changed-time: 20190610044447.266Z
get-account-is-disabled: false
get-account-activation-time:
get-seconds-until-account-activation:
get-account-is-not-yet-active: false
get-account-expiration-time:
get-seconds-until-account-expiration:
get-account-is-expired: false
get-password-is-expired: false
get-password-expiration-time:
get-seconds-until-password-expiration:
get-password-expiration-warned-time:
get-seconds-until-password-expiration-warning:
get-account-is-failure-locked: false
get-failure-lockout-time:
get-seconds-until-authentication-failure-unlock:
get-authentication-failure-times:
get-remaining-authentication-failure-count:
get-must-change-password: false
get-account-is-password-reset-locked: false
get-password-reset-lockout-time:
get-seconds-until-password-reset-lockout:
get-account-is-idle-locked: false
get-idle-lockout-time:
get-seconds-until-idle-lockout:
get-last-login-time:
get-last-login-ip-address:
get-password-changed-by-required-time:
get-seconds-until-required-password-change-time:
get-password-history-count: 0
get-grace-login-use-times:
get-remaining-grace-login-count: 0
get-has-retired-password: false
get-password-retired-time:
get-retired-password-expiration-time:
get-available-sasl-mechanisms: EXTERNAL
get-available-sasl-mechanisms: PLAIN
get-available-sasl-mechanisms: UNBOUNDID-CERTIFICATE-PLUS-PASSWORD
get-available-sasl-mechanisms: UNBOUNDID-EXTERNALLY-PROCESSED-AUTHENTICATION
get-available-otp-delivery-mechanisms:
get-has-totp-shared-secret: false
get-has-registered-yubikey-public-id: false
get-registered-yubikey-public-ids:
get-has-static-password: true

Password Policy-Related Controls

We also provide support for a number of request and response controls that allow for interaction with a user’s password policy state. They include:

  • Account Usable Control — May be included in a search request to indicate that the server should include a corresponding response control with each matching entry that indicates whether the account has a password policy state that would allow that user to authenticate.
  • Get Password Policy State Issues Control — May be included in a bind request to indicate that the bind response should include a response control with information about any errors, warnings, or notices pertaining to a user’s password policy state.
  • Password Expired Control — May be returned in the response to a bind request if the target user has an expired password or must change their password before they will be permitted to request any other operation.
  • Password Expiring Control — May be returned in the response to a bind request if the target user’s password will expire in the near future.
  • Password Policy Control — May be included in an add, bind, compare, modify, and password modify requests to indicate that the server should return a response control with information about any potential error or warning related to the target user’s password policy state.
  • Password Update Behavior Control — May be included in an add, modify, or password modify request to customize the behavior that the server should use when setting a new password.
  • Password Validation Details Control — May be included in an add, modify, or password modify request to indicate that the server should return extended information about the quality of the proposed password and any issues that prevented it from being accepted.
  • Retire and Purge Password Controls — May be included in a modify or password modify request to indicate that the user’s former password should be explicitly retired (so that it can continue to be used for a brief period of time as an alternative to the new password) or purged.
  • Suppress Operational Attribute Update Control — May be included in a request to indicate that the server should suppress updates to one or more operational attributes (including last login time and last login IP address, which are normally controlled by the password policy) that may have otherwise been updated by the operation.

UnboundID LDAP SDK for Java 4.0.11

We have just released version 4.0.11 of the UnboundID LDAP SDK for Java. It is available for download from the releases page of our GitHub repository (https://github.com/pingidentity/ldapsdk/releases), from the Files page of our SourceForge repository (https://sourceforge.net/projects/ldap-sdk/files/), and from the Maven Central Repository (https://search.maven.org/search?q=g:com.unboundid%20AND%20a:unboundid-ldapsdk&core=gav).

The LDAP SDK release notes are available at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but the changes included in this release are as follows:

  • Updated the round-robin and fewest connections server sets so that they can temporarily blacklist a server that was found to be offline or unavailable. If an attempt to create a connection to a server fails, or if that connection is found to be unacceptable for some reason (e.g., it does not pass the associated health check), subsequent connection attempts will avoid that server until a background thread determines that it is available again. Blacklisted servers will still be tried as a last resort if it is not possible to get an acceptable connection to a non-blacklisted server. These server sets will now use the blacklist by default, but that can be disabled programmatically through the constructor or by setting a system property before creating the server set.
  • Updated the round-robin and fewest connections server sets to improve concurrency. In previous implementations, these sets could only create one connection at a time, which could limit the rate at which connection pools using them could establish new connections. This is no longer the case, and any number of threads will be able to create connections in parallel using the server sets. This change also updated the ServerSet API to make it possible for a server set to be notified whenever a connection created with that set has been closed.
  • Added a new SubtreeDeleter utility class that can make it easier to delete a specified subtree, optionally including or excluding the base entry for that subtree. It provides a good client-side alternative to the subtree delete request control, which isn’t supported by all servers and can sometimes be problematic in servers that do support it.
  • Added a new ldapdelete command-line tool that can be used to delete entries from an LDAP directory server. The DNs of the entries to delete can be provided on the command line, read from a file, or read from standard input. Alternately, the server can search for and delete all entries matching one or more filters. It offers a number of options, including support for client-side and server-side subtree deletes, rate limiting, and a variety of standard and proprietary controls.
  • Improved the LDAP SDK’s protection against socket write attempts that block for an indefinite length of time. This is only likely to occur when sending a large number of asynchronous requests over a connection, and only in the case that the server stops reading requests from the client or if a networking problem prevents the request from reaching the server and prevents the client from receiving any information about that failure.
  • Added InMemoryDirectoryServer.applyChangesFromLDIF methods that can be used to read LDIF change records and apply them to data in the server. The changes will be applied atomically, and if any of them cannot be applied successfully, then the server data will remain unchanged.
  • Updated the searchrate utility to allow specifying the base DN, scope, filter, and requested attributes using LDAP URLs rather than using separate arguments to provide appropriate values. The LDAP URL can be a fixed URL, or it can be a value pattern (including the ability to include variable content in the URLs or to load the URLs from a file). Using LDAP URLs allows for more precise control over the combination of base, scope, filter, and requested attributes on a per-request basis. Note that any addresses and ports used in the URLs will be ignored; the --hostname and --port arguments will still be used to identify which servers to use.
  • Updated the ldapsearch and ldapmodify command-line tools to use an unlimited response timeout, which will prevent the tool from giving up on an operation if it takes the server a long time to return any kind of response. Previously, the tools used the LDAP SDK’s default timeout of five minutes for searches and 30 seconds for add, delete, modify, and modify DN operations.
  • Updated the ldapmodify command-line tool to add a --clientSideSubtreeDleete argument that can be used to cause each delete operation to be converted to a client-side subtree delete operation, in which the tool will search for entries to delete and then delete them individually. This makes it easier to delete entries with subordinates on servers that either do not support the subtree delete request control or in which the client may not have permission to use that control.
  • Added a new indent-ldap-filter command-line tool that can help make it easier to visualize complex filters with a lot of components, and especially a lot of nesting. If possible, it can also try to simplify the filter (for example, to remove unnecessary levels of nesting, like an AND inside an AND).
  • Enabled concurrent socket factory use by default for all versions of Java. In the past, we have observed that at least some IBM JVMs had a thread safety issue with SSL socket factory implementations, so we only allowed a socket factory to be used concurrently by multiple threads on a whitelisted set of JVMs. We no longer believe that the IBM JDK socket factory thread safety is an issue, and there are now many more JVM vendors (e.g., Apple, Azul, Amazon Coretto, AdoptOpenJDK, and potentially Red Hat), so concurrent socket factory use will be enabled by default. If an issue is found on a particular JVM, then concurrent access can be disabled programmatically or with a system property.
  • Updated the LDAPCommandLineTool API to add an option to expose an --enableSSLDebugging argument. If this argument is available, and if it is provided in the set of command-line arguments when the tool is run, then the JVM’s SSL/TLS debugging support will be enabled, and the JVM will write a large amount of TLS-related debugging information to standard error. This can help troubleshoot problems with or provide detailed information about any TLS communication that the tool attempts.
  • Updated the LDAP SDK to add protection against JVM security managers that may prevent calls to certain methods, like attempts to interact with system properties, environment variables, or logger levels.
  • Updated the password reader so that it will generate a more user-friendly error message if it is run in a context in which no console is available. A tool could encounter this error if its output has been redirected, or if it’s not running in an interactive shell (for example, in a cron job or system startup script).
  • Dramatically improved the performance of the streamfile value pattern, which operates like the sequentialfile value pattern in that it can iterate through values in sequential order, except that streamfile doesn’t need to hold the whole file in memory at once whereas sequentialfile does.
  • Updated the Filter.simplifyFilter method to simplify an AND filter containing an LDAP false filter (an OR filter with zero components, which will never match anything) to just that LDAP false filter, and to simplify an OR filter containing an LDAP true filter (an AND filter with zero components, which will match any entry) to just that LDAP true filter.
  • Added a PasswordValidationDetailsResponseControl.get(LDAPException) method that makes it more convenient to get the response control from an unsuccessful operation.
  • Improved the exception message that is generated if a failure occurs while trying to create a TLS-based connection. If the JVM supports creating an unconnected SSLSocket and then connecting it after the fact (which makes it possible to specify a connect timeout), and that connection attempt failed (for example, because the client did not trust the certificate presented by the server), the LDAP SDK could think that the connection was still established. Subsequent attempts to use the connection would fail, but the failure message would not accurately reflect the true cause of the problem.
  • Updated the in-memory directory server to improve the diagnostic message that is returned when it rejects an add attempt because the provided entry is not within any of the configured base DNs.
  • Fixed an issue in generating the normalized representation of a multivalued RDN when one or more of those components referenced an attribute type by its OID or by a name other than the first one listed in the attribute type definition. Previously, the normalized string representation would have simply used an all-lowercase representation of the provided attribute name, but it will now use an all-lowercase representation of the primary name for that attribute (if schema information is available to the client). Also, updated the logic used to determine whether an RDN has a specified name or name-value pair to handle the use of alternate names, and exposed the RDN.getNameValuePairs method to make it easier to work with an RDN’s name-value pairs.
  • Fixed a bug in the ByteStringBuffer.append(CharSequence,int,int) method in which the final integer argument could be interpreted as the number of characters to append rather than the end position at which to stop appending, which could yield incorrect results when the method was called with a nonzero start position. Also, updated the ByteStringBuffer.append methods that take CharSequence arguments to eliminate the creation of an intermediate character array, thereby improving performance and reducing garbage creation.
  • Updated the LDAP SDK’s command-line tool framework to fix an issue with the tool’s validation for required, exclusive, and dependent argument sets. If an argument was configured with a default value, then that default value could have been mistakenly treated as if it had been explicitly provided by the user. This could cause problems for arguments that are part of an exclusive argument set (in which only one of the arguments in that set may be provided) or a dependent argument set (in which an argument can only be used if at least one of a specified set of additional arguments is present). In such cases, the tool could not have been used in interactive mode. The modrate tool was affected by this issue.
  • Updated the argument parser to fix a problem with the way that it handles backslash characters in argument property files. Previously, it only correctly handled backslashes if they were at the end of a line to indicate that the content continued to the next line, or if they were followed by the letter ‘u’ and the hexadecimal representation of the desired Unicode character. It did not handle the backslash in front of another character used to force that character to be treated as a literal (for example, a backslash followed by an equal sign should be treated as just an equal sign, but was instead being treated as a backslash followed by an equal sign).