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 }