| Security

## Digest-MD5 Authentication

> > Note: The LDAP provider's Digest-MD5 implementation uses the Java Cryptography Extension (JCE), version 1.2 or higher. If you are using the Java 2 SDK, v1.4, then the JCE is already included so you need to take no further action. Otherwise, you need to install the JCE and JCE providers in order for the Digest-MD5 examples to work.

> Digest-MD5 authentication is the required authentication mechanism for LDAP v3 servers (RFC 2829). Because the use of SASL is part of the LDAP v3 (RFC 2251), servers that support only the LDAP v2 do not support Digest-MD5.

> The Digest-MD5 mechanism is described in RFC 2831. It is based on the HTTP Digest Authentication (RFC 2617). In Digest-MD5, the LDAP server sends data that includes various authentication options that it is willing to support plus a special token to the LDAP client. The client responds by sending an encrypted response that indicates the authentication options that it has selected. The response is encrypted in such a way that proves that the client knows its password. The LDAP server then decrypts and verifies the client's response.

> To use the Digest-MD5 authentication mechanism, you must set the authentication environment properties as follows.

> `Context.SECURITY_AUTHENTICATION`.
>   Set to the string `"DIGEST-MD5"`.
> `Context.SECURITY_PRINCIPAL`.
>   Set to the principal name. This is a server-specific format. Some servers support a login user id format, such as that defined for Unix or Windows login screens. Others accept a distinguished name. Yet others use the authorization id formats defined in RFC 2829. In that RFC, the name should be either the string `"dn:"`, followed by the fully qualified DN of the entity being authenticated, or the string `"u:"`, followed by the user id. Some servers accept multiple formats. Examples of some of these formats are `"cuser"`, `"dn: cn=C. User, ou=NewHires, o=JNDITutorial"`, and `"u: cuser"` The data type of this property must be `java.lang.String`.
> `Context.SECURITY_CREDENTIALS`.
>   Set to the password of the principal (e.g., `"mysecret"`). It is of type `java.lang.String`, `char` array (`char[]`), or `byte` array (`byte[]`). If the password is a `java.lang.String` or `char[]`, then it is encoded by using UTF-8 for transmission to the server. If the password is a `byte[]`, then it is transmitted as is to the server.

> The following example shows how a client performs authentication using Digest-MD5 to an LDAP server.

> >     // Set up the environment for creating the initial context
> >     Hashtable env = new Hashtable();
> >     env.put(Context.INITIAL_CONTEXT_FACTORY,
> >         "com.sun.jndi.ldap.LdapCtxFactory");
> >     env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

> >     // Authenticate as C. User and password "mysecret"
> >     env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
> >     env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
> >     env.put(Context.SECURITY_CREDENTIALS, "mysecret");

> >     // Create the initial context
> >     DirContext ctx = new InitialDirContext(env);

> >     // ... do something useful with ctx

> > Note: The i-Planet Directory Server, v5 supports the Digest-MD5 authentication mechanism for users that have clear-text passwords. You must set the password encryption mode before you create the user. If you have already created the user, delete it and recreate it. To set the password encryption mode using the Administration Console, select the Configuration tab and the Data node. In the Passwords pane, select the "No encryption (CLEAR)" option for "Password encryption." The server accepts simple user names (that is, the value of the `"uid"` attribute for entries that have one) and the "dn:" format of user names. See the server's documentation for detailed information.

> #### Specifying the Realm

> A realm defines the namespace from which the authentication entity (the value of the `Context.SECURITY_PRINCIPAL` property) is selected. A server might have multiple realms. For example, a server for a university might be configured to have two realms, one for its student users and another for faculty users. Realm configuration is done by the directory administrator. Some directories have a default single realm. For example, the i-Planet Directory Server, v5, uses the fully qualified hostname of the machine as the default realm.

> In Digest-MD5 authentication, you must authenticate to a specific realm. You may use the following authentication environment property to specify the realm. If you do not specify a realm, then any one of the realms offered by the server will be used.

> `java.naming.security.sasl.realm`
>   Set to the realm of the principal. This is a deployment-specific and/or server-specific case-sensitive string. It identifies the realm or domain from which the principal name (`Context.SECURITY_PRINCIPAL`) should be chosen. If this realm does not match one of the realms offered by the server, then the authentication fails.

> The following example shows how to set the environment properties for performing authentication using Digest-MD5 and a specified realm. To make this example work in your environment, you must change the source code so that the realm value reflects what has been configured on your directory server.

> >     // Authenticate as C. User and password "mysecret" in realm "JNDITutorial"
> >     env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
> >     env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
> >     env.put(Context.SECURITY_CREDENTIALS, "mysecret");
> >     env.put("java.naming.security.sasl.realm", "JNDITutorial");

