-
Bug
-
Resolution: Fixed
-
P3
-
1.3.0
-
beta
-
generic
-
generic
Name: yyT116575 Date: 01/30/2001
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)
[also jsse1.0.2]
Instructions:
1. Edit the attached program. Change the values of baseDN and LDAPServer
as necessary for your local environment. LDAPPort should be a port
that accepts anonymous binds but not authenticated binds.
2. Compile and run.
Expected result would be that the authenticated bind:
/* bind to the server */
operation = "bind as principal \"" + principal + "\"";
System.out.println(operation);
ctx = new InitialDirContext(env);
would fail with LDAP error code 13, "Confidentiality required",
which would result in AuthenticationNotSupportedException. Instead,
this results in AuthenticationException:
authenticate("###@###.###", "foo")
anonymous bind
search for "(uid=###@###.###)"
close anonymous connection
authenticated bind ...
bind as principal "emailaddress=###@###.###, ou=Employees,
o=hp.com"
bind as principal "emailaddress=###@###.###, ou=Employees,
o=hp.com" failed: javax.naming.AuthenticationException: [LDAP: error
code 13 - Authenticated binds are only allowed over SSL on port 636]
returns: false
The code needs to be able to distinguish these! LDAP error code 13 is
an administrative error: the code should have used port 636, not 389.
AuthenticationException is supposed to mean "Invalid credentials",
that is, the wrong password.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cut here ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import java.util.Hashtable;
import java.util.Enumeration;
import javax.naming.*;
import javax.naming.directory.*;
/**
* Implements LDAP authentication.
* If SSL is enabled then a Java secure socket implementation
* (like JSSE) needs to be installed in the JVM.
*/
class LDAPAuthenticationProvider
{
/** The distinguished name under which to search for a user name */
private String baseDN = "ou=Employees, o=hp.com";
/** The attribute name that stores the user name */
private String uidAttr = "uid";
/** The host name of the LDAP server */
private String LDAPServer = "ldap.hp.com";
/** Should we use an SSL connection to the LDAP server */
private boolean useSSL = false;
/** The port number of the LDAP server. If useSSL is true,
* this must be the port for SSL connections to the LDAP server
*/
private String LDAPPort = "389";
/** What kind of LDAP authentication to use */
private String authType = "simple";
public boolean authenticate(String userName, String password)
throws Exception
{
System.out.println("authenticate(\"" + userName + "\", \"" + password +
"\")");
Hashtable env = new Hashtable(5, 0.75f);
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
/* Specify host and port to use for directory service */
env.put(Context.PROVIDER_URL, "ldap://" + LDAPServer + ":" + LDAPPort);
if (useSSL) {
env.put(Context.SECURITY_PROTOCOL, "ssl");
}
String operation = null;
DirContext ctx = null;
SearchResult sr = null;
try {
/* get a handle to an Initial DirContext */
operation = "anonymous bind";
System.out.println(operation);
ctx = new InitialDirContext(env);
/* specify search constraints to search subtree */
operation = "search ...";
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
/* search for all entries with the uid */
String target = "(" + uidAttr + "=" + userName +")";
operation = "search for \"" + target + "\"";
System.out.println(operation);
NamingEnumeration results
= ctx.search(baseDN, target, constraints);
operation = "close anonymous connection";
System.out.println(operation);
ctx.close();
if ((results == null) || (!results.hasMore()) ||
((sr = (SearchResult) results.next()) == null)) {
System.out.println("uid not found");
return false;
}
if (results.hasMore()) {
System.out.println(
"multiple search results for uid");
return false;
}
}
catch (InvalidSearchFilterException e) {
String message = operation + " failed: " + e.toString();
System.out.println(message);
return false;
}
catch (NamingException e) {
String message = operation + " failed: " + e.toString();
System.out.println(message);
throw(new Exception(message));
}
catch (Exception e) {
String message = operation + " failed: " + e.toString();
System.out.println(message);
throw(new Exception(message));
}
try {
/* prepare to do authenticated bind */
operation = "authenticated bind ...";
System.out.println(operation);
env.put(Context.SECURITY_AUTHENTICATION, authType);
String principal = sr.getName() + ", " + baseDN;
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, password);
/* bind to the server */
operation = "bind as principal \"" + principal + "\"";
System.out.println(operation);
ctx = new InitialDirContext(env);
operation = "close authenticated connection";
System.out.println(operation);
ctx.close();
}
catch (AuthenticationException e) {
System.out.println(operation + " failed: " + e.toString());
return false;
}
catch (NamingException e) {
String message = operation + " failed: " + e.toString();
System.out.println(message);
throw(new Exception(message));
}
catch (Exception e) {
String message = operation + " failed: " + e.toString();
System.out.println(message);
throw(new Exception(message));
}
return true;
}
public static void main(String args[])
{
LDAPAuthenticationProvider ap = new LDAPAuthenticationProvider();
boolean result;
try {
result = ap.authenticate(args[0], args[1]);
System.out.println("returns: " + result);
}
catch (Exception e) {
System.out.println("caught exception: " + e.toString());
}
}
}
(Review ID: 116055)
======================================================================