9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.jndi.ldap.sasl;
27
28 import java.io.*;
29 import java.util.Vector;
30 import java.util.Hashtable;
31 import java.util.StringTokenizer;
32
33 import javax.naming.AuthenticationException;
34 import javax.naming.AuthenticationNotSupportedException;
35 import javax.naming.NamingException;
36
37 import javax.naming.ldap.Control;
38
39 import javax.security.auth.callback.CallbackHandler;
40 import javax.security.sasl.*;
41 import com.sun.jndi.ldap.Connection;
42 import com.sun.jndi.ldap.LdapClient;
43 import com.sun.jndi.ldap.LdapResult;
44
45 /**
46 * Handles SASL support.
47 *
48 * @author Vincent Ryan
49 * @author Rosanna Lee
50 */
51
52 final public class LdapSasl {
53 // SASL stuff
54 private static final String SASL_CALLBACK = "java.naming.security.sasl.callback";
55 private static final String SASL_AUTHZ_ID =
56 "java.naming.security.sasl.authorizationId";
57 private static final String SASL_REALM =
58 "java.naming.security.sasl.realm";
59
60 private static final int LDAP_SUCCESS = 0;
61 private static final int LDAP_SASL_BIND_IN_PROGRESS = 14; // LDAPv3
62
63 private LdapSasl() {
93 public static LdapResult saslBind(LdapClient clnt, Connection conn,
94 String server, String dn, Object pw,
95 String authMech, Hashtable<?,?> env, Control[] bindCtls)
96 throws IOException, NamingException {
97
98 SaslClient saslClnt = null;
99 boolean cleanupHandler = false;
100
101 // Use supplied callback handler or create default
102 CallbackHandler cbh =
103 (env != null) ? (CallbackHandler)env.get(SASL_CALLBACK) : null;
104 if (cbh == null) {
105 cbh = new DefaultCallbackHandler(dn, pw, (String)env.get(SASL_REALM));
106 cleanupHandler = true;
107 }
108
109 // Prepare parameters for creating SASL client
110 String authzId = (env != null) ? (String)env.get(SASL_AUTHZ_ID) : null;
111 String[] mechs = getSaslMechanismNames(authMech);
112
113 try {
114 // Create SASL client to use using SASL package
115 saslClnt = Sasl.createSaslClient(
116 mechs, authzId, "ldap", server, (Hashtable<String, ?>)env, cbh);
117
118 if (saslClnt == null) {
119 throw new AuthenticationNotSupportedException(authMech);
120 }
121
122 LdapResult res;
123 String mechName = saslClnt.getMechanismName();
124 byte[] response = saslClnt.hasInitialResponse() ?
125 saslClnt.evaluateChallenge(NO_BYTES) : null;
126
127 res = clnt.ldapBind(null, response, bindCtls, mechName, true);
128
129 while (!saslClnt.isComplete() &&
130 (res.status == LDAP_SASL_BIND_IN_PROGRESS ||
131 res.status == LDAP_SUCCESS)) {
132
133 response = saslClnt.evaluateChallenge(
134 res.serverCreds != null? res.serverCreds : NO_BYTES);
135 if (res.status == LDAP_SUCCESS) {
136 if (response != null) {
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.jndi.ldap.sasl;
27
28 import java.io.*;
29 import java.security.cert.X509Certificate;
30 import java.util.Vector;
31 import java.util.Hashtable;
32 import java.util.StringTokenizer;
33
34 import javax.naming.AuthenticationException;
35 import javax.naming.AuthenticationNotSupportedException;
36 import javax.naming.NamingException;
37
38 import javax.naming.ldap.Control;
39
40 import javax.security.auth.callback.CallbackHandler;
41 import javax.security.sasl.*;
42 import com.sun.jndi.ldap.Connection;
43 import com.sun.jndi.ldap.LdapClient;
44 import com.sun.jndi.ldap.LdapResult;
45 import com.sun.jndi.ldap.sasl.TlsChannelBinding.TlsChannelBindingType;
46
47 /**
48 * Handles SASL support.
49 *
50 * @author Vincent Ryan
51 * @author Rosanna Lee
52 */
53
54 final public class LdapSasl {
55 // SASL stuff
56 private static final String SASL_CALLBACK = "java.naming.security.sasl.callback";
57 private static final String SASL_AUTHZ_ID =
58 "java.naming.security.sasl.authorizationId";
59 private static final String SASL_REALM =
60 "java.naming.security.sasl.realm";
61
62 private static final int LDAP_SUCCESS = 0;
63 private static final int LDAP_SASL_BIND_IN_PROGRESS = 14; // LDAPv3
64
65 private LdapSasl() {
95 public static LdapResult saslBind(LdapClient clnt, Connection conn,
96 String server, String dn, Object pw,
97 String authMech, Hashtable<?,?> env, Control[] bindCtls)
98 throws IOException, NamingException {
99
100 SaslClient saslClnt = null;
101 boolean cleanupHandler = false;
102
103 // Use supplied callback handler or create default
104 CallbackHandler cbh =
105 (env != null) ? (CallbackHandler)env.get(SASL_CALLBACK) : null;
106 if (cbh == null) {
107 cbh = new DefaultCallbackHandler(dn, pw, (String)env.get(SASL_REALM));
108 cleanupHandler = true;
109 }
110
111 // Prepare parameters for creating SASL client
112 String authzId = (env != null) ? (String)env.get(SASL_AUTHZ_ID) : null;
113 String[] mechs = getSaslMechanismNames(authMech);
114
115 // Internal TLS Channel Binding property cannot be set explicitly
116 if (env.get(TlsChannelBinding.CHANNEL_BINDING) != null) {
117 throw new NamingException(TlsChannelBinding.CHANNEL_BINDING +
118 " property cannot be set explicitly");
119 }
120
121 Hashtable<String, Object> envProps = (Hashtable<String, Object>) env;
122
123 try {
124 // Prepare TLS Channel Binding data
125 if (conn.isTlsConnection()) {
126 TlsChannelBindingType cbType =
127 TlsChannelBinding.parseType(
128 (String)env.get(TlsChannelBinding.CHANNEL_BINDING_TYPE));
129 if (cbType == TlsChannelBindingType.TLS_SERVER_END_POINT) {
130 // set tls-server-end-point channel binding
131 X509Certificate cert = conn.getTlsServerCertificate();
132 if (cert != null) {
133 TlsChannelBinding tlsCB =
134 TlsChannelBinding.create(cert);
135 envProps = (Hashtable<String, Object>) env.clone();
136 envProps.put(TlsChannelBinding.CHANNEL_BINDING, tlsCB.getData());
137 } else {
138 throw new SaslException("No suitable certificate to generate " +
139 "TLS Channel Binding data");
140 }
141 }
142 }
143
144 // Create SASL client to use using SASL package
145 saslClnt = Sasl.createSaslClient(
146 mechs, authzId, "ldap", server, envProps, cbh);
147
148 if (saslClnt == null) {
149 throw new AuthenticationNotSupportedException(authMech);
150 }
151
152 LdapResult res;
153 String mechName = saslClnt.getMechanismName();
154 byte[] response = saslClnt.hasInitialResponse() ?
155 saslClnt.evaluateChallenge(NO_BYTES) : null;
156
157 res = clnt.ldapBind(null, response, bindCtls, mechName, true);
158
159 while (!saslClnt.isComplete() &&
160 (res.status == LDAP_SASL_BIND_IN_PROGRESS ||
161 res.status == LDAP_SUCCESS)) {
162
163 response = saslClnt.evaluateChallenge(
164 res.serverCreds != null? res.serverCreds : NO_BYTES);
165 if (res.status == LDAP_SUCCESS) {
166 if (response != null) {
|