From 38fc88aa89f1eb893ce43acf49179e4b2b1228c7 Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Tue, 22 Nov 2011 16:16:03 +0000
Subject: [PATCH] Example showing SASL PLAIN authentication

---
 opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/package-info.java |   32 +++++
 opendj3/src/main/docbkx/dev-guide/chap-authenticating.xml                                               |   62 ++++++++++
 opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/Main.java         |  210 +++++++++++++++++++++++++++++++++++
 3 files changed, 303 insertions(+), 1 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/Main.java b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/Main.java
new file mode 100644
index 0000000..f7b2dd4
--- /dev/null
+++ b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/Main.java
@@ -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.
+  }
+}
diff --git a/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/package-info.java b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/package-info.java
new file mode 100644
index 0000000..31ab1aa
--- /dev/null
+++ b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/saslauth/package-info.java
@@ -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;
diff --git a/opendj3/src/main/docbkx/dev-guide/chap-authenticating.xml b/opendj3/src/main/docbkx/dev-guide/chap-authenticating.xml
index a2660f8..a57e9f6 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-authenticating.xml
+++ b/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>
\ No newline at end of file

--
Gitblit v1.10.0