<!--

Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
Portions copyright 1999 Netscape Communications Corporation. All
Rights Reserved.

The contents of this document are subject to the terms of the
Creative Commons Attribution-ShareAlike 2.5 license or any later
version (the "License"). You may not use this document except in
compliance with the License.

See the License for the specific language governing
permissions and limitations under the License. You can obtain
a copy of the License at
http://creativecommons.org/licenses/by-sa/2.5/legalcode.

-->
<chapter id="sasl"><title>SASL Authentication With &DirectorySDKForJava;</title>
<highlights>
<para>This chapter describes the process of using a SASL mechanism to authenticate
an LDAP client to an LDAP server.</para>
<itemizedlist>
<para>This chapter covers the following topics:</para>
<listitem><para><olink targetptr="sasl-overview">Understanding SASL and Directory
SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="sasl-prepare">Preparing to Use SASL Authentication
With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="sasl-client">Using SASL in the Client With
Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="sasl-reading">Further Reading About SASL</olink></para>
</listitem>
</itemizedlist>
</highlights>
<sect1 id="sasl-overview"><title>Understanding SASL and &DirectorySDKForJava;</title>
<indexterm>
<primary>SASL</primary>
<secondary>defined</secondary>
</indexterm>
<para>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.</para>
<para>All SASL mechanisms are registered with the Internet Assigned Numbers
Authority (IANA). Included among these mechanisms are <literal>KERBEROS_V4</literal>, <literal>
GSSAPI</literal>, 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.</para>
<para>When a client attempts to authenticate to an LDAP server with the <literal>
LDAPConnection.authenticate</literal> method, the client can specify a list
of SASL mechanisms to use. If the client does not specify any mechanisms, &DirectorySDKForJava; queries
the server to find out which mechanisms the server supports. If &DirectorySDKForJava; and
the server have a common mechanism, authentication can occur.</para>
<para>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 &DirectorySDKForJava; with
a mechanism driver.</para>
<para>If the server does not support any of the requested mechanisms, the
SDK returns an <classname>AuthenticationNotSupportedException</classname>.</para>
<para>If the mechanism driver requires additional authentication data from
the client, the driver sends a <classname>Callback</classname> object to the
client. To prepare for the callback, the client implements a <classname>CallbackHandler
</classname> and passes the handler to &DirectorySDKForJava;. 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 <classname>CallbackHandler</classname> object
with <classname>Callback</classname> objects for each item to be processed.
The <classname>CallbackHandler</classname> then determines how to proceed.</para>
<para>&DirectorySDKForJava; includes a package, <literal>com.netscape.sasl</literal>,
that contains the code necessary to perform all of the steps involved in SASL
authentication.</para></sect1>
<sect1 id="sasl-prepare"><title>Preparing to Use SASL Authentication With &DirectorySDKForJava;</title>
<itemizedlist>
<para>Before performing SASL authentication, you must do the following:</para>
<listitem><para>Ensure that your LDAP server supports at least one SASL mechanism
</para></listitem>
<listitem><para>Ensure that your client environment supports at least one
SASL mechanism supported by the server</para></listitem>
</itemizedlist>
<sect2 id="sasl-prepare-server"><title>SASL Support on the Server</title>
<indexterm>
<primary>SASL</primary>
<secondary>server-side requirements</secondary>
</indexterm>
<para>&cnDirectoryServer; supports a plug-in API that allows you to write
your own server plug-in to handle SASL authentication. &cnDirectoryServer; also
supports SASL authentication through DIGEST-MD5 and through GSSAPI.</para>
<itemizedlist>
<para>If you write your own plug-in, your plug-in uses a registered SASL mechanism
to do the following:</para>
<listitem><para>Get information from a SASL bind request.</para></listitem>
<listitem><para>Create and send a SASL bind response back to the client.</para>
<para>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.</para></listitem>
</itemizedlist>
</sect2>
<sect2 id="sasl-prepare-client"><title>SASL Support on the Client</title>
<indexterm>
<primary>SASL</primary>
<secondary>client-side requirements</secondary>
</indexterm>
<para>To authenticate over SASL, you must have a mechanism in your SASL client
package. If you have obtained a <classname>ClientFactory</classname> class
that can produce a SASL mechanism that your server supports, you can name
its package in your code.</para>
<itemizedlist>
<para>This option can be performed in one of two ways:</para>
<listitem><para>Request a SASL client. Specify the package in the <property>javax.security.sasl.client.pkgs
</property> property of its <classname>Hashtable</classname>.</para></listitem>
<listitem><para>Set the package as the default factory for the session with
the <literal>Sasl.setSaslClientFactory</literal> method.</para></listitem>
</itemizedlist>
<para>For example, you might have a class, <classname>mysecurity.sasl.ClientFactory
</classname>, capable of producing a <classname>SaslClient</classname> object
for one or more mechanisms. You could then write either of the two following
bits of code:</para>
<programlisting>Hashtable props = new Hashtable();
props.put("javax.security.sasl.client.pkgs", "mysecurity.sasl");
ld.authenticate(dn, props, cbh);</programlisting>
<programlisting>Sasl.setSaslClientFactory (new mysecurity.sasl.ClientFactory());
ld.authenticate(dn, props, cbh);</programlisting>
<para>The parameters used have the following descriptions:</para>
<variablelist>
<varlistentry><term><parameter>dn</parameter></term>
<listitem><para>Authentication DN</para>
</listitem>
</varlistentry>
<varlistentry><term><parameter>props</parameter></term>
<listitem><para>Optional properties that the mechanism accepts</para>
<para>Refer to <olink type="auto-generated" targetptr="sasl-client-external">Using
the External Mechanism</olink> for details.</para>
</listitem>
</varlistentry>
<varlistentry><term><parameter>cbh</parameter></term>
<listitem><para>Instance of <classname>CallbackHandler</classname> that is
implemented in your application</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="sasl-prepare-callback"><title>Implementing <literal>javax.security.auth.callback
</literal></title>
<indexterm>
<primary>authentication</primary>
<secondary>implementing SASL callbacks</secondary>
</indexterm><indexterm>
<primary>callbacks</primary>
<secondary>implementing for SASL</secondary>
</indexterm><indexterm>
<primary>SASL</primary>
<secondary>implementing callbacks</secondary>
</indexterm>
<para>Some SASL mechanisms require additional credentials during the authentication
process. To provide this additional information, your SASL client might need
to implement <classname>Callback</classname> objects and a <classname>CallbackHandler
</classname> to list credentials. <classname>Callback</classname> and <classname>
CallbackHandler</classname> are part of the <literal>javax.security.auth.callback
</literal> package.</para>
<para>The following example shows <classname>Callback</classname> and <classname>
CallbackHandler</classname> implementations.</para>
<programlisting>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 &lt; callbacks.length; i++) {
            if (callbacks[i] instanceof TextOutputCallback) {
                // display the message according to the
                // specified STYLE
                TextOutputCallback toc =
&#9;&#9;    (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(
&#9;&#9;    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;
}</programlisting>
</sect2>
</sect1>
<sect1 id="sasl-client"><title>Using SASL in the Client With &DirectorySDKForJava;</title>
<itemizedlist>
<para>You are ready to authenticate when you have done the following:</para>
<listitem><para>Determined that at least one SASL mechanism exists in common
between the server and your client environment</para></listitem>
<listitem><para>Implemented <classname>javax.security.auth.callback.CallbackHandler
</classname> if you might need to supply additional credentials during authentication
</para></listitem>
</itemizedlist>
<para>The following example shows how to use SASL in an application:</para>
<programlisting>Hashtable props = new Hashtable();
props.put("javax.security.sasl.client.pkgs", "mysecurity.sasl");
ld.authenticate(dn, props, new SampleCallbackHandler());</programlisting>
<sect2 id="sasl-client-external"><title>Using the <literal>External</literal> Mechanism
</title>
<indexterm>
<primary>SASL</primary>
<secondary>using the EXTERNAL mechanism with</secondary>
</indexterm><indexterm>
<primary>SSL</primary>
<secondary>using SASL with</secondary>
</indexterm>
<para>&DirectorySDKForJava; includes a mechanism called <literal>EXTERNAL</literal>.
This mechanism verifies that SSL authentication has already completed before
the mechanism allows a client to connect over LDAP.</para>
<orderedlist>
<para>To use the <literal>EXTERNAL</literal> mechanism, do the following:</para>
<listitem><para>Bind to the server, and authenticate using SSL.</para><para>Refer
to <olink type="auto-generated" targetptr="ssl-connecting">Connecting to a
Server Over SSL With Directory SDK for Java</olink> for details.</para>
</listitem>
<listitem><para>Call the <literal>LDAPConnection.authenticate</literal> method
as follows:</para>
<programlisting>ld = new LDAPConnection();
ld.authenticate(
    null, new String[]{"EXTERNAL"}, null, (CallbackHandler)null);</programlisting>
<para><literal>LDAPConnection.authenticate</literal> takes the following parameters.
</para>
<variablelist>
<varlistentry><term><parameter>dn</parameter></term>
<listitem><para>Authentication DN</para>
</listitem>
</varlistentry>
<varlistentry><term><parameter>mechanisms</parameter></term>
<listitem><para>List of SASL mechanisms to use for authentication</para>
<para>If <literal>null</literal> is specified, &DirectorySDKForJava; queries
the server for all available mechanisms.</para>
</listitem>
</varlistentry>
<varlistentry><term><parameter>props</parameter></term>
<listitem><para>Optional properties that the mechanism accepts, which include
the following:</para>
<variablelist>
<varlistentry><term><property>javax.security.sasl.encryption.minimum</property></term>
<listitem><para>The minimum key length to be used during the session.</para>
<para>The default value is <literal>0</literal>, no session protection. A
value of <literal>1</literal> enables integrity protection only.</para>
</listitem>
</varlistentry>
<varlistentry><term><property>javax.security.sasl.encryption.maximum</property></term>
<listitem><para>The maximum key length to be used during the session.</para>
<para>The default value is <literal>256</literal>.</para>
</listitem>
</varlistentry>
<varlistentry><term><property>javax.security.sasl.server.authentication</property></term>
<listitem><para>A boolean value.</para>
<para><literal>true</literal> if a server must authenticate to the client.
The default value is <literal>false</literal>.</para>
</listitem>
</varlistentry>
<varlistentry><term><property>javax.security.sasl.ip.local</property></term>
<listitem><para>The client's IP address in dotted decimal format.</para>
<para>This value is required for <literal>KERBEROS_V4</literal> authentication.
No default value exists.</para>
</listitem>
</varlistentry>
<varlistentry><term><property>javax.security.sasl.ip.remote</property></term>
<listitem><para>The server's IP address in dotted decimal format.</para>
<para>This value is required for <literal>KERBEROS_V4</literal> authentication.
No default value exists.</para>
</listitem>
</varlistentry>
<varlistentry><term><property>javax.security.sasl.maxbuffer</property></term>
<listitem><para>The maximum size of the security layer frames.</para>
<para>The default is <literal>0</literal>, meaning that the client does not
use the security layer.</para>
</listitem>
</varlistentry>
<varlistentry><term><property>javax.security.sasl.client.pkgs</property></term>
<listitem><para>A bar-separated list of package names to use when locating
a <classname>SaslClientFactory</classname>.</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry><term><parameter>cbh</parameter></term>
<listitem><para>Instance of <classname>CallbackHandler</classname> that is
implemented in your application.</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</orderedlist>
</sect2>
<sect2 id="sasl-client-other"><title>Other SASL Mechanisms</title>
<para>Authentication with a SASL mechanism other than <literal>EXTERNAL</literal> requires
you to implement classes for the mechanism in the client and on the server.</para>
</sect2>
</sect1>
<sect1 id="sasl-reading"><title>Further Reading About SASL</title>
<para>SASL is described in <ulink url="http://www.ietf.org/rfc/rfc4422.txt"
type="text_url">RFC 4422</ulink>.</para>
<para>For a current list of registered SASL mechanisms, see <ulink
url="http://www.iana.org/assignments/sasl-mechanisms" type="url">http://www.iana.org/assignments/sasl-mechanisms
</ulink>.</para></sect1>
</chapter>
