Friday June 30, 2006 | cn=Directory Manager All about Directory Server |
Working with LDAP ControlsThe LDAP specification defines standard behavior for all of the core types of operations that can be performed. However, there are cases in which you want the server to deviate from the default behavior, or perhaps you want it to provide additional information back to the client. This is where controls come in.LDAP controls have three components:
Technically, controls are all optional. It's not an absolute requirement for an LDAP directory server to support any controls at all, although most if not all do. However, the set of controls that different servers support does vary from one to another. If that's the case, then how is a client supposed to know whether the server it's talking to supports a given control? It can use the supportedControl attribute of the root DSE. In Directory Server 5.2 Patch 4, this might look like: $ ldapsearch -h ldap.example.com -p 389 -b '' -s base '(objectClass=*)' supportedControl version: 1 dn: supportedControl: 1.2.840.113556.1.4.473 supportedControl: 1.3.6.1.4.1.1466.29539.12 supportedControl: 1.3.6.1.4.1.42.2.27.9.5.2 supportedControl: 1.3.6.1.4.1.42.2.27.9.5.6 supportedControl: 1.3.6.1.4.1.42.2.27.9.5.8 supportedControl: 2.16.840.1.113730.3.4.2 supportedControl: 2.16.840.1.113730.3.4.3 supportedControl: 2.16.840.1.113730.3.4.4 supportedControl: 2.16.840.1.113730.3.4.5 supportedControl: 2.16.840.1.113730.3.4.9 supportedControl: 2.16.840.1.113730.3.4.12 supportedControl: 2.16.840.1.113730.3.4.13 supportedControl: 2.16.840.1.113730.3.4.14 supportedControl: 2.16.840.1.113730.3.4.15 supportedControl: 2.16.840.1.113730.3.4.16 supportedControl: 2.16.840.1.113730.3.4.17 supportedControl: 2.16.840.1.113730.3.4.18 supportedControl: 2.16.840.1.113730.3.4.19 The controls that correspond to these OIDs are as follows:
We'll be adding support for additional controls in future versions of the server, so stay tuned. Posted by cn_equals_directory_manager ( Jun 30 2006, 10:42:22 AM CDT ) Permalink The SSHA Password Storage SchemeIn an earlier post I discussed the various mechanisms that we have in place for protecting passwords in the Directory Server. One of the forms of protection that we provide comes in the form of password storage schemes, and the default and most secure storage scheme currently included is the SSHA scheme. This is a salted version of the SHA-1 message digest algorithm, and it provides a level of protection against dictionary attacks.One-way message digest algorithms like SHA-1 and MD5 are intentionally designed so that it's not possible to determine the original cleartext value from the hash value. However, they are also designed so that the same cleartext always hashes to exactly the same digest. Therefore, if I know that the cleartext "password" always generates a base64-encoded SHA-1 hash of "W6ph5Mm5Pz8GgiULbPgzG37mj9g=", then every time I see that encoded value, I know that the cleartext value was "password". If I create a dictionary of pre-hashed values that maps to them to the cleartext used to generate the hashes, I can use that to help me quickly break any commonly-used passwords. The introduction of a salt into the encoding process is enough to render precomputed dictionaries useless. It works by adding a random element to the digest process so that a given cleartext value does not always generate the same encoded value. If I use SSHA to encode the cleartext "password" five times, then I wil get five different encoded values. In fact, because we use a 64-bit salt there are 18,446,744,073,709,551,616 different ways of encoding the same clear-text value. This makes creating a dictionary completely infeasible because of the sheer volume that would be required to hold even all encodings for a single value. I've previously stated that there is no reason for a client to know how passwords are encoded in the server, and I stick by that. Any client that attempts to verify passwords externally is broken, since it can't abide by the configured password policy, and because it will stop working if the storage scheme is changed in the future. Similarly, allowing applications to pre-encode passwords before sending them to the server can also bypass password policy restrictions. Nevertheless, we frequently find that people are curious as to exactly how SSHA works, so I'll describe it here for informational purpopses only. The algorithm that we use is actually very simple:
When a user attempts to bind to the Directory Server, the server validates the clear-text password provided by the user in the following way:
To better illustrate this process, I've created a very simple Java class that can be used to either encode a clear-text password using SSHA or compare a given clear-text password with an encoded password to determine whether it is valid. It should be self-contained and thoroughly commented, so it may help illustrate the steps outlined above in a more programmatic manner. Posted by cn_equals_directory_manager ( Jun 23 2006, 12:31:16 PM CDT ) Permalink Protecting Passwords in the Directory ServerIn order to perform simple authentication, the Directory Server must store the user's password so that it can be verified while processing the bind request. Because the server is storing so many passwords, that could make it a potential target for people trying to gain unauthorized access to various systems. If you can figure out a user's password, then you can likely impersonate that person in any application that uses LDAP simple authentication to identify users. Therefore, it stands that this is something that needs to be as difficult as possible to achieve.The first line of defense that the Directory Server offers is in the area of access control. It is a relatively simple matter to ensure that the password will not be accessible to users, and in fact this is the default configuration. If anyone other than an administrator retrieves a user's entry, then the password will not be included in that entry. It's possible to override this, of course, but in general it's not recommended. There should be no reason for clients to need to see this (and any client that authenticates clients by retrieving the password and manually comparing it against what the user provided is fundamentally broken), so this is a good first step. The second step is to prevent passwords from being exposed to those that might be able to observe the network communication between clients and the Directory Server. Even though most users can't retrieve passwords, the root DN (typically "cn=Directory Manager") and other administrative users may be able to do so, and you'll want to prevent other observers from being able to see that. Further, simple bind requests will always contain the password in the clear, so that should be protected as well. All of this can be achieved through the use of SSL/TLS, or through a related mechanism like IPsec. Most of these mechanisms also include protection against man-in-the-middle attacks, where someone sets up a simple proxy server that can capture passwords as they're being sent to the server. Preventing access to the passwords over LDAP is very important, but it's not the only method that a malicious user might try to get access to them. The passwords will also be contained on disk in the Directory Server database, as well as in backups and LDIF exports of the data. Therefore, it's critical to make sure that the set of people that have access to the Directory Server systems and data backups is limited only to those that really need it. Fortunately, even if someone does have access to see passwords as they are stored in the Directory Server, there is still another level of protection that will create some difficulty for an attacker. In most cases, the passwords are not stored in the clear, but rather are encoded using password storage schemes. A password storage scheme provides a way to represent a password that can be used by the Directory Server to determine if a password provided in a bind request is correct but that makes it very difficult to tell what the actual password is. The storage schemes provided by the server out of the box include:
Note that it is possible to add support for new password storage schemes to the server (as documented in the Plug-In Developer's Guide), so if none of our default schemes are appropriate for your deployment you can add support for your own without too much difficulty. And I should point out that we will be adding support for additional storage schemes in the future so you will have more choices available that may be more appropriate in certain cases. With all of these levels of protection for user passwords, about the only thing that an attacker can try (other than social engineering or looking for post-it notes with the password written on it) is brute force. At this point, it all comes down to the strength of the user's password. This is primarily a function of the character set used for the password and the number of characters in the password. For example, if we know that the password is comprised of six lowercase alphabetic characters, then there can only be 308,915,776 possible values. My laptop can do about 3 million of these hashes per second, so that's only 100 seconds to run through the entire set of possible values. On the other hand, if a password is 10 characters long and can use the full set of 95 printable ASCII characters then there are 59,873,693,923,837,890,625 possible values and it would take my laptop over 630,000 years to work thorugh all of them. Even a massive compute grid isn't going to be able to knock that down to anything that's even close to a reasonable length of time, so not even brute force is a feasilbe attack vector for something like that. Ultimately, this means that password security is really an issue of the strength of the passwords. Our server currently offers the ability to enforce a minimum length and provide some other basic checks like ensuring that the password doesn't match the values of other attributes in the user's entry. The upcoming Directory Server 6 release will include a number of other checks that can be enforced (you may be able to get this as a plugin for a 5.x server through our professional services engineering) like ensuring passwords use different classes of characters (e.g., at least some number of lowercase letters, uppercase letters, numeric digits, and other symbols) and dictionary checks, and we've got even bigger plans for releases after that. If you've got to use passwords for authentication, then we want to help you keep them as secure as possible. Posted by cn_equals_directory_manager ( Jun 21 2006, 08:17:01 AM CDT ) Permalink Comments [3] LDAP Authentication MechanismsOne of the most common tasks that the Directory Server is given is to serve as the repository for authenticating users. Traditionally, this is accomplished by binding to the server using simple authentication, but there are other options that may have their own advantages and disadvantages. These options come in the form of SASL mechanisms, where SASL is the Simple Authentication Security Layer defined in RFC 2222 and recently updated in RFC 4422. Many people may not be familiar with all of these methods, so I'll briefly describe them here.Note that this post isn't going to go into a lot of detail about how to configure the server or clients to perform these types of authentication. The Directory Server Administration Guide, and in particular Chapter 11: Managing Authentication and Encryption provides instructions for doing this. LDAP simple authentication is aptly-named because it is a very straightforward mechanism. A user binding with simple authentication needs only to provide their DN and password. This is the most widely supported LDAP authentication method, so chances are pretty good that if your application supports authenticating against a Directory Server then it can use simple authentication. However, there are a couple of disadvantages to using simple authentication. The first is that in order to authenticate the client must know the users's DN, which is not necessarily something that the end user is likely to know. However, this is generally overcome by first performing a search to find the user's entry (e.g., based on a uid or e-mail address), and then take the DN from that user entry to use in the simple authentication. The second disadvantage is that simple authentication does nothing to protect the user's password as it is transmitted over the network, so anyone that can listen in can see the password in the clear. This can be overcome by encrypting the communication with the server (e.g., using SSL/TLS to perform the encryption at the client-server level, or using IPsec to achieve it at a host or network level). Even though it is a relatively straightforward process to encrypt the communication between the client and the server to protect the credentials used for simple authentication, this does incur a cost for the entire set of communication because it is not possible to encrypt only the bind request (it is possible to use the StartTLS extended operation to encrypt only a portion of the interaction between the client and the server, but it also requires that any existing authentication be disregarded when transitioning from secure to insecure communication). In some cases, encrypting the entire session between the client and the server may add an undesirable amount of overhead if the password is the only thing that would need to be protected. In this case, an alternative that you could consider would be the use of SASL authentication with the DIGEST-MD5 mechanism. The DIGEST-MD5 mechanism is a password-based authentication method whose primary benefit is that it doesn't expose the bind password to anyone that might happen to be listening in on the network communication between the client and the server. It is able to accomplish this because the password itself is never transferred, but rather just information that proves the client does know the user's real password. It is a little more complicated than the simple authentication process because it requires a multi-stage bind (basically, the client and server both come up with some random data and then use that in combination with the user's password to generate an MD5 hash), but ultimately the password is never exposed in the clear, and the mechanism is relatively secure against replay and man-in-the-middle attacks. It also has the benefit of being able to authenticate using an authorization ID (which can specify either a user ID or a full DN), which means that the client doesn't necessarily have to do a search first in order to get the user's DN. The primary downside of using the DIGEST-MD5 authentication mechanism is that it requires the Directory Server to know the clear-text password for the user. For our current server, this means that the values must be stored in the clear (i.e., using the "CLEAR" scheme). This is an unacceptable proposition in most cases because of the dangers associated with keeping the passwords in the clear, although we will likely eliminate many of these concerns in the future by adding password storage schemes based on reversible encryption. While passwords are certainly very commonly used in LDAP authentication, they are certainly not the only form of credentials that are available. In particular, our Directory Server supports two other SASL mechanisms that don't directly involve passwords: EXTERNAL and GSSAPI. The EXTERNAL mechanism tells the Directory Server that the user wants to authenticate based on some other identifying information that may be available. In our Directory Server, this currently is available only for client connections that have been established using SSL where the client has provided its own certificate to the server (i.e., SSL client authentication). The Directory Server can use the information in that certificate to map it to a user's entry and can accept that as authentication. Since this is based on relatively strong cryptographic methods, it can be significantly more secure than using passwords, but it is also more complicated to manage because each user must have their own certificate and the Directory Server must have enough information available to determine whether to trust that certificate. On a large scale, this generally involves a PKI deployment and may also require storing public keys in user entries for use in the validation process, and this can be a cumbersome process to set up and manage. The SASL GSSAPI mechanism allows a user to authenticate to the Directory Server through Kerberos V. For cases in which Kerberos is already deployed and used as a single sign-on solution for other applications in the environment, this can be a relatively simple way to expand that to include authenticating to the Directory Server. In that case, the server will require its own Kerberos key and must be able to map the client principals to user entries for the authentication process, but it may be an attractive option for environments where Kerberos is already widely deployed. There are a number of other SASL mechanisms that have been defined, but at present our server only supports EXTERNAL, DIGEST-MD5, and GSSAPI. We are considering adding support for other mechanisms like CRAM-MD5 and PLAIN in future releases, but if there are other mechanisms that you might find useful then that would be helpful for us to know as well. Posted by cn_equals_directory_manager ( Jun 16 2006, 02:02:12 PM CDT ) Permalink Comments [2] Lots of New LDAP RFCsThe RFC editor was busy today. RFCs 4510 through 4533 all deal with LDAP in some way. Several of them came from the ldapbis working group, which provides clarification on the core LDAPv3 specifications so there's not a whole lot of new and groundbreaking stuff. Nevertheless, if you've never read through the official protocol specification, then it's worth checking out. In particular:
In addition to updating the core specifications, there were also some new specifications that made it out of the draft phase. Some of the most interesting of these include:
These have been around in draft form for a while, and we already provide support for the "Who am I?" operation in current releases and others are slated for inclusion in future releases. We're certainly intent in keeping up with the proposals and specifications, and if there are other specifications that you think you would find particularly useful then let us know. We can't make any promises, but it always helps to know what our customers feel are the most important enhancements that we can make. Posted by cn_equals_directory_manager ( Jun 08 2006, 11:42:51 PM CDT ) Permalink Comments [1] LDAP Connection PoolingIf you're developing applications to communicate with the Directory Server, you'll want to make your code as efficient as possible to minimize the load on the server and to get the responses as quickly as possible. A couple of weeks ago, I gave a few tips for develping such applications. One of these was the recommendation to use connection pools wherever possible. That's actually a pretty broad topic, and it deserves its own post.Connection pooling is a very good thing for a few reasons. The biggest benefit that it provides is that it saves the expense of establishing a new connection every time the client wants to issue a request to the server. Just establishing the TCP connection can be pretty expensive, especially when SSL is involved, so avoiding it is a good thing. Using connection pools also helps keep the total number of connections to the server down, since a few connections can be shared by all the end users instead of having a separate connection per concurrent user. The number of concurrent connections really doesn't have much impact on the performance of Sun's Directory Server, but each connection does use a little memory and keeping lots of connections open can consume all of the server's available file descriptors so it can't accept any new connections. Finally, a good connection pooling implementation can make it easier for your application to deal with errors and fail over to another server in the event of a problem, and it can also work to spread the load across multiple servers. The term "connection pool" can mean different things to different people, and what they envision can have varying degrees of complexity. In its simplest form, a connection pool is simply a set of one or more connections that remain established for an extended period of time and may be accessed by multiple threads in an application (or in some cases, in multiple applications). And even in "more complex" forms, they are still pretty simple and ultimately just boil down to a list of connections. However, I've come up with a set of tips that you might find helpful if you're considering implementing your own pool:
Traditional connection pool implementations merely provide the basic framework that allows the client to check out and return connections. Many SDKs provide supporf for this type of pooling, but I feel that they are often too lacking in support for things like failure handling, and they often leave too much work to the application developer. I generally prefer to develop my own connection pool implementation, and in the process of doing so push a lot of the common logic into the pool itself. For example, although it is possible to retrieve a connection from the pool, I also include helper methods that make it possible to perform most common operations in the pool itself (where the method will retrieve a connection, perform the request, take care of any necessary error handling, and return the connection to the pool). This simplifies the application and avoids unnecessary duplication of code and makes it easier to ensure that there are no connection leaks or other problems. I'm not aware of any LDAP SDKs that currently provide this capability, but perhaps that's a feature that we can provide at some point in the future. Fortunately, it's not that difficult for you to implement for yourself and I believe that the benefits of doing so greatly outweigh the time and effort invested in it. Posted by cn_equals_directory_manager ( Jun 05 2006, 08:10:28 AM CDT ) Permalink |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||