2

I am trying to write a method that, given the information for connecting to and searching an LDAP (e.g., the hostname, base DN, etc., can retrieve an attribute that contains a CA certificate (the "caCertificate" attribute).

I've seen some suggestions about how to do this, but so far have not been able to get one working.

I think that I'm able to do the LDAP search and retrieval but have not been able to figure out how to handle the byte array that is the certificate attribute value.

Here's a snippet of the part I think is working:

        Date theReturnedDate = null;
        String base = "ou=CAs,dc=test,dc=com";
        String filter = "(objectclass=CertificationAuthority)";

        System.out.println("In LDAPUpdate.checkReadLdap: Entering, theLdapCn = [" + theLdapCn + "]...");
    Hashtable envRead = new Hashtable(11);
    envRead.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    envRead.put(Context.PROVIDER_URL, "ldap://my.test.ldap:389");
    envRead.put(Context.SECURITY_AUTHENTICATION, "simple");
    envRead.put(Context.SECURITY_PRINCIPAL, "cn=admin,ou=people,dc=test,dc=com");
    envRead.put(Context.SECURITY_CREDENTIALS, "xxx"); 
    //specify attributes to be returned in binary format
    envRead.put("java.naming.ldap.attributes.binary","caCertificate");


    SearchControls searchCtls = new SearchControls();
    //Specify the attributes to return
    String returnedAtts[]={"caCertificate"};
    searchCtls.setReturningAttributes(returnedAtts);

    DirContext ctx = null;
        try
    {
        // Create the initial directory context
        InitialDirContext initialContext = new InitialDirContext(envRead);
        ctx = (DirContext)initialContext;

        System.out.println("Context Sucessfully Initialized");

        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

        NamingEnumeration results = ctx.search(base, filter, constraints);

        while(results != null && results.hasMore())
        {
            SearchResult sr = (SearchResult) results.next();
            String dn = sr.getName() + "," + base;
            System.out.println("Distinguished Name is " + dn);

            Attributes ar = ctx.getAttributes(dn, returnedAtts);

            if(ar == null)
            {
                System.out.println("Entry " + dn);
                System.out.println(" has none of the specified attributes\n");
            }
            else
            {
                System.out.println("In LDAPUpdate.readCheckLdap: returnedAtts.length=[" + returnedAtts.length + "]");
                for(int i=0; i<returnedAtts.length; i++)
                {
                    Attribute attr = ar.get(returnedAtts[i]);
                    System.out.println(returnedAtts[i] + ":");

                    for(Enumeration vals=attr.getAll(); vals.hasMoreElements();)
                    {
                        System.out.println("\t" + vals.nextElement());
                    }
                }
            }
        }
    }
    catch(Exception e)
    {
        System.err.println(e);
    }

Can anyone tell how to do the rest of what I need, i.e., to take the attribute that is returning with the CA certificate and turn it into an X509Certificate object?

user207421
  • 305,947
  • 44
  • 307
  • 483
user555303
  • 1,146
  • 3
  • 20
  • 44

2 Answers2

1

Can anyone tell how to do the rest of what I need, i.e., to take the attribute that is returning with the CA certificate and turn it into an X509Certificate object?

Something like this:

import java.io.ByteArrayInputStream;
import java.security.cert.*;

CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(bytes));

E&OE

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Hi - What is 'bytes'? Do I get that by doing 'attrs.get("caCertificate")'? If so, when I try what you suggested, I get "The constructor ByteArrayInputStream(Attribute) is undefined". – user555303 Jun 14 '16 at 15:56
  • @user555303 `bytes` is a `byte[]`. – user207421 Mar 25 '19 at 08:42
1

I think that I got it working!

For the record, here is full working example. I left some debug code in there that might be helpful. This will bind to an LDAP server, then retrieve an entry then extract the caCertificate attribute into an X509Certificate object. Then, it displays the Subject DN from the X509Certificate to test that the object was instantiated ok.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;


public class GoodReadACertFromLdap{

public static void main(String[] args) {

    System.out.println("This Java application demonstrates how to retrieve a caCertificate object from an LDAP server");

    Hashtable env = new Hashtable(11);
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://myldapserver:389/");
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, "cn=directory manager");
    env.put(Context.SECURITY_CREDENTIALS, "XXXX");
    Object cert = null;
    Attributes attrs = null;
    Attribute attr = null;

      try {
            LdapContext ctx = new InitialLdapContext(env, null);
            ctx.setRequestControls(null);
            NamingEnumeration<?> namingEnum = ctx.search("CN=mycert,ou=CAs,dc=whatever,dc=com", "(objectclass=*)", getSimpleSearchControls());
            while (namingEnum.hasMore ()) {
                SearchResult result = (SearchResult) namingEnum.next ();    
                attrs = result.getAttributes ();
                System.out.println(attrs.get("cn"));
                cert = attrs.get("caCertificate;binary");
                System.out.println(cert);
                System.out.println(attrs.get("objectclass"));

            } 
            namingEnum.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

      if (((Attribute)cert).size() == 0) {
          System.out.println("The cert attribute was cert.size == 0!");
          System.exit(0);
      }

      System.out.println("The cert attribute cert.size was NOT 0, so will now try to make it into a certificate object!");
      System.out.println("The cert attribute cert.size was: [" + ((Attribute)cert).size() + "]");
      System.out.println("Here's cert again: [" + cert + "]");

      try {
          X509Certificate certOut = null;
          CertificateFactory cf = CertificateFactory.getInstance("X.509");

          attr = attrs.get("caCertificate;binary");     // get the caCertificate attribute so we can make a NamingEnumeration from it...
          for (NamingEnumeration e = attr.getAll();e.hasMore();) {
            try {
                 ByteArrayInputStream bais = new ByteArrayInputStream( (byte[])e.next());
                 certOut = (X509Certificate)cf.generateCertificate(bais);
            } catch (Exception ex ) {
                System.out.println("While converting Attribute object to a X509Certificate, EXCEPTION = " + ex);
            } // end catch()
          }

          System.out.println("certOut.getSubjectDN = [" + certOut.getSubjectDN() + "]");


      } catch (Exception e) {
          e.printStackTrace();
      }

} // end main()



private static SearchControls getSimpleSearchControls() {
    SearchControls searchControls = new SearchControls();
    searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    searchControls.setTimeLimit(30000);
    String[] attrIDs = {"cn", "caCertificate", "objectclass"};
    searchControls.setReturningAttributes(attrIDs);
    return searchControls;
} // end getSimpleSearchControls()



} // end CLASS
user555303
  • 1,146
  • 3
  • 20
  • 44