Mozilla LDAP SDK Programmer's Guide/SASL Authentication With LDAP Java SDK

From MozillaWiki
Jump to: navigation, search

This section describes the process of using a SASL mechanism to authenticate an LDAP client to an LDAP server.

Understanding SASL and LDAP Java SDK

The Simple Authentication and Security Layer (SASL) is an authentication method. SASL allows you to use mechanisms other than simple passwords and SSL for authenticating over connection-based protocols, such as LDAP.

All SASL mechanisms are registered with the Internet Assigned Numbers Authority (IANA). Included among these mechanisms are KERBEROS_V4, GSSAPI, and several others. The client implements these mechanisms through the use of mechanism drivers. These drivers are classes that contain the code that is required for authenticating over a given mechanism. When a client attempts to authenticate to an LDAP server with the LDAPConnection.authenticate method, the client can specify a list of SASL mechanisms to use. If the client does not specify any mechanisms, LDAP Java SDK queries the server to find out which mechanisms the server supports. If LDAP Java SDK and the server have a common mechanism, authentication can occur.

If the server supports a requested mechanism, the server responds with one or more challenges. To authenticate, the client must correctly respond to these challenges. Client handling is performed transparently by LDAP Java SDK with a mechanism driver.

If the server does not support any of the requested mechanisms, the SDK returns an AuthenticationNotSupportedException. If the mechanism driver requires additional authentication data from the client, the driver sends a Callback object to the client. To prepare for the callback, the client implements a CallbackHandler and passes the handler to LDAP Java SDK. The SASL mechanism might need additional client credentials. The SASL mechanism might also notify the client of errors during the SASL negotiations. For either purpose, the mechanism calls the CallbackHandler object with Callback objects for each item to be processed. The CallbackHandler then determines how to proceed. LDAP Java SDK includes a package, com.netscape.sasl, that contains the code necessary to perform all of the steps involved in SASL authentication.

Preparing to Use SASL Authentication With LDAP Java SDK

Before performing SASL authentication, you must do the following:

  • Ensure that your LDAP server supports at least one SASL mechanism
  • Ensure that your client environment supports at least one SASL mechanism supported by the server

SASL Support on the Server

Directory Server supports a plug-in API that allows you to write your own server plug-in to handle SASL authentication. Directory Server also supports SASL authentication through DIGEST-MD5 and through GSSAPI. If you write your own plug-in, your plug-in uses a registered SASL mechanism to do the following:

  1. Get information from a SASL bind request.
  2. Create and send a SASL bind response back to the client.
    This response can take the form of a challenge that requires an answer from the client. The response can also take the form of an error message. Finally, the response can take the form of a success message indicating that authentication is complete.

SASL Support on the Client

To authenticate over SASL, you must have a mechanism in your SASL client package. If you have obtained a ClientFactory class that can produce a SASL mechanism that your server supports, you can name its package in your code.

This option can be performed in one of two ways:

  • Request a SASL client. Specify the package in the javax.security.sasl.client.pkgs property of its Hashtable.
  • Set the package as the default factory for the session with the Sasl.setSaslClientFactory method.

For example, you might have a class, mysecurity.sasl.ClientFactory, capable of producing a SaslClient object for one or more mechanisms. You could then write either of the two following bits of code:

Hashtable props = new Hashtable();
props.put("javax.security.sasl.client.pkgs", "mysecurity.sasl");
ld.authenticate(dn, props, cbh);
Sasl.setSaslClientFactory (new mysecurity.sasl.ClientFactory());
ld.authenticate(dn, props, cbh);

The parameters used have the following descriptions:

  • dn: Authentication DN
  • props: Optional properties that the mechanism accepts
    Refer to Using the External Mechanism for details.
  • cbh: Instance of CallbackHandler that is implemented in your application

Implementing javax.security.auth.callback

Some SASL mechanisms require additional credentials during the authentication process. To provide this additional information, your SASL client might need to implement Callback objects and a CallbackHandler to list credentials. Callback and CallbackHandler are part of the javax.security.auth.callback package.

The following example shows Callback and CallbackHandler implementations.

