UnboundID LDAP SDK for Java 3.0.0

We have just released the 3.0.0 version of the UnboundID LDAP SDK for Java. It is available for download via the website or from GitHub. There are a few pretty significant announcements to accompany this release:

  • The Commercial Edition of the LDAP SDK is now open source under the GPLv2 and LGPLv2.1 licenses. The Commercial Edition contains everything in the Standard Edition, plus a lot of additional functionality that is specifically intended for use in interacting with UnboundID server products.

  • The source code and packaged releases are now available on GitHub at We will continue to maintain the repository, mailing lists, and discussion forum at SourceForge, but GitHub is now the recommended public repository for the LDAP SDK source code. Both public repositories now contain the Commercial Edition code along with the code for the Standard Edition and the Minimal Edition.

  • The Commercial Edition and Minimal Edition releases of the LDAP SDK are now in the Maven Central Repository. Both have a GroupId of "com.unboundid". The Commercial Edition has an ArtifactId of "unboundid-ldapsdk-commercial-edition", and the Minimal Edition has an ArtifactId of "unboundid-ldapsdk-minimal-edition". Previously, only the Standard Edition was available (GroupId "com.unboundid" and ArtifactId "unboundid-ldapsdk").

The following additional features, bug fixes, and enhancements are also included in this release:

  • The LDAP SDK now supports a JSON-based configuration syntax that can be used to specify a number of properties used to create LDAP connections and connection pools. It can include information about which servers to use (and if there are multiple servers, how to choose between them), how to authenticate (via simple authentication or several SASL mechanisms), how to secure the communication, and a number of other properties.

  • You can now manually invoke a synchronous health check against a connection pool, optionally with a different health check mechanism than is configured for the pool.

  • Improved the mechanism used to enforce a connect timeout. If a timeout occurs, it may be possible to close the associated socket and terminate the background connect thread more quickly.

  • You can now specify an alternate certificate key and/or trust store format (e.g., PKCS12 rather than the default of JKS) when launching the in-memory directory server from the command line.

  • There is improved support for command-line argument parsing, including support for arguments that provide information about LDAP controls, and better support for validating common argument formats.

  • Update the default settings for LDAP connection pools to eliminate the potential for the pool to block for up to five seconds if a connection is needed but none is immediately available.

  • When using value patterns (as in tools like searchrate, modrate, authrate, etc.), it is now possible to provide a path to a file whose lines should be accessed in sequential order. It was previously only possible to access file contents in random order.

  • The identify-unique-attribute-conflicts example tool now supports an optional filter. If provided, the tool will only report conflicts in entries matching that filter.

  • Ensure that connection pool statistics are properly updated to reflect connections closed as a result of a health check failure.

  • Fix a bug that could prevent the LDIF parser from using the correct matching rule for attributes if it is provided with access to an LDAP schema.

  • Fix a null pointer exception that could be thrown when attempting to retrieve the set of required or optional attributes from an object class definition if the associated schema is missing definitions for any of the superior object classes.

  • The Commercial Edition of the LDAP SDK has been updated with support for a number of new controls and extended operations, a filter syntax for searching inside attribute values that represent JSON objects, and other enhancements.


The New and a New LDAP SDK Release

Today, UnboundID is unveiling a new website, in addition to a revamp of the company's main site. is the new home for the UnboundID LDAP SDK for Java, but it's also intended to be a general resource for all things LDAP. It includes information about many other LDAP APIs for a wide range of programming languages, as well as a number of commercial and open source LDAP server offerings. has a lot of information about LDAP, including in-depth descriptions of protocol operations, key data structures like distinguished names and search filters, the LDIF format, and a glossary of LDAP terms. It also provides a pretty comprehensive list of LDAP specifications and reference documents, including RFCs and IETF drafts, as well as result code and OID references.

We're also releasing a new 2.3.8 version of the UnboundID LDAP SDK for Java. This is a minor release with only a couple of feature enhancements and bug fixes, including:

  • We've added a new Filter.simplifyFilter method that can be used to rearrange search filters so that they can be better optimized and processed more efficiently by many directory servers. This primarily involves simplification of the elements inside AND and OR filters, like removing unnecessary nesting (e.g., if an AND filter is nested inside another AND filter, then the elements inside the inner AND filter are moved into the outer filter), getting rid of duplicate elements, and replacing an AND or OR filters containing a single element with just that element. You can optionally re-order the elements inside an AND or an OR filter in a way that will make elements that are generally more efficient to process come before those that are generally less efficient to parse.

  • We've added a utility class for working with and comparing object identifiers (OIDs).

  • We fixed a thread-safety bug in the in-memory directory server.

  • The LDAP SDK document now contains information about a number of LDAP-related specifications defined in RFCs and Internet Drafts, as well as result code and OID reference documents.

The new 2.3.8 release of the LDAP SDK is available for download on or from the SourceForge project page. It's also available in the Maven Central Repository.


UnboundID LDAP SDK for Java 2.3.7

We have just released the 2.3.7 version of the UnboundID LDAP SDK for Java. You can get the latest release online at the UnboundID Website, the SourceForge project page, or in the Maven Central Repository.

