Posts Tagged ‘ University of Illinois

Authenticating against UIUC Active Directory (AD) using Python

So in a follow up to my earlier post, here is the equivalent code to authenticate against UIUC Active Directory using Python:

ldap_auth.py:

import ldap

def authenticate(netid, password):
    server = "ldaps://ad.uiuc.edu:636"
    who = "CN="+netid+",OU=Campus Accounts,DC=ad,DC=uiuc,DC=edu"
    try:
        conn = ldap.initialize(server)
        ldap.set_option( ldap.OPT_X_TLS_DEMAND, True )
        ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER)
        result = conn.simple_bind_s(who,password)
    except ldap.LDAPError, e:
        return False
    conn.unbind()
    return True

print authenticate("cemeyer2", "password")

That’s it. As mentioned in my earlier post, I’m pretty sure that any application that authenticates this way would be looked down upon by CITES since the application in question would potentially be able to sniff user login information, so please only use this code in a personal testing environment, not for a deployed application unless approved by people much higher up than me.

Authenticating against UIUC Active Directory (AD) using Java

So in recent weeks I have become interested in means of authenticating users against sources such as Active Directory at UIUC. Although the UIUC domain controllers support Kerberos authentication, I have decided to implement a simpler LDAPS based method due to LDAP being included in the JRE. The code I wrote up looks something like:

LDAPAuth.java:

import java.util.Hashtable;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

public class LDAPAuth {

	public static void main(String[] args)
	{
		System.out.println(authenticate("cemeyer2","password"));
	}

	public static boolean authenticate(String netid, String password)
	{
		String userDN = findUserDN(netid);
		try
		{
			LdapContext ctx = createLDAPContext(userDN, password);
			ctx.close();
			return true;
		}
		catch(Exception e)
		{
			return false;
		}
	}

	private static String findUserDN(String netid)
	{
		return "CN="+netid+",OU=Campus Accounts,DC=ad,DC=uiuc,DC=edu";
	}

	private static LdapContext createLDAPContext(String bindDN, String bindPassword) throws NamingException
	{
		Hashtable env = new Hashtable();
		env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
		env.put("java.naming.provider.url", "ldaps://ad.uiuc.edu/");
		env.put("java.naming.ldap.factory.socket", "TrustAllSSLSocketFactory");
		env.put("java.naming.security.protocol", "ssl");
		env.put("java.naming.security.principal", bindDN);
		env.put("java.naming.security.credentials", bindPassword);
		env.put("java.naming.security.authentication", "simple");
		env.put("com.sun.jndi.ldap.connect.pool", "true");
		LdapContext context = new InitialLdapContext(env, null);
		return context;
	}
}

And in the same package (default package in this example), TrustAllSSLSocketFactory.java:

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class TrustAllSSLSocketFactory extends SSLSocketFactory
{
    private static class TrustAllTrustManager
        implements X509TrustManager
    {

        public void checkClientTrusted(X509Certificate ax509certificate[], String s1)
            throws CertificateException
        {
        }

        public void checkServerTrusted(X509Certificate ax509certificate[], String s1)
            throws CertificateException
        {
        }

        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[0];
        }

        private TrustAllTrustManager()
        {
        }

    }

    public TrustAllSSLSocketFactory()
    {
        try
        {
            SSLContext sslcontent = SSLContext.getInstance("TLS");
            sslcontent.init(null, new TrustManager[] {
                new TrustAllTrustManager()
            }, new SecureRandom());
            _factory = sslcontent.getSocketFactory();
        }
        catch(Throwable t)
        {
        	//do nothing
        }
    }

    public static SocketFactory getDefault()
    {
        return new TrustAllSSLSocketFactory();
    }

    public Socket createSocket(Socket socket, String s, int i, boolean flag)
        throws IOException
    {
        return _factory.createSocket(socket, s, i, flag);
    }

    public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr2, int j)
        throws IOException
    {
        return _factory.createSocket(inaddr, i, inaddr2, j);
    }

    public Socket createSocket(InetAddress inaddr, int i)
        throws IOException
    {
        return _factory.createSocket(inaddr, i);
    }

    public Socket createSocket(String s, int i, InetAddress inaddr, int j)
        throws IOException
    {
        return _factory.createSocket(s, i, inaddr, j);
    }

    public Socket createSocket(String s, int i)
        throws IOException
    {
        return _factory.createSocket(s, i);
    }

    public String[] getDefaultCipherSuites()
    {
        return _factory.getSupportedCipherSuites();
    }

    public String[] getSupportedCipherSuites()
    {
        return _factory.getSupportedCipherSuites();
    }

    private SSLSocketFactory _factory;

}

Once that’s done, using the static LDAPAuth.authenticate() method will allow you to authenticate users against UIUC Active Directory over LDAPS without the need for an AD service account. But I’m pretty sure that any application that authenticates this way would be looked down upon by CITES since the application in question would potentially be able to sniff user login information, so please only use this code in a personal testing environment, not for a deployed application unless approved by people much higher up than me.

Good Luck!