1
votes

If one uses ldapsearch to search a particular LDAP server for base level naming contexts, the search works fine.

$ ldapsearch -h myhealthisp.com -p 10389 -x -s base -b "" namingContexts
# extended LDIF
#
# LDAPv3
# base <> (default) with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#

#
dn:
namingContexts: dc=myhealthisp,dc=com

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1`

Using the JNDI, however, we get the following response:

No Results for: myhealthisp.com. Problem: [LDAP: error code 32 - No Such Object] null

Here's our code:

private Attribute getCertFromLdap(SRVRecord srvRec, CertificateInfo certInfo) throws CertLookUpException{
    env.put(DirContext.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    sc1 = new SearchControls();
    sc1.setSearchScope(SearchControls.ONELEVEL_SCOPE);

try {
        env.put(DirContext.PROVIDER_URL, "ldap://" + targetDomain + ":" + srvRec.getPort());        
        System.out.println("ldap://" + targetDomain + ":" + srvRec.getPort());

        DirContext dc = new InitialDirContext(env);
        NamingEnumeration directoryNE = null;

        System.out.println("Got HERE!");
        directoryNE= dc.search("", "objectClass=*", sc1);

        System.out.println("SC1 :" + sc1);
        while (directoryNE.hasMore()){
                        SearchResult result1 = (SearchResult) directoryNE.next();

            // print DN of entry
            System.out.println("Result.getNameInNamespace: " + result1.getName());
            Attribute foundMail = findMailAttribute(result1.getNameInNamespace()); 

            if(foundMail != null){
                return foundMail;
            }
        }       
        dc.close(); 
} catch (NamingException e) {
    System.out.println("No Results for: " + targetDomain + "\nProblem: " +     e.getLocalizedMessage() + "  " + e.getCause());
} return null;

}

The only way that we are able to return the base directories for myhealthisp.com is by hard coding the directory name (dc=myhealthisp,dc=com) into the base directory search filter (see this for what we are basing our code off of: http://directory.apache.org/apacheds/manuals/basic-user-guide-1.5.8-SNAPSHOT/html/ch03s03.html#LDAP Operations Searching)

When our code searches onctest.org LDAP server, we are given each of the namingContexts back.

Here's the output to the Eclipse console for both the onctest.org server and the myhealthisp.com server:

ldap://onctest.org.:10389
Got HERE!
SC1 :javax.naming.directory.SearchControls@4c408bfc
Result.getNameInNamespace: ou=config
Result.getNameInNamespace: dc=example,dc=com
Result.getNameInNamespace: ou=system
Search Result: cn=dts556: null:null:{mail=mail: [email protected],     usercertificate=userCertificate: [B@35e06ba6, objectclass=objectClass: organizationalPerson,     person, inetOrgPerson, top, o=o: onctest, sn=sn: Test Case, cn=cn: dts556}

Service Record: _ldap._tcp.onctEst.org. 86400   IN  SRV 0 0 10389 onctest.org.
ldap://myhealthisp.com.:10389
Got HERE!
No Results for: myhealthisp.com.
Problem: [LDAP: error code 32 - No Such Object]  null
Unable to find certificate at LDAP for: [email protected]
_ldap._tcp.myhealthisp.com. 3600    IN  SRV 0 0 10389 myhealthisp.com.

We think that the following is causing the problem:

  • JDNI cannot do a base search for OpenLDAProotDSE objectClass directories.
2

2 Answers

2
votes

Generally anonymous bind doesnt have privilege to do a ldap search on the root. Every directory has the OOTB privileges for anonymous bind and searching the root. In case of apache DS, a search of the naming contexts can be done via the ldap query

ldapsearch -h localhost -p 10389 -s base -b "" "(objectclass=*)" namingContexts

However, a one level search of subtree search such as

ldapsearch -h localhost-p 10389 -s one -b "" -D "uid=admin,ou=system" -w secret "(objectclass=*)"

Gives the following result: which is what you are doing in the jndi program: ldap_search: No such object ldap_search: additional info: NO_SUCH_OBJECT: failed for SearchRequest baseDn : '' filter : '(2.5.4.0=*)' scope : single level typesOnly : false Size Limit : no limit Time Limit : no limit Deref Aliases : never Deref Aliases attributes : : null

JNDI code for the first ldapsearch command :

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class SampleLDAPSearch {

  private Attribute getCertFromLdap() {
      String targetDomain = "localhost";
      String port = "10389";

      Hashtable env = new Hashtable();
      env.put(DirContext.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      SearchControls sc1 = new SearchControls();
      sc1.setSearchScope(SearchControls.OBJECT_SCOPE);
      sc1.setReturningAttributes(new String[] { "namingContexts" });

      try {
          env.put(DirContext.PROVIDER_URL, "ldap://" + targetDomain + ":" + port);

          System.out.println("ldap://" + targetDomain + ":" + port);

          DirContext dc = new InitialDirContext(env);
          NamingEnumeration directoryNE = null;

          System.out.println("Got HERE!");
          directoryNE = dc.search("", "objectclass=*", sc1);

          System.out.println("SC1 :" + sc1);
          while (directoryNE.hasMore()) {
              SearchResult result1 = (SearchResult) directoryNE.next();

              // print DN of entry
              System.out.println("Result.getNameInNamespace: " + result1.getName());
              Attributes attrs = result1.getAttributes();
              Attribute attr = attrs.get("namingContexts");
              System.out.println(attr);

          }
          dc.close();
      } catch (NamingException e) {
          System.out.println("No Results for: " + targetDomain + "\nProblem: " + e.getLocalizedMessage() + "  "
                  + e.getCause());
      }
      return null;

  }

  public static void main(String[] args) {
      SampleLDAPSearch sls = new SampleLDAPSearch();
      sls.getCertFromLdap();
  }
}
0
votes

The Root DSE must not appear when the search level is not base. Further more, LDAP clients must not depend on the information contained in the root DSE because those attribute might be protected by access controls. From RFC4512:

These attributes are retrievable, subject to access control and other
restrictions, if a client performs a Search operation [RFC4511] with
an empty baseObject, scope of baseObject, the filter
"(objectClass=*)" [RFC4515], and the attributes field listing the
names of the desired attributes.  It is noted that root DSE
attributes are operational and, like other operational attributes,
are not returned in search requests unless requested by name.

Change the search scope to base. Better still, do not write code that depends on objects being retrieved from the root DSE.

see also