Complete release note information is available online at on the UnboundID website, but some of the most significant changes include:

  • Updated the logic used to select the TLS protocols to use for secure communication. SSLv3 is now disabled by default in response to the recent POODLE bug. On IBM JVMs, the set of enabled TLS protocols should be more broadly compatible with earlier TLS versions when support for TLSv1.1 or TLSv1.2 is enabled.

  • Added the ability to perform improved SSLSocket validation, which makes it possible to perform certificate hostname validation in a more secure and convenient manner than was previously available. It is also now possible to get access to the SSL session associated with a connection secured via SSL/TLS or StartTLS.

  • Added a new server set that can work in a DNS round-robin configuration, in which multiple IP addresses are associated with the same resolvable name.

  • Added an LDAPConnectionPool.shrinkPool method that can be used to reduce the number of currently-available connections to a specified number.

  • Improved support for class inheritance in the LDAP SDK persistence framework. If one class marked with @LDAPObject is a subclass of another class marked with @LDAPObject, then the logic used to construct the entry's DN for instances of the subclass may be inherited from the superclass. Also, DN fields and entry fields will be properly handled in subclasses, and improvements have been made in requesting specific attributes to include in search result entries.

  • Added a new interceptor API to the in-memory directory server. This API can be used to alter or reject an LDAP request before it is processed by the server, to alter or suppress search result entries or references, and to alter LDAP results before they are returned to the client.

  • Updated the searchrate, modrate, authrate, and search-and-mod-rate tools to support altering the rate at which they process operations over time. Also, update these tools to make it possible to programmatically interrupt their processing.

  • Improved support for automatic referral following and auto-reconnect to ensure that the newly-established connection will properly use StartTLS if the original connection had successfully used StartTLS to secure its communication.

  • Fixed a bug in the Entry.applyModifications method that could cause valid modifications to be rejected if those modifications targeted attributes used in the entry's DN but would not actually have resulted in a change to the entry DN.

  • Fixed a bug in the Entry.diff method in which, if provided with a specific set of attributes to examine, the method would not examine variants of those attributes containing attribute options.

  • Fixed a potential null pointer exception that could arise as a result of a race condition in the course of closing a connection. Fixed a potential illegal argument exception that could arise when closing a connection pool if multiple concurrent threads were used to close the connections but no connections were currently available in the pool.


UnboundID LDAP SDK for Java 2.3.6

We have just released the 2.3.6 version of the UnboundID LDAP SDK for Java. You can get the latest release online at the UnboundID Website or the SourceForge project page, and it's also available in the Maven Central Repository.

This is primarily a maintenance release, containing bug fixes and some minor enhancements over the 2.3.5 version. A fully copy of the release notes for this version may be found on the UnboundID website, but some of the most notable changes include:

  • It is now possible to create a connection pool with a health check, without the need to set the health check after the pool has been created. The primary benefit of this approach is that the health check will be used for the initial set of connections that are established when the pool is created.

  • The LDIF change record implementations have been updated to add support for change records that include request controls.

  • Update the GSSAPI and DIGEST-MD5 SASL bind requests to support the use of the integrity and confidentiality quality of protection modes.

  • Improve support for processing asynchronous operations so that it is possible to invoke an asynchronous add, compare, delete, modify, or modify DN operation without needing to provide a result listener if the result will be accessed using the Future API. Also update the connection pool to make it possible to invoke multiple add, compare, delete, modify, modify DN, and/or search operations concurrently over the same connection as asynchronous operations.

  • Ensure that the thread-local connection pool uses the LDAPConnection.isConnected method as further verification that a connection is still established before attempting to use it.

  • Fix a bug in the in-memory directory server that prevented the updated values of certain attributes (e.g., modifiersName and modifyTimestamp) from appearing in the entry returned in a post-read response control.

  • Fix a potential thread safety bug in the get entry connection pool health check.


UnboundID LDAP SDK for Java 2.3.5

We have just released the 2.3.5 version of the UnboundID LDAP SDK for Java. You can get the latest release online at the UnboundID website or the SourceForge project page, and it's also available in the Maven Central Repository.

