User Tools

Site Tools


LDAP Integration

ILRI uses an Active Directory server for user authentication, which is primarily used for Exchange e-mail services. Active Directory is Microsoft's proprietary version of LDAP with a little extra special sauce. Currently users have an Active Directory username and password for their Windows-centric single sign on and e-mail, and then they have a separate account for use with the HPC. There exists functionality in Linux to look at Active Directory for user authentication.


Active Directory integration will work if we use Likewise-Open. It has been tested in a virtual server environment, but requires a few network changes to work on the HPC:

  • HPC must have the correct time (AD authenticates via Kerberos, which is heavily sensitive to time)
  • HPC must be able to access AD on several TCP ports (kerberos, LDAP, etc)


Apache Authentication

It's possible to use Basic authentication via Active Directory in web applications.

Make sure Apache has mod_perl installed and working first:

# apt-get install libapache2-mod-perl2 libapache2-mod-perl2-dev
# a2enmod perl
# apache2ctl graceful

Install the required perl dependencies for Apache and LDAP:

# apt-get install libauthen-simple-ldap-perl

Install the required AD Auth package and any dependencies it has using CPAN:

$ sudo cpan
> install Apache2::AuthenMSAD

Then add a stanza such as this to your Apache config:

   AuthName "Microsoft Active Directory Authentication"
   AuthType Basic

   PerlAuthenHandler Apache2::AuthenMSAD
   PerlSetVar MSADDomain
   PerlSetVar MSADServer

   #require valid-user
   require user aorth akihara

That stanza can go in a VirtualHost, a Directory, a Location, etc… restart Apache and you're golden.


Open source standalone implementation of Samba, OpenLDAP, Kerberos, etc for Active Directory integration:

  • open ports in Firewall (Active Directory, NTP, Kerberos)
  • make sure time is in sync with the server! NTP must be configured correctly before installing AD integration
  • Likewise-Open has their own CIFS server but can also work with existing Samba installs I think

Using ldapsearch on Linux

Try to search from a Linux machine which can talk to the AD server (HPC is behind firewall):

ldapsearch -x -H ldap:// -b "dc=ilri,dc=cgiarad,dc=org" -D "cn=bioinfohpc,cn=users,dc=ilri,dc=cgiarad,dc=org" -W "(sAMAccountName=bioinfohpc)"
[aorth@shamba: ~]$ ldapsearch -x -H ldap:// -b "dc=ilri,dc=cgiard,dc=org" -D "cn=bioinfohpc,cn=users,dc=ilri,dc=cgiard,dc=org" -W ""
Enter LDAP Password: 
ldap_bind: Invalid credentials (49)
        additional info: 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece

According to the web this error means the user does not exist. Either I've specified the user's distinguished name incorrectly, or the account is not configured with the proper permissions to bind:

HEX: 0×525 – user not found
DEC: 1317 – ERROR_NO_SUCH_USER (The specified account does not exist.)
NOTE: Returns when username is invalid.


A note of possible interest regarding binding on Linux (from the samba mailing list):

AD domain controllers listen on the standard LDAPS port (636) and will only accept binds on that port.
You cannot bind as a user on port 389.  I don't think they support TLS on port 389, but I have no tried in a
 long time.

Domain controller vs. Global catalog

As ILRI has many AD domains and our users could be coming from anywhere, we need to query a server running the global catalog service instead of a normal domain controller. This note is of help:

All Windows 2000/2003 AD domain controllers (including Global Catalog Servers) listen for LDAP requests
 on the standard LDAP port 389. However, domain controllers (including Global Catalog Servers) respond to LDAP
 queries on port 389 with AD information from within its own AD domain only. Again, this works fine in a single
 domain configuration but not in a multi-domain setup. Global Catalog Servers additionally listen for LDAP 
requests on port 3268, Microsoft's AD LDAP port. Global Catalog Servers respond to LDAP queries on port 3268
 with AD information from the entire AD forest. In multi-domain AD environments, it is best to use port 3268.

ILRI Kenya has three Active Directory servers, and from what I can tell two of them run a global catalog:

  • ← running a global catalog (port 3268)
  • ← running a global catalog (port 3268)


Someone hacked up a PAM module several years ago which could be dropped into a Linux server and allow AD authentication with minimal configuration. See the documentation here: cgiar-hpc-cop.doc

This no longer works! It relied on anonymous access to the AD server, but ILRI's Active Directory servers are configured to disallow anonymous binds. These notes have been left here for reference only!

