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