There are a lot of improvements in this release over the 2.3.4 version. A full copy of the release notes for this version may be found on the UnboundID website, but many of the improvements are related to connection pooling, load balancing, and failover, but there are other additions and a number of bug fixes also included in this release. Some of the most notable changes include:

  • Added a new fewest connections server set. If used to create a connection pool in which connections span multiple servers, the pool will try to send each newly-created connection to the server with the fewest number of active connections already open by that server set.

  • Updated the LDAPConnectionPool class to make it possible to specify an alternate maximum connection age that should be used for connections created to replace a defunct connection. In the event that a directory server goes down and pooled connections are shifted to other servers, this can help connections fail back more quickly.

  • Updated the failover server set to make it possible to specify an alternate maximum connection age for pooled connections that are established to a server other than the most-preferred server. This can help ensure that failover connections are able to fail back more quickly when the most-preferred server becomes available again.

  • Added a new version of the LDAPConnectionPool.getConnection method that can be used to request a connection to a specific server (based on address and port), if such a connection is readily available.

  • Added a new LDAPConnectionPool.discardConnection method that can be used to close a connection that had been checked out from the pool without creating a new connection in its place. This can be used to reduce the size of the pool if desired.

  • Added a new LDAPConnection.getLastCommunicationTime method that can be used to determine the time that the connection was last used to send a request to or read a response from the directory server, and by extension, the length of time that connection has been idle.

  • Updated the connection pool so that by default, connections which have reached their maximum age will only be closed and replaced by the background health check thread. Previously, the LDAP SDK would also check the connection age when a connection was released back to the pool (and this option is still available if desired), which could cause excess load against the directory server as a result of a number of connections being closed and re-established concurrently. Further, checking the maximum connection age at the time the connection is released back to the pool could have an adverse impact on the perceived response time for an operation because in some cases the LDAP SDK could close and re-establish the connection before the result of the previous operation was made available to the caller.

  • Updated the LDIF writer to add the ability to write the version header at the top of an LDIF file, to ensure that modify change records include a trailing dash after the last change in accordance with the LDIF specification, and to fix a bug that could cause it to behave incorrectly when configured with an LDIF writer entry translator that created a new entry as opposed to updating the entry that was provided to it.

  • Dramatically improved examples included in the Javadoc documentation. All of these examples now have unit test coverage to ensure that the code is valid, and many of the examples now reflect a more real-world usage.

  • Improved the quality of error messages that may be returned for operations that fail as a result of a client-side timeout, or for certain kinds of SASL authentication failures. Also improved the ability to perform low-level debugging for responses received on connections operating in synchronous mode.

  • Updated the in-memory directory server to support enforcing a maximum size limit for searches.

  • Added a couple of example tools that can be used to find supposedly-unique attribute values which appear in multiple entries, or to find entries with DN references to other entries that don't exist.

  • Made a number of improvements around the ability to establish SSL-based connections, or to secure existing insecure connections via StartTLS. Improvements include making it possible to specify the default SSL protocol via a system property so that no code change may be required to set a different default protocol, allowing the ability to define a timeout for StartTLS processing as part of the process for establishing a StartTLS-protected connection.

  • Fixed a bug that could cause the LDAP SDK to enter an infinite loop when attempting to read data from a malformed intermediate response.

  • Fixed a bug that could cause problems in handling the string representation of a search filter that contained non-UTF-8 data.


UnboundID LDAP SDK for Java 2.3.4

We have just released the 2.3.4 version of the UnboundID LDAP SDK for Java. You can get the latest release online at the UnboundID website or the SourceForge project page, and it's also available in the Maven Central Repository.