This was working once, using a slightly customized PAM module, but broken when IT services disabled anonymous binding. In order to use the module several steps are needed. Download the module source and edit the code to point to the correct server, then compile it as shown below:

  • Compile the code: gcc -fPIC -c pam_cgiar_ldap.c
  • Link the code: ld -x –shared –lldap -o pam_cgiar_ldap.o


#define DEFAULT_USER "nobody"
#include <stdio.h>
 * here, we make definitions for the externally accessible functions
 * in this file (these definitions are required for static modules
 * but strongly encouraged generally) they are used to instruct the
 * modules include file to define their prototypes.
#define PAM_SM_AUTH
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <lber.h> //for ldap
#include <ldap.h> //for ldap
#include <string.h> //added by lavila
#include <syslog.h> //added by Alan to compile on newer Linux
int testBind(char* loginDN, char* password)
  struct timeval timeOut = {10,0};    /* 10 second connection timeout */
  int returnValue=0;
  char* pass2;
  char tempPass[100];
  //syslog (LOG_ERR, "pam_cgiar_ldap: user %s, password %s",loginDN,password );
  LDAP *ld;
  int version = LDAP_VERSION3;
  ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
  ldap_set_option( NULL, LDAP_OPT_NETWORK_TIMEOUT, &timeOut);
  ld = ldap_init("" , 389 );
  if (ld==NULL) printf("\nproblems connecting\n");
  int rc;
  //if (ldap_simple_bind_s( ld, loginDN,password)!= LDAP_SUCCESS )
  if (ldap_simple_bind_s( ld, loginDN,password)!= LDAP_SUCCESS )
      returnValue =0;
      syslog (LOG_ERR, "pam_cgiar_ldap: -->ldap authentication failed");
  syslog (LOG_ERR, "pam_cgiar_ldap: -->ldap authentication ok");
  FILE* outFile;
  outFile=fopen ("/salida.txt","w");
 // if (rc==PAM_SUCCESS)
  fprintf(outFile,"\nPassword: %s\n",password);
//  return(0);
  return (returnValue);
/* --- authentication management functions --- */
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv)
    int retval,rc;
    const char *user=NULL;
    char *p;
//syslog (LOG_ERR, "illegal option %s", argv[i]);
     * authentication requires we know who the user wants to be
    retval = pam_get_user(pamh, &user, NULL);
    if (retval != PAM_SUCCESS) {
	D(("get user returned error: %s", pam_strerror(pamh,retval)));
	return retval;
   // rc=pam_get_item (pamh, PAM_AUTHTOK, (const void **) &p);
    if (user == NULL || *user == '\0') {
	D(("username not known"));
	retval = pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER);
	if (retval != PAM_SUCCESS)
	    return PAM_USER_UNKNOWN;
   // user = NULL;                                            /* clean up */
   // return PAM_SUCCESS;
  //changes introduced by lavila
 // I still cannot put this module on top of the stack
 // I have to put it at least on second place
 // or my password information returns null when using get_itme
 //maybe I should use pam_start to load pamh
  rc=pam_get_item (pamh, PAM_AUTHTOK, (const void **) &p);
 // if (rc == PAM_SUCCESS)
   char luser[100];
 // if (p!=NULL)
 /* {
    FILE* outFile;
    outFile=fopen ("/salida.txt","w");
    fprintf(outFile,"\nPassword1: %s\n",p);
    rc = testBind(luser,p);
    rc = testBind(luser,p);
//  rc=0;
 if (rc==1) 
  return PAM_SUCCESS;
 else return PAM_AUTH_ERR;
	   // return PAM_USER_UNKNOWN;
   //lavila, en esta funcion debo hacer la validacion
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
		   ,const char **argv)
     return PAM_SUCCESS;
//	    return PAM_USER_UNKNOWN;
/* --- account management functions --- */
int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
		     ,const char **argv)
     return PAM_SUCCESS;
/* --- password management --- */
int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc
		     ,const char **argv)
     return PAM_SUCCESS;
/* --- session management --- */
int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
			,const char **argv)
    return PAM_SUCCESS;
int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
			 ,const char **argv)
     return PAM_SUCCESS;
/* end of module definition */
/* static module data */
/*struct pam_module_pam_permit_modstruct = {
struct pam_module_pam_cgiar_ldap_modstruct = {
ldap_integration.txt · Last modified: 2012/02/06 08:43 by aorth