views:

229

answers:

2

I want to connect to a LDAP server using a .p12 certificate instead of using a username and password. The Java solution for this looks like

String ldapURL = "ldaps://"+host+":"+port;   

System.setProperty("javax.net.ssl.keyStoreType", "PKCS12" );  
System.setProperty("javax.net.ssl.keyStore",keystore);
System.setProperty("javax.net.ssl.keyStorePassword", keystorePassword);   

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapURL);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.REFERRAL, "follow");

try 
{
    // Create initial context
    LdapContext ctx = new InitialLdapContext(env, null);
    // Perform client authentication using TLS credentials
    ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "EXTERNAL");

    SearchControls ctls = new SearchControls();
    // Specify the search filter to match
    String filter = "(objectClass=*)";
    // Search for objects using the filter
NamingEnumeration answer = ctx.search("ou="+elemType[i]+","+siteSpecificBaseDN, filter, ctls);

...

Can I do the same using python? I only could find examples showing how to connect to a LDAP server with python-ldap using a username and a password, but that is not what I need. If it is not possible using .p12 certificate, it would also help me, if there is a solution using x509 certificates (.pem format).

A: 

Hi there,

It looks like ldaptor can provide you with this functionality. It's built on top of twisted, which has support for SSL built into the twisted.internet.ssl module.

See: ldaptor.protocols.ldap.ldapclient.startTLS()

HTH,

-aj

AJ
A: 

If you use python-ldap, you can use the TLS options to set these parameters.

ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, "/path/to/trustedcerts.pem")
ldap.set_option(ldap.OPT_X_TLS_CERTFILE, "/path/to/usercert.pem")
ldap.set_option(ldap.OPT_X_TLS_KEYFILE, "/path/to/user.key.pem")

ds = ldap.initialize("ldaps://ldap.example.com:port/")
# If using START_TLS instead of ldaps:
# ds = ldap.initialize("ldap://ldap.example.com:port/")
# ds.start_tls_s()

In this case:

  • trustedcerts.pem is the equivalent of the trust store. It's a concatenation of the trusted certificates you want in PEM format. You could also use a directory with individual certificates with OPT_X_TLS_CACERTFILE, but I think it's not supported by GnuTLS, so it depends on which TLS library python-ldap and its OpenLDAP client library have been compiled against. More details on the underlying direcives in the OpenLDAP manual.
  • usercert.pem is your user certificate, in PEM format (you'll have to extract it from your PKCS#12 file)
  • user.key.pem is your private key (again, it needs to be extracted from the p12 file)

Certificate and key extraction from a PKCS#12 file can be done with OpenSSL using this:

openssl pkcs12 -in userstore.p12 -clcerts -nokeys -out usercert.pem
openssl pkcs12 -in userstore.p12 -nocerts -nodes -out user.key.pem

Note: if you extract the private key (in user.key.pem) this way (-nodes), it will not be password-protected, so you'll need to make sure this file is not readable by anyone else. I don't think OpenLDAP (and even less its Python binding) let you prompt for a password interactively to get around that problem, but I'm not sure.

Bruno