The main reason for this release is the disclosure of a security vulnerability (VU#225657) that affects the Oracle Javadoc tool and all Javadoc content generated with affected versions of that tool. This included Javadoc documentation included as part of earlier versions of the UnboundID LDAP SDK for Java. The 2.3.4 release of the LDAP SDK has been generated with an updated version of the Javadoc tool that should no longer be vulnerable to the referenced bug.

There are a few other updates in this release, including:

  • We have fixed a bug that could cause a pooled connection to be unnecessarily closed and re-established when performing a simple bind on a connection operating in synchronous mode.

  • We have fixed a bug in the schema parser that could prevent it from parsing certain schema elements from their string representations if the last element in those elements was an OBSOLETE, SINGLE-VALUE, or NO-USER-MODIFICATION token and there was no space between that token and the closing parenthesis that followed it.

  • We have updated the disconnect handler mechanism to provide more assurance that there would not be multiple notifications for a single disconnect.

  • We have added support for the Microsoft DirSync control, which may be used to discover information about changes processed in an Active Directory server.

  • We have fixed a bug in the entry validator (and the validate-ldif tool that uses the entry validator) that could incorrectly classify entries that had multiple structural object classes as entries that did not have any structural class.

  • We have updated the LDAP command-line tool API to make it possible to create tools that support establishing LDAP connections but without offering options to authenticate those connections. We have also updated the API to make it possible to provide passwords to the tool by interactively prompting for them rather than requiring them to be provided as command line arguments or included in clear-text files on the filesystem.


UnboundID LDAP SDK for Java 2.3.3

We have just released the 2.3.3 version of the UnboundID LDAP SDK for Java, with a number of improvements and bug fixes over the 2.3.1 release (NOTE: the only difference between the 2.3.2 and 2.3.3 releases is a fix to a javadoc formatting problem). You can get the latest release online at the UnboundID website or the SourceForge project page, and it's also available in the Maven Central Repository.

As usual, the release notes provide a complete overview of changes made in this release, but some of the most significant updates include:

  • A number of connection pooling improvements and fixes, including: It is now possible to create a connection pool even if a failure is encountered while establishing the initial set of connections, which is useful for cases in which the target directory server is unavailable when the application is starting. You can establish and/or close connections in parallel, which helps speed things up if the pool has a lot of connections or the server is remote or otherwise slow to respond. Pooled connections that cache server schema information are established more quickly. Methods have been added to help undo the effects of processing a bind on a pooled connection so that connections stay authenticated as the account used when they were initially established.

  • A number of persistence framework improvements and fixes, including: The default object encoder now provides generic support for Serialized objects. A new getAll method makes it possible to retrieve all objects of a specified type below a given base DN. Fix a bug related to generating an appropriate set of modifications for an updated object, and for generating filters to define criteria to use when searching for objects. Improve the output of the generate-schema-from-source tool.

  • A number of In-Memory Directory Server and LDAP listener improvements and fixes, including: It is now possible to combine multiple schema files to create the schema for the in-memory directory server. The canned response request handler now has the ability to customize the entries and references to return for a search operation. The LDAP debugger tool now has the ability to accept SSL-based connections.

  • A number of LDIF-related improvements and fixes, including: Add an LDIFWriterEntryTranslator interface that can make it easier to transform entries to be written to LDIF. Fix a bug that could cause problems reading LDIF records with comments that have been wrapped across multiple lines. Add a convenience method to get the entry to be added from an LDIF add change record (whereas previously it was only possible to get the DN and attributes separately).

  • A number of tool-related improvements and fixes, including: Add a new multi-server command-line tool API which makes it easier to create tools that need to interact with multiple directory servers. Make it easier to register JVM a shutdown hook to invoke code when the JVM in which the tool is running begins shutting down.

  • Add the ability to specify the default SSL/TLS protocol version when creating secure connections (or using StartTLS) for cases in which the caller doesn't explicitly specify a protocol.

  • Dramatically improve the performance of the Attribute equals method for attributes that have a large number of values.


How LinkedIn Missed Out

Within the last week, LinkedIn, eHarmony, and have all announced security breaches that resulted in millions of user passwords exposed to the world. While the passwords were encoded with one-way digests, that didn't stop attackers from discovering the clear-text passwords for a large percentage of those accounts.

There's no such thing as a perfectly secure system, and brilliant and determined hackers have a lot of tricks up their sleeve, from technical assaults like exploiting unpatched software vulnerabilities and to social engineering cons like sweet-talking secretaries. But there are a lot of things that LinkedIn and the others should have done to help prevent this kind of breach.

Consider Using Third-Party Authentication

The best way to ensure that attackers can't break into your system and steal user passwords is for your system to not have any user passwords. Authentication systems like OpenID and OAuth allow you to push the responsibility for authenticating users (and securing their accounts) to a third party. If you're willing to leave the authentication to an organization like Google, Facebook, or Yahoo, and your users are willing to accept this solution, then you don't need to worry about storing credentials at all.

Note, however, that passwords may not be the only sensitive information that you need to store in your system. In fact, attackers generally don't care about user passwords themselves but rather the other information about users that passwords can be used to access. As a result, you should treat all the information that you store about users with the utmost care and sensitivity because any compromise of your system will be bad for both your users and your reputation, regardless of whether that compromise includes login credentials.

It is therefore important that you store your data in a repository that offers the kinds of security features you need to help ensure it is adequately protected. The UnboundID Directory Server offers a wide range of security features, including several that you won't be able to find in other products. Some of these features are primarily intended to help secure user passwords, but many can be applied for all kinds of information.

Use Salted Password Hashes

The people who designed the security systems at these companies knew enough to use cryptographic digests (also called hashing algorithms) to protect the passwords. These are mathematical algorithms that transform passwords in a way that is believed to be impossible to reverse. Good cryptographic digests (like the SHA-1 algorithm used by LinkedIn) offer a good level of protection because they prevent attackers from knowing useful information like how long a password is or what kinds of characters it might contain, and if they're guessing passwords then they won't be able to tell how close any guess is to being right.

But one of LinkedIn's big mistakes is that they didn't salt their passwords. One-way digest algorithms always generate exactly the same hash for a given input. This is essential for their use in applications like protecting passwords and verifying data integrity, but it also means that attackers can (and do) prepare ahead of time. I may not be able to look at the string "6367c48dd193d56ea7b0baad25b19455e529f5ee" and know that it's the SHA-1 digest for the string "abc123", but if I have a big dictionary of commonly-used passwords, I can just run each of the strings in that dictionary through the SHA-1 digest in order to get the encoded representation, and when I find an encoded password that looks like "6367c48dd193d56ea7b0baad25b19455e529f5ee", I can use my precomputed dictionary to do a reverse lookup and know that represents the password "abc123".

Password salting prevents this kind of attack because it adds a random element into each encoded password. When you're going to create a salted password, you first come up with some random data (for example, "kMPsCwaT") and prepend it to the clear-text password (like "kMPsCwaTabc123"). Then, you run that through the digest algorithm (to get a hash like "51c4125fe2e2e94bdefa8f7a8e5c12ebfd94833b"), and finally prepend the salt to the hash (e.g., "kMPsCwaT51c4125fe2e2e94bdefa8f7a8e5c12ebfd94833b"). When a user is authenticating, it then becomes necessary to pull the salt off the encoded password and prepend that to the clear-text password that they provide before running it through the digest algorithm.

Because salted passwords contain random data, it's not possible for an attacker to have a dictionary prepared in advance. Running through a dictionary (or using a brute-force approach to try every possible combination of characters) will take a lot longer to crack a password, and even if you are successful for one user, that won't help for any other user even if they chose the same password because it will have a different salt and therefore a different encoded representation.

The UnboundID Directory Server supports password salting out of the box in a manner that is completely transparent to clients. It can be used in conjunction with MD5, SHA-1, and any of the 256-bit, 384-bit, and 512-bit SHA-2 variants. It's on by default, and would have made it a lot harder (or at least taken a lot longer) for attackers to discover the clear-text representations of the stolen passwords.

Use Expensive Encoding Algorithms

If someone gets access to an encoded password and knows how it was encoded, then there really is no way to prevent them from discovering the clear-text password used to generate that hash. If they want it bad enough, they can simply try every possible combination of characters, and with relatively cheap access to distributed computing, it's possible to generate trillions of hashes per second. The only variables that affect this are the strength of the password (as will be discussed below), and the algorithm used to generate its encoded representation. For example, using the 512-bit SHA-2 instead of the 160-bit SHA-1 just about doubles the length of time required to generate a digest, which in turn means that it just about doubles the length of time an attacker will have to spend trying to crack a password.

To make the process even more expensive, you can have your password encoding process use multiple rounds of hashing. For example, take the clear-text password, salt it, and run that through the digest algorithm. Then take the resulting hash and run it through the digest algorithm again. And again. Repeat this process so that the final encoded password requires 5000 hashes. If you're using 512-bit SHA-2, then this process is now about ten thousand times more expensive than the simple SHA-1 process used for the leaked passwords, meaning that it will take an attacker ten thousand times longer to crack a password with this encoding scheme than with SHA-1.

The UnboundID Directory Server provides support for password encoding algorithms that employ thousands (or potentially even millions, if you're really paranoid) of rounds of hashing using the 256-bit or 512-bit SHA-2 algorithms. This algorithm is already available for use in holding login passwords for many Linux and UNIX systems, so it's been designed by and carefully scrutinized by many security experts and is considered extremely strong.

Reject Weak Passwords

If an attacker obtains an encoded password, then the biggest risk of that password being cracked comes from the strength of the password itself. A password that is a word from the dictionary or a name or date or other common string will almost certainly be broken in a fraction of a second. If a password is relatively short, then so also will be the time required to discover it even if it's necessary to try every possible combination of characters. For example, if a beefy system can generate 100 billion hashes per second, then it will only take about two seconds to try every possible combination of eight lowercase ASCII letters.

The two biggest factors in password complexity are the length of the password and the set of possible characters it may contain (which we'll call the password alphabet), and they're related by the mathematical formula al, where a represents the size of the password alphabet and l is the length of the password. For example, if the alphabet is the set of lowercase ASCII letters and the length is eight characters, then there are 268 = 208,827,064,576 possible password combinations (which seems like a big number, until you realize how fast computers are at performing these computations). However, if you instead consider both uppercase and lowercase letters, numeric digits, and a number of symbols, then the alphabet can grow to about 95 characters, and there would then be 958 = 6,634,204,312,890,625 possible values, which is nearly 32,000 times larger and would take the better part of a day to crack on a system capable of trying a hundred billion passwords per second. And increasing the length to ten characters takes the time to crack from a little over eighteen hours to a little over eighteen years.

The best way to ensure that users have strong passwords is to configure your system to enforce restrictions around password length, the kinds of characters that may be used, and other kinds of constraints. The UnboundID Directory Server ships with support for a number of password validators, including:

  • A dictionary validator, which can be used to ensure that users aren't allowed to supply passwords that exist in a given dictionary file (optionally including testing the reversed password).
  • A length validator, which can be used to ensure that users aren't allowed to choose a password that is too short (or potentially too long, although there's little reason to configure a maximum length).
  • A character set validator, which can be used to ensure that passwords include at least a specified minimum number of characters from a number of different character sets.
  • A unique characters validator, which can be used to ensure that passwords contain at least a specified number of different characters.
  • A repeated characters validator, which can be used to ensure that passwords don't contain repeated strings.
  • An attribute value validator, which can be used to ensure that the supplied password does not match the value of any other attribute in the user's entry.
  • A regular expression validator, which can be used to ensure that the supplied password matches (or alternately, does not match) a given regular expression.
  • A similarity validator, which can be used to ensure that when a user is changing his or her password, the new password is not too similar to the previous password.

In addition, the UnboundID Server SDK can be used to develop additional custom password validators if those provided with the server by default are not sufficient. It also provides a password history feature that can prevent users from repeatedly using the same set of passwords.

When allowing users to choose their passwords, it is also important to ensure that those passwords are always supplied in clear-text. Some systems allow users to provide the password in a form that is already encoded in a manner that the server can interpret. This is undesirable, because if a user is allowed to supply a pre-encoded password, then the server has no idea what the clear-text representation is, and therefore cannot determine whether it satisfies all of the configured password quality requirements.

Of course, strong passwords aren't much good if users can't remember them. This is a very real problem that needs to be considered, and it is compounded by the fact that your users will likely need to have accounts in other systems. In reality, this means that users will probably choose one of the following options:

  • They will use a password manager that automatically keeps track of all the usernames and passwords they use across all systems they access. This is the best solution, and one that you should probably recommend, since it means that they only have to remember one password for the password manager, and let it remember all the others. Unfortunately, less experienced users may find this prospect kind of scary.
  • Write their passwords down or keep them in a file. This is kind of the low-tech version of a password manager, and as long as all copies of the password list is protected, then it's reasonably safe.
  • Use the same password (or a small set of passwords) for all sites they access. This is dangerous, because if their password is compromised on one site, then it may be used to gain access to other sites. There's not much that can be done to prevent this (other than requiring multifactor authentication), but unless it's an account that has elevated privileges, it will be more likely to adversely affect that one user than the overall security of your data store.
  • Forget the password they chose and rely on the "I forgot my password" mechanism to reset it each time they need to access your system. If the reset process is automated and requires them to receive an e-mail or SMS message, then it may be a relatively secure approach (assuming that the e-mail address and/or phone number were previously verified), but if it involves talking to a human then it will probably raise your support costs and may allow a skilled social engineer to convince the support personnel to grant them access to someone else's account.

It is unfortunate that non-technical users will be the ones who find strong password requirements to be the most onerous and unpleasant, but it is important to decide whether end user convenience is more important than end user security.

Prevent Online Access to Passwords

While it isn't clear exactly how the attackers were able to obtain these large lists of encoded passwords, it's likely that they were able to manipulating the identity store (or an application using it) into performing a query that exposed this information to the requester. For example, if they were using a relational database, then maybe they discovered a flaw in an application that allowed for an SQL injection.

Identity data stores (whether relational databases, LDAP directory servers, or some other kind of repository) should be like roach motels for passwords: passwords can go in, but they can't come out. It shouldn't be possible for even an all-powerful user to perform a query that can retrieve password information, and the system should also require that all passwords supplied to it (whether validating credentials during authentication or supplying a new password) be processed over a secure communication channel so that anyone with the ability to observe the network traffic cannot examine it in order to learn passwords.

The UnboundID Directory Server includes a sensitive attributes feature that makes it possible do exactly this for passwords and other kinds of sensitive information. You can easily configure the server so that passwords will be stripped from results even for requests from root users, and to require that any operations attempting to manipulate the values of such attributes will be allowed only over a secure connection. It is possible to configure this restriction to be in effect across the server, but it is also possible to tailor the behavior to the requester (based on a number of characteristics, like who's asking, how they're authenticated, where they're coming from, whether the connection is secure, etc.), so that if there is an application that does have a legitimate need to be able to retrieve this information, the server can be configured to only return the data to that application.

The UnboundID Directory Server also includes very powerful and flexible logging capabilities, and it is possible to configure the server to log information about any operation in which passwords (or other attributes which may contain sensitive data) is returned to the client. This can be useful for auditing purposes so that if an attacker is somehow able to issue a query that returns sensitive information, you can see exactly which entries and which attributes were accessed.

Encrypt Server Data, Including Backups and Data Exports

Even if they weren't able to get the data store to expose the passwords via a network request, it's possible that they were able to get the password data in some other way. For example, if they were able to obtain access to the system on which the data was stored, then perhaps they were able to examine the database files directly, or perhaps they were able to obtain a backup or export of the data that included passwords.

It is important to ensure that adequate protection is in place for all copies of the server data, whether on the live running system or in backups. Certainly this includes things like restricting access to systems which can access this information and ensuring that only authorized users are able to access the data files, but it is also recommended that you encrypt such information so that even if an attacker does gain access to it, they won't be able to extract anything useful from it.

The UnboundID Directory Server makes it easy to enable encryption for all data so that it is never stored in the clear. It also provides the ability to encrypt backups and LDIF exports so that the information is protected in these forms as well.

Prevent Repeated Authentication Attempts

If you have adequately protected your system to prevent retrieving passwords from the data store, and if all copies of the data are encrypted, then attackers should be prevented from obtaining encoded passwords for users. However, there may be other ways to crack user passwords. The most common of these approaches is simply to try to repeatedly authenticate as that user with different passwords until you finally get it right. This will be much slower than the offline attacks that are available with access to encoded passwords, but given enough time, determination, and luck, it may just work. Of course, these kinds of attacks can be thwarted by limiting the number of unsuccessful authentication attempts that will be allowed for a user account before that account is locked.

The UnboundID Directory Server can be configured to lock accounts after too many authentication failures so that any subsequent attempts will fail even if the right credentials are given. This lockout can be either temporary (so that additional login attempts will be allowed after a specified period of time) or permanent (so that the user will not be allowed to authenticate at all until an administrator resets the password). It can also be configured to log and/or notify administrators when an account is locked as a result of failures, along with a number of other significant password policy events.

Enforce Authentication Restrictions

In many environments, it is common for each application to have its own account that will be used to perform operations in the server, and that application account may have more rights than normal user accounts. If an attacker is able to compromise an application account, then he or she may be able to wreak more havoc than with other user accounts.

To help prevent this, it is advisable to restrict application accounts so that they are less likely to be useful to attackers even if their credentials are discovered. For example, you may want to restrict their use to a certain range of IP addresses and/or to only allow them to authenticate in certain ways. The UnboundID Directory Server provides a number of features like this, including restrictions based on client address, authentication type, and communication security, as well as restrictions around the use of proxied authorization. In addition, client connection policies can also be used to permit or restrict operations based on a number of characteristics about the client.

Support Multifactor Authentication

One great way to mitigate the risk of compromised passwords is to make use of multifactor authentication, which require the user to provide multiple pieces of information to confirm his or her identity. This is usually manifest as two-factor authentication combining something you know (like a password) with something you have (e.g., some kind of device capable of generating one-time passwords or PINs). In a system that uses multifactor authentication, if an attacker discovers a user's password, then they won't be able to do anything with it unless they also have a way of obtaining the other credentials.

Multifactor authentication used to be a rather inconvenient prospect because it required that you actually provide your users with a physical device like a SecurID token (which has a numeric display with numbers that change every minute), and if you didn't have that token with you, then you couldn't authenticate. However, the proliferation of mobile phones has made this a much more realistic possibility. For example, you can configure your Google account to require multifactor authentication, combining a password with a one-time code obtained in one of the following ways:

Using the Google Authenticator app, which uses the time-based one-time password (TOTP) algorithm defined in RFC 6238. This option does not require any kind of network communication. By having a one-time password sent to your mobile phone as a text message. By having a one-time password read to you by a speech synthesizer over a voice call.

With multifactor authentication support enabled, an attacker will need to get access to your mobile phone in addition to figuring out your password before they'll be able to access your Google account.

Similarly, Facebook can be configured to require a one-time code sent as an SMS message any time you log in from a system it doesn't recognize. There are a number of other applications which provide some level of support for multifactor authentication, but it's unfortunate that there are still so many who do not offer it as an option so that their more technical and security-conscious users can take advantage of the additional security that it can provide.

At present, the UnboundID Directory Server supports multifactor authentication in the form of a password combined with a PIN generated using the TOTP algorithm (and is therefore compatible with the Google Authenticator app, along with other software capable of generating these codes). However, support for additional multifactor authentication schemes may be added in the future.

Plan for Disaster

No matter how tightly locked down your system may be, you should have a plan for dealing with a security breach in which an attacker is able to successfully obtain passwords and/or other sensitive information from your system. Hopefully you'll never have to put this plan into action, but it's far better to have a strategy you may not use than to find yourself without one when you really need it.

The first thing that you should do is to identify what information may have been compromised, and then tell your users about it. Trying to cover it up may be illegal, and it prevents affected users from trying to mitigate the risk of the attack while giving the bad guys more time to use the data they stole. It will also likely be more damaging to your reputation if users hear about a breach in your systems from someone else before they hear it from you.

If information about passwords may have been exposed, regardless of whether the passwords were encoded, then you should encourage or require users to change their passwords as soon as possible (and the UnboundID Directory Server offers a feature that can be used to require users to change their passwords by a given date/time). However, you should also assume that if login credentials were obtained, an attacker could have authenticated using those credentials and obtained access to other information about the account.

You should also try to determine how the attack was conducted so that you can make any changes in your system to help prevent the attack from recurring. If there isn't enough information available to determine the attack vector, then you may need to make broad changes to tighten the overall security of the environment. You will likely also want to ensure that appropriate logging is in place to make it easier to discover and analyze attacks in the future.

Finally, you should work with the vendors of any software that attackers were able to breach so that they can better understand how their software is being targeted and identify whether any changes may be needed to help prevent future problems. Even if the software you're using has features which could have prevented the attack from succeeding, the vendor may wish to consider enabling those features by default or better highlighting them in their documentation. Certainly we at UnboundID would be very interested to hear of attacks (whether successful or not) against our software so that we can continue to reevaluate the product features and default configuration. And if you have suggestions for improvement, we'd love to hear them as well.


UnboundID LDAP SDK for Java 2.3.1

The 2.3.1 release of the UnboundID LDAP SDK for Java primarily includes a number of bug fixes and minor functionality enhancements, many of which are in direct response to requests from users. You can get the latest release online at the UnboundID website or the SourceForge project page, and it's also available in the Maven Central Repository.

As usual, the release notes provide a complete overview of changes made in this release, but some of the most significant updates include:

  • The 2.3.0 release added the ability for the LDAP SDK to respect client-side timeouts for operations invoked via the asynchronous API. Unfortunately, for applications which had a very high rate of asynchronous operations, a bug in this implementation could cause excessive memory pressure (potentially including out of memory errors). That bug has been corrected.

  • Also in the 2.3.0 release, a change was made to prevent simultaneous use of the socket factory associated with the client connection. This was done in response to the discovery that some socket factories in the IBM JVM (at the SSL socket factory, if not others) may fail if an attempt was made to use them concurrently by multiple threads. Unfortunately, while this change made the LDAP SDK safer to use on such platforms, it also introduced a problem for other JVMs that could cause long delays in the ability to establish a connection following an attempt to connect to a server that is either unresponsive or slow to respond. In an attempt to strike a balance between these problems, concurrent use will be allowed on JVMs known to be threadsafe (including those provided by Sun, Oracle, and Apple), while still defaulting to single-threaded use on other JVMs. In addition, it is now possible to configure whether this should be allowed on a per-connection basis using a new setting in the LDAPConnectionOptions class.

  • A number of new SSL trust managers have been added, including one which looks only at the validity dates of the presented certificate, another that looks at the hostname of the certificate (either in the CN subject attribute or a subjectAltName extension), and an aggregate trust manager that can be used to decide whether to trust a certificate based on the combined results of a set of trust managers. Also, the prompt trust manager has been updated to display additional information about the certificate to allow the user to make more informed decisions about whether to trust the certificate.

  • Support for the SASL EXTERNAL bind request has been updated to make it possible to either include or exclude the SASL credentials element. This makes it possible to work with directory servers which require SASL credentials as well as those which do not expect them for EXTERNAL requests.

  • We have added a new server set implementation which will attempt to simultaneously connect to multiple servers, and will return the first connection it was able to establish. While this may increase the load across all servers at the time of the connection attempt, it helps ensure the lowest possible delay when trying to establish a connection to one of a set of servers.

  • The LDIF reader has been updated to provide better control over how to handle lines with unexpected trailing spaces, and also to make it possible to handle reading data from file with relative paths rather.

  • The searchrate, modrate, and search-and-modrate tools have been updated to make it possible to periodically close and re-establish connections to the server after a specified number of operations.

  • Fixed a corner case bug resulting from an application which attempted to use multiple resource files with the same paths. For example, if an application tried to use a properties file named "" or "", there may be a conflict between the version of that file used by the application and the one provided by the UnboundID LDAP SDK for Java. The names of the properties files used by the LDAP SDK have been renamed to avoid the possibility of conflicting with those which may have been used by other applications.


UnboundID LDAP SDK for Java 2.3.0

We have just released the UnboundID LDAP SDK for Java 2.3.0. It's been about six months since the last release, and there are several new features and bug fixes. It is available for download now from the UnboundID website and the SourceForge project page, and it's also available in the Maven central repository.

The release notes contain a pretty comprehensive set of changes since the 2.2.0 release, but some of the most significant changes are as follows:

  • It is now possible to use DNS SRV records (as described in RFC 2782) to automatically discover available LDAP servers in the environment. The implementation will respect defined priorities and weights, and can be used for individual connections or connection pools.

  • Experimental support has been added for the password policy control (as defined in draft-behera-ldap-password-policy) and the no-operation control (as defined in draft-zeilenga-ldap-noop). Even though these drafts are not necessarily finalized, some servers (including the UnboundID Directory Server) have implemented support for them, so it is useful to be able to access them through the LDAP SDK.

  • The schema caching mechanism (which makes it possible for client-side determinations to use server schema for more appropriate matching) has been made much more efficient so that multiple connections to the same server and with equivalent perceptions of the schema will reference the same object rather than having separate equivalent objects.

  • Updated the LDAP SDK so that operations invoked via the asynchronous API will still respect client-side timeouts.

  • A number of schema-related changes have been made to the in-memory directory server. You can now update the schema dynamically through LDAP modify operations. Supported syntaxes and matching rules are now advertised (at least when using the default standard schema). You can configure the server to allow attribute values which violate the associated attribute syntax, or to allow entries with multiple structural object classes (or no structural class at all).

  • The in-memory directory server has been updated with support for equality indexes to help speed up certain kinds of search operations (particularly when dealing with more than a handful of entries).

  • The in-memory directory server has been updated to always use the "dn:" form in authorization identity response controls. Previously, it could use the "u:" form in responses to SASL PLAIN binds that used the "u:" form in the request. It will also now use the correct value of "" instead of "dn:" to indicate the anonymous authorization identity.

  • It is now possible to customize the values that will be displayed for the vendorName and vendorVersion attributes in the root DSE. This can help the server more effectively fool applications which are coded to only work with certain directories.

  • The LDAP SDK persistence framework has been updated so that it supports attributes with options (e.g., "userCertificate;binary"). It is now also possible to specify superior object classes that should be included in entries that are created.

  • The connection pool implementation has been updated to provide better closed connection and unsolicited response detection for connections operating in synchronous mode.

  • The 2.2.0 release added support for using a newly-created connection to retry operations that failed in a manner that indicated the connection may no longer be valid. In the 2.3.0 release, it is now possible to configure that capability based on the type of operation being processed, whereas in the previous version all operation types were handled in an identical manner.

  • The LDIFReader has new convenience methods that can be used to read the contents of an LDIF file and retrieve the contents as a list of entries. This can be convenient when working with small LDIF files, especially for testing purposes.

  • The LDAP SDK now supports parsing LDAP URLs with an "ldapi" scheme. The LDAP SDK does not provide support for LDAPI (LDAP over UNIX domain sockets) in the out-of-the-box configuration, but it can now parse URLs using an "ldapi" scheme.

  • Command-line tools have been updated so that they can specify a tool version. If this is used, then the LDAP SDK can automatically add a "--version" argument to such tools which will cause the version string to be printed to the terminal.

  • Some changes were made to help the LDAP SDK be more fully functional on IBM Java VMs. This includes necessary changes to support GSSAPI on IBM VMs, and a workaround for an apparent bug that could result in exceptions from concurrent calls to SocketFactory.createSocket methods.