mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Mark Craig
22.16.2011 38fc88aa89f1eb893ce43acf49179e4b2b1228c7
Example showing SASL PLAIN authentication
2 files added
1 files modified
304 ■■■■■ changed files
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/Main.java 210 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/package-info.java 32 ●●●●● patch | view | raw | blame | history
opendj3/src/main/docbkx/dev-guide/chap-authenticating.xml 62 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/Main.java
New file
@@ -0,0 +1,210 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opendj3/legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opendj3/legal-notices/CDDLv1_0.txt.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2011 ForgeRock AS
 */
/**
 * An example client application which performs SASL authentication to a
 * directory server, displays a result, and closes the connection.
 *
 * Set up StartTLS before using this example.
 */
package org.forgerock.opendj.examples.saslauth;
import java.security.GeneralSecurityException;
import javax.net.ssl.SSLContext;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.LDAPConnectionFactory;
import org.forgerock.opendj.ldap.LDAPOptions;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SSLContextBuilder;
import org.forgerock.opendj.ldap.TrustManagers;
import org.forgerock.opendj.ldap.requests.PlainSASLBindRequest;
import org.forgerock.opendj.ldap.requests.Requests;
/**
 * An example client application which performs SASL PLAIN authentication to a
 * directory server over LDAP with StartTLS. This example takes the following
 * command line parameters:
 * <ul>
 * <li>host - host name of the directory server</li>
 * <li>port - port number of the directory server for StartTLS, e.g. 1389</li>
 * <li>authzid - (Optional) Authorization identity</li>
 * <li>authcid - Authentication identity</li>
 * <li>passwd - Password of the user to authenticate</li>
 * </ul>
 * The host, port, authcid, and passwd are required.
 * SASL PLAIN is described in <a href="http://www.ietf.org/rfc/rfc4616.txt">RFC
 * 4616</a>.
 * <p>
 * The authzid and authcid are prefixed as described in <a
 * href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513, section
 * 5.2.1.8</a>, with "dn:" if you pass in a distinguished name, or with "u:" if
 * you pass in a user ID.
 * <p>
 * By default, OpenDJ is set up for SASL PLAIN to use the Exact Match Identity
 * Mapper to find entries by searching uid values for the user ID. In other
 * words, the following examples are equivalent.
 * <pre>
 * dn:uid=bjensen,ou=people,dc=example,dc=com
 * u:bjensen
 * </pre>
 */
public final class Main
{
  /**
   * Authenticate to the directory using SASL PLAIN.
   * @param args The command line arguments
   */
  public static void main(String[] args)
  {
    parseArgs(args);
    Connection connection = null;
    try
    {
      final LDAPConnectionFactory factory =
          new LDAPConnectionFactory(host, port, getTrustAllOptions());
      connection = factory.getConnection();
      PlainSASLBindRequest request = Requests.newPlainSASLBindRequest(
          authcid, passwd.toCharArray());
      if (authzid != null) request.setAuthorizationID(authzid);
      connection.bind(request);
      System.out.println("Authenticated as " + authcid + ".");
    }
    catch (final ErrorResultException e)
    {
      System.err.println(e.getMessage());
      System.exit(e.getResult().getResultCode().intValue());
      return;
    }
    catch (final InterruptedException e)
    {
      System.err.println(e.getMessage());
      System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
      return;
    }
    catch (final GeneralSecurityException e)
    {
      System.err.println(e.getMessage());
      System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue());
    }
    finally
    {
      if (connection != null)
        connection.close();
    }
  }
  /**
   * For StartTLS the connection factory needs SSL context options.
   * In the general case, a trust manager in the SSL context serves to check
   * server certificates, and a key manager handles client keys when the server
   * checks certificates from our client.
   *
   * OpenDJ directory server lets you install by default with a self-signed
   * certificate that is not in the system trust store. To simplify this
   * implementation trusts all server certificates.
   */
  private static LDAPOptions getTrustAllOptions()
    throws GeneralSecurityException
  {
    LDAPOptions lo = new LDAPOptions();
    SSLContext sslContext = new SSLContextBuilder()
      .setTrustManager(TrustManagers.trustAll()).getSSLContext();
    lo.setSSLContext(sslContext);
    lo.setUseStartTLS(true);
    return lo;
  }
  private static String host;
  private static int port;
  private static String authzid;
  private static String authcid;
  private static String passwd;
  /**
   * Parse command line arguments.
   * @param args host port [authzid] authcid passwd
   */
  private static void parseArgs(String[] args)
  {
    if (args.length < 4 || args.length > 5) giveUp();
    host = args[0];
    port = Integer.parseInt(args[1]);
    if (args.length == 5)
    {
      authzid = args[2];
      authcid = args[3];
      passwd = args[4];
    }
    else
    {
      authzid = null;
      authcid = args[2];
      passwd = args[3];
    }
  }
  private static void giveUp()
  {
    printUsage();
    System.exit(1);
  }
  private static void printUsage()
  {
    System.err.println(
      "Usage: host port [authzid] authcid passwd");
    System.err.println(
      "\tThe port must be able to handle LDAP with StartTLS.");
    System.err.println(
      "\tSee http://www.ietf.org/rfc/rfc4616.txt for more on SASL PLAIN.");
  }
  private Main()
  {
    // Not used.
  }
}
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/package-info.java
New file
@@ -0,0 +1,32 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opendj3/legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opendj3/legal-notices/CDDLv1_0.txt.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2011 ForgeRock AS
 */
