I'm maintaining some legacy Java LDAP code. I know next to nothing about LDAP.
The program below basically just sends the userid and password to the LDAP server, receives notification back if the credentials are good. If so, it prints out the LDAP attributes received from the LDAP server, if not it prints out an exception.
All works well if a bad password is given. An "invalid credentials" exception gets thrown. However, if a blank password is sent to the LDAP Server, authentication will still happen, LDAP attributes will still be returned.
Is this unhappy situation due to the LDAP server allowing blank passwords, or does the code below need to be adjusted such a blank password will get fed to the LDAP server in such a way so it will get rejected?
I do have data validation in place. I took it off in a testing environment to solve another issue and noticed this problem. I would prefer not to have this problem underneath the data validation.
Thanks much in advance for any information
import javax.naming.*;
import javax.naming.directory.*;
import java.util.*;
import java.sql.*;
public class LDAPTEST {
public static void main(String args[]) {
String lcf = "com.sun.jndi.ldap.LdapCtxFactory";
String ldapurl = "ldaps://ldap-cit.smew.acme.com:636/o=acme.com";
String loginid = "George.Jetson";
String password = "";
DirContext ctx = null;
Hashtable env = new Hashtable();
Attributes attr = null;
Attributes resultsAttrs = null;
SearchResult result = null;
NamingEnumeration results = null;
int iResults = 0;
int iAttributes = 0;
env.put(Context.INITIAL_CONTEXT_FACTORY, lcf);
env.put(Context.PROVIDER_URL, ldapurl);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=" + loginid + ",ou=People,o=acme.com");
env.put(Context.SECURITY_CREDENTIALS, password);
try {
ctx = new InitialDirContext(env);
attr = new BasicAttributes(true);
attr.put(new BasicAttribute("uid",loginid));
results = ctx.search("ou=People",attr);
while (results.hasMore()) {
result = (SearchResult)results.next();
resultsAttrs = result.getAttributes();
for (NamingEnumeration enumAttributes = resultsAttrs.getAll(); enumAttributes.hasMore();) {
Attribute a = (Attribute)enumAttributes.next();
System.out.println("attribute: " + a.getID() + " : " + a.get().toString());
iAttributes++;
}// end for loop
iResults++;
}// end while loop
System.out.println("Records == " + iResults + " Attributes: " + iAttributes);
}// end try
catch (Exception e) {
e.printStackTrace();
}
}// end function main()
}// end class LDAPTEST
Unfortunately, the authentication with a DN and an empty password is one of the difficiency of LDAP, and results in an "unauthenticated" positive response from the server. Some LDAP servers have configuration options to disable that behavior that has been discouraged in the latest revision of LDAPv3 (RFC 4511), and even have it disabled by default.
Ultimately, the client application should check input parameters and make sure the password is not empty.
You need to change authentication method from simple (which is not something to use in an production environment anyways, at least not without SSL).
As it is stated here: http://docs.oracle.com/javase/jndi/tutorial/ldap/security/simple.html
If you supply an empty string, an empty byte/char array, or null to the Context.SECURITY_CREDENTIALS environment property, then the authentication mechanism will be "none". This is because the LDAP requires the password to be nonempty for simple authentication. The protocol automatically converts the authentication to "none" if a password is not supplied.
There are two types of BIND operations, simple
and SASL
. In the case of the simple BIND, there are four possibilities:
anonymous
, no authentication takes place. This is the initial state, and also the state when a BIND request is received by the serverunauthenticated
, no authentication takes placeWhen a connection is initially established, the connection is anonymous
. Each BIND request resets the connection state to anonymous
. Each successful BIND request changes the authorization state of the connection to that of the distinguished name. Each unsuccessful BIND request leaves the connection unauthenticated.
The semantics of BIND are defined in LDAP: Authentication
What happens when you send an "empty" password is the authentication (ie bind) is done as anonymous.
Your code could be modified to detect an empty password or userid to stop this activity.
Some LDAP implementaitons can stop any anonymous binds.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With