> #### More Than Just Authentication

> The Digest-MD5 SASL mechanism also supports the establishment of a negotiated security layer after successful authentication. The security layer can perform integrity and privacy protection. The security layer is specified by the quality of protection (qop), which is negotiated with the server during authentication. You specify the qops that your application can tolerate, listing the most desirable qop first. For example, if your application prefers privacy protection but can live with integrity-only protection, then you would specify `"auth-conf,auth-int"` as the value of `"javax.security.sasl.qop"` property. If the server supports only authentication, then the authentication would fail; otherwise, either privacy or integrity would be selected depending on server support, with priority given to privacy.

> The following example shows how to set the environment properties for performing authentication using Digest-MD5 with integrity protection.

> >     // Authenticate as C. User and password "mysecret"
> >     env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
> >     env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
> >     env.put(Context.SECURITY_CREDENTIALS, "mysecret");

> >     // Request integrity protection
> >     env.put("javax.security.sasl.qop", "auth-int");

> Digest-MD5 supports five different ciphers for privacy protection. The cipher selected is negotiated between the client and server during authentication. These five ciphers are mapped to the `"high"`, `"medium"`, and `"low"` settings defined for the `"javax.security.sasl.strength"` environment property. Here is a table that lists the ciphers, their mappings and descriptions.

> Cipher | QOP Mapping | Description
> --- | --- | ---
> RC4 (40 bit) | low | The RC4 cipher with 40 bit key.
> RC4 (56 bit) | medium | The RC4 cipher with 56 bit key.
> RC4 (128 bit) | high | The RC4 cipher with 128 bit key.
> DES | medium | The Data Encryption Standard (DES) cipher in cipher block chaining (CBC) mode with a 56 bit key.
> Triple DES | high | The "triple DES" cipher in CBC mode with EDE with the same key for each E stage (aka "two keys mode") for a total key length of 112 bits.

> In the Digest-MD5 protocol, the server sends the client a list of ciphers that it supports. The client must select a cipher from this list. The selection is determined by the setting of the `"javax.security.sasl.strength"` environment property and the ciphers configured on the client's platform. For example, suppose the server offers all five ciphers and the client has not set the `"javax.security.sasl.strength"` property. This effectively means that the client is requesting strengths in order of preference of `"high"`, `"medium"`, and `"low"`. If triple DES or RC4 with 128 bits is available on the client's platform, then it will be the selected cipher. Otherwise, if DES or RC4 with 56 bits is available on the client's platform, then it will be selected. And so on. If the client supports none of the listed ciphers, then the SASL authentication fails.

> The LDAP provider uses the Java Cryptography Extension (JCE) for cipher support. For information about installing and configuring Java security providers, including JCE providers, see the Installing Providers section of the Java Cryptography Architecture API Specification & Reference document. The ciphers available from the installed JCE providers will determine which ciphers the LDAP provider supports.

> > Note 1: The default JCE provider that is in the Java 2 SDK, v1.4, supports only DES and triple DES with a key length limit of 64. To use the `"high"` privacy strength setting, you need to remove from the JCE the restriction on cryptographic strengths. Such restrictions are specified in jurisdiction policy files. See the JCE documentation for information on how to replace jurisdiction policy files. To use the RC4 ciphers, you must install a JCE provider that supports RC4.

> > Note 2: The i-Planet Directory Server, v5, supports only authentication for Digest-MD5. It does not support integrity or privacy protection.

> The following example shows how to set the environment properties for performing authentication using Digest-MD5 with medium-strength privacy protection.

> >     // Authenticate as C. User and password "mysecret"
> >     env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
> >     env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
> >     env.put(Context.SECURITY_CREDENTIALS, "mysecret");

> >     // Request privacy protection
> >     env.put("javax.security.sasl.qop", "auth-conf");

> >     // Request medium-strength cryptographic protection
> >     env.put("javax.security.sasl.strength", "medium");

> #### Specifying the Maximum Receive Buffer Size

> When requesting integrity or privacy protection, you may specify the maximum receive buffer size to use by using the `"javax.security.sasl.maxbuffer"` environment property. If you do not specify a maximum, it defaults to the Digest-MD5 default of 65536 bytes. The following example shows how to set the environment properties for performing authentication using Digest-MD5 with integrity protection and a maximum receive buffer size of 16384 bytes.

> >     // Authenticate as C. User and password "mysecret"
> >     env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
> >     env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
> >     env.put(Context.SECURITY_CREDENTIALS, "mysecret");

> >     // Request integrity protection
> >     env.put("javax.security.sasl.qop", "auth-int");

> >     // Request a maximum receive buffer size of 16384 bytes
> >     env.put("javax.security.sasl.maxbuf", "16384");

| Security