/**
 * An example client application which performs SASL authentication to a
 * directory server, displays a result, and closes the connection.
 */
package org.forgerock.opendj.examples.saslauth;
opendj3/src/main/docbkx/dev-guide/chap-authenticating.xml
@@ -190,6 +190,66 @@
 <section xml:id="sasl-auth">
  <title>SASL Authentication</title>
  
  <para>TODO</para>
  <para>Simple Authentication and Security Layer (SASL) provides a way to
  use other mechanisms for authentication such as Kerberos or Digest
  authentication, or even to define your own authentication mechanism. The
  directory server likely advertises supported SASL mechanisms in the root
  DSE. The follow example shows how to search OpenDJ for supported SASL
  mechanisms.</para>
  <screen>$ ldapsearch
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --baseDN ""
 --searchScope base
 "(objectclass=*)" supportedSASLMechanisms
dn:
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: EXTERNAL
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5</screen>
  <para>Notice that neither the Kerberos (GSSAPI SASL) nor the Anonymous
  mechanism is enabled by default, though OpenDJ implements both.</para>
  <para>In order to use a SASL mechanism to bind, your program must set up
  a <literal>SASLBindRequest</literal> and pass that to the
  <literal>bind()</literal> method of the <literal>Connection</literal>.</para>
  <para>This section shows an example using the SASL PLAIN mechanism, which
  takes either a DN or a user ID to authenticate, with an optional DN or user
  ID as the authorization ID that identifies the user who performs operations.
  The SASL PLAIN mechanism itself does not secure the connection, so the
  example uses StartTLS. The example is provided with the OpenDJ LDAP SDK
  examples in
  <filename>org.forgerock.opendj.examples.saslauth.Main.java</filename>.
  The following excerpt shows the core of the bind process.</para>
  <programlisting language="java">try
{
  final LDAPConnectionFactory factory =
      new LDAPConnectionFactory(host, port, getTrustAllOptions());
  connection = factory.getConnection();
  PlainSASLBindRequest request = Requests.newPlainSASLBindRequest(
      authcid, passwd.toCharArray());
  if (authzid != null) request.setAuthorizationID(authzid);
  connection.bind(request);
  System.out.println("Authenticated as " + authcid + ".");
}</programlisting>
  <para>The implementation for <literal>getTrustAllOptions()</literal>, the
  same as in the example above, sets up Start TLS. When you run this example
  with both authorization and authentication IDs, <literal>authzid</literal>
  and <literal>authcid</literal>, set to <literal>u:bjensen</literal> and
  password <literal>hifalutin</literal>, the bind is successful, and the
  program reaches the final line of the <literal>try</literal> block.</para>
  <screen>Authenticated as u:bjensen.</screen>
  <para>Behind the scenes, OpenDJ has the SASL PLAIN mechanism configured by
  default to use the Exact Match Identity Mapper to look up user IDs as
  <literal>uid</literal> values. If you use another directory server, you might
  have to configure how it maps user IDs to user entries.</para>
 </section>
</chapter>