class SampleCallbackHandler implements CallbackHandler {
    SampleCallbackHandler(String userName) {
        userName = userName;
    }
    /** Invoke the requested Callback */
    public void invokeCallback(Callback[] callbacks)
        throws java.io.IOException,UnsupportedCallbackException {
        for (int i = 0; i  callbacks.length; i++) {
            if (callbacks[i] instanceof TextOutputCallback) {
                // display the message according to the
                // specified STYLE
                TextOutputCallback toc =
		    (TextOutputCallback)callbacks[i];
                switch (toc.getStyle()) {
                    case TextOutputCallback.ERROR:
                        System.out.println("ERROR: " + toc.getMessage());
                        break;
                    case TextOutputCallback.INFORMATION:
                        System.out.println(toc.getMessage());
                        break;
                    case TextOutputCallback.WARNING:
                        System.out.println("WARNING: " + toc.getMessage());
                        break;
                }
            } else if (callbacks[i] instanceof TextInputCallback){
                // prompt the user for information
                TextInputCallback tic = (TextInputCallback)callbacks[i];
                // display the prompt and a default reply
                System.err.print(tic.getPrompt() + " [" +
                    tic.getDefaultText() + "]: ");
                System.err.flush();
                BufferedReader reader = new
                    BufferedReader(new InputStreamReader(System.in));
                tic.setText(reader.readLine());
            } else if (callbacks[i] instanceof NameCallback) {
                ((NameCallback)callbacks[i]).setName(_userName);
            } else if (callbacks[i] instanceof PasswordCallback){
                // prompt the user for sensitive information
                PasswordCallback pc = (PasswordCallback)callbacks[i];
                System.err.print(pc.getPrompt() + " ");
                System.err.flush();
                pc.setPassword(readPassword(System.in));
            } else if (callbacks[i] instanceof LanguageCallback){
                // Get the language from the locale
                LanguageCallback lc = (LanguageCallback)callbacks[i];
                lc.setLocale(Locale.getDefault());
            } else {
                throw new UnsupportedCallbackException(
		    callbacks[i], "Unrecognized Callback");
            }
        }
    }
    /** Reads user password from given input stream. */
    private char[] readPassword(InputStream in) {
        // insert code to read a user password from the
        // input stream
    }
    private String _userName = null;
}

Using SASL in the Client With LDAP Java SDK

You are ready to authenticate when you have done the following:

  • Determined that at least one SASL mechanism exists in common between the server and your client environment
  • Implemented javax.security.auth.callback.CallbackHandler if you might need to supply additional credentials during authentication

The following example shows how to use SASL in an application:

Hashtable props = new Hashtable();
props.put("javax.security.sasl.client.pkgs", "mysecurity.sasl");
ld.authenticate(dn, props, new SampleCallbackHandler());

Using the External Mechanism

LDAP Java SDK includes a mechanism called EXTERNAL. This mechanism verifies that SSL authentication has already completed before the mechanism allows a client to connect over LDAP. To use the EXTERNAL mechanism, do the following:

  1. Bind to the server, and authenticate using SSL.
    Refer to Connecting to a Server Over SSL With LDAP Java SDK for details.
  2. Call the LDAPConnection.authenticate method as follows:
ld = new LDAPConnection();
ld.authenticate(
    null, new String[]{"EXTERNAL"}, null, (CallbackHandler)null);

LDAPConnection.authenticate takes the following parameters.

  • dn: Authentication DN
  • mechanisms: List of SASL mechanisms to use for authentication
    If null is specified, LDAP Java SDK queries the server for all available mechanisms.
  • props: Optional properties that the mechanism accepts, which include the following:
    • javax.security.sasl.encryption.minimum: The minimum key length to be used during the session.
      The default value is 0, no session protection. A value of 1 enables integrity protection only.
    • javax.security.sasl.encryption.maximum: The maximum key length to be used during the session.
      The default value is 256.
    • javax.security.sasl.server.authentication: A boolean value.
      true if a server must authenticate to the client.
      The default value is false.
    • javax.security.sasl.ip.local: The client's IP address in dotted decimal format.
      This value is required for KERBEROS_V4 authentication.
      No default value exists.
    • javax.security.sasl.ip.remote: The server's IP address in dotted decimal format.
      This value is required for KERBEROS_V4 authentication.
      No default value exists.
    • javax.security.sasl.maxbuffer: The maximum size of the security layer frames.
      The default is 0, meaning that the client does not use the security layer.
    • javax.security.sasl.client.pkgs: A bar-separated list of package names to use when locating a SaslClientFactory.
  • cbh: Instance of CallbackHandler that is implemented in your application.

Other SASL Mechanisms

Authentication with a SASL mechanism other than EXTERNAL requires you to implement classes for the mechanism in the client and on the server.

Further Reading About SASL

SASL is described in RFC 4422. For a current list of registered SASL mechanisms, see http://www.iana.org/assignments/sasl-mechanisms.