View Javadoc

1   /*
2    * CDDL HEADER START
3    *
4    * The contents of this file are subject to the terms of the
5    * Common Development and Distribution License, Version 1.0 only
6    * (the "License").  You may not use this file except in compliance
7    * with the License.
8    *
9    * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
10   * or http://forgerock.org/license/CDDLv1.0.html.
11   * See the License for the specific language governing permissions
12   * and limitations under the License.
13   *
14   * When distributing Covered Code, include this CDDL HEADER in each
15   * file and include the License file at legal-notices/CDDLv1_0.txt.
16   * If applicable, add the following below this CDDL HEADER, with the
17   * fields enclosed by brackets "[]" replaced with your own identifying
18   * information:
19   *      Portions Copyright [yyyy] [name of copyright owner]
20   *
21   * CDDL HEADER END
22   *
23   *
24   *      Copyright 2011-2012 ForgeRock AS
25   */
26  
27  /**
28   * An example client application which performs SASL authentication to a
29   * directory server, displays a result, and closes the connection.
30   *
31   * Set up StartTLS before using this example.
32   */
33  package org.forgerock.opendj.examples;
34  
35  import java.security.GeneralSecurityException;
36  
37  import javax.net.ssl.SSLContext;
38  
39  import org.forgerock.opendj.ldap.Connection;
40  import org.forgerock.opendj.ldap.ErrorResultException;
41  import org.forgerock.opendj.ldap.LDAPConnectionFactory;
42  import org.forgerock.opendj.ldap.LDAPOptions;
43  import org.forgerock.opendj.ldap.ResultCode;
44  import org.forgerock.opendj.ldap.SSLContextBuilder;
45  import org.forgerock.opendj.ldap.TrustManagers;
46  import org.forgerock.opendj.ldap.requests.PlainSASLBindRequest;
47  import org.forgerock.opendj.ldap.requests.Requests;
48  
49  /**
50   * An example client application which performs SASL PLAIN authentication to a
51   * directory server over LDAP with StartTLS. This example takes the following
52   * command line parameters:
53   * <ul>
54   * <li>host - host name of the directory server</li>
55   * <li>port - port number of the directory server for StartTLS, e.g. 1389</li>
56   * <li>authzid - (Optional) Authorization identity</li>
57   * <li>authcid - Authentication identity</li>
58   * <li>passwd - Password of the user to authenticate</li>
59   * </ul>
60   * The host, port, authcid, and passwd are required. SASL PLAIN is described in
61   * <a href="http://www.ietf.org/rfc/rfc4616.txt">RFC 4616</a>.
62   * <p>
63   * The authzid and authcid are prefixed as described in <a
64   * href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513, section
65   * 5.2.1.8</a>, with "dn:" if you pass in a distinguished name, or with "u:" if
66   * you pass in a user ID.
67   * <p>
68   * By default, OpenDJ is set up for SASL PLAIN to use the Exact Match Identity
69   * Mapper to find entries by searching uid values for the user ID. In other
70   * words, the following examples are equivalent.
71   *
72   * <pre>
73   * dn:uid=bjensen,ou=people,dc=example,dc=com
74   * u:bjensen
75   * </pre>
76   */
77  public final class SASLAuth {
78      /**
79       * Authenticate to the directory using SASL PLAIN.
80       *
81       * @param args
82       *            The command line arguments
83       */
84      public static void main(String[] args) {
85          parseArgs(args);
86          Connection connection = null;
87  
88          try {
89              final LDAPConnectionFactory factory =
90                      new LDAPConnectionFactory(host, port, getTrustAllOptions());
91              connection = factory.getConnection();
92              PlainSASLBindRequest request =
93                      Requests.newPlainSASLBindRequest(authcid, passwd.toCharArray());
94              if (authzid != null) {
95                  request.setAuthorizationID(authzid);
96              }
97              connection.bind(request);
98              System.out.println("Authenticated as " + authcid + ".");
99          } catch (final ErrorResultException e) {
100             System.err.println(e.getMessage());
101             System.exit(e.getResult().getResultCode().intValue());
102             return;
103         } catch (final GeneralSecurityException e) {
104             System.err.println(e.getMessage());
105             System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue());
106         } finally {
107             if (connection != null) {
108                 connection.close();
109             }
110         }
111     }
112 
113     /**
114      * For StartTLS the connection factory needs SSL context options. In the
115      * general case, a trust manager in the SSL context serves to check server
116      * certificates, and a key manager handles client keys when the server
117      * checks certificates from our client.
118      *
119      * OpenDJ directory server lets you install by default with a self-signed
120      * certificate that is not in the system trust store. To simplify this
121      * implementation trusts all server certificates.
122      */
123     private static LDAPOptions getTrustAllOptions() throws GeneralSecurityException {
124         LDAPOptions lo = new LDAPOptions();
125         SSLContext sslContext =
126                 new SSLContextBuilder().setTrustManager(TrustManagers.trustAll()).getSSLContext();
127         lo.setSSLContext(sslContext);
128         lo.setUseStartTLS(true);
129         return lo;
130     }
131 
132     private static String host;
133     private static int port;
134     private static String authzid;
135     private static String authcid;
136     private static String passwd;
137 
138     /**
139      * Parse command line arguments.
140      *
141      * @param args
142      *            host port [authzid] authcid passwd
143      */
144     private static void parseArgs(String[] args) {
145         if (args.length < 4 || args.length > 5) {
146             giveUp();
147         }
148 
149         host = args[0];
150         port = Integer.parseInt(args[1]);
151 
152         if (args.length == 5) {
153             authzid = args[2];
154             authcid = args[3];
155             passwd = args[4];
156         } else {
157             authzid = null;
158             authcid = args[2];
159             passwd = args[3];
160         }
161     }
162 
163     private static void giveUp() {
164         printUsage();
165         System.exit(1);
166     }
167 
168     private static void printUsage() {
169         System.err.println("Usage: host port [authzid] authcid passwd");
170         System.err.println("\tThe port must be able to handle LDAP with StartTLS.");
171         System.err.println("\tSee http://www.ietf.org/rfc/rfc4616.txt for more on SASL PLAIN.");
172     }
173 
174     private SASLAuth() {
175         // Not used.
176     }
177 }