Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java, LDAP: Make it not ignore blank passwords?

Tags:

java

ldap

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
like image 471
Steve Avatar asked Sep 10 '12 21:09

Steve


4 Answers

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.

like image 198
Ludovic Poitou Avatar answered Oct 15 '22 07:10

Ludovic Poitou


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.

like image 20
Tobb Avatar answered Oct 15 '22 07:10

Tobb


There are two types of BIND operations, simple and SASL. In the case of the simple BIND, there are four possibilities:

  • empty DN and empty password: anonymous, no authentication takes place. This is the initial state, and also the state when a BIND request is received by the server
  • non-empty DN, empty password: unauthenticated, no authentication takes place
  • non-empty DN, non-emptypassword: the normal case, authentication is attempted
  • empty DN, non-empty password: server behavior is not defined in the LDAP standards. No authentication takes place.

When 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

like image 4
Terry Gardner Avatar answered Oct 15 '22 06:10

Terry Gardner


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.

like image 1
jwilleke Avatar answered Oct 15 '22 08:10

jwilleke