[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: ldap() in shared objects...



Jason Gerfen wrote:

I have compiled a shared object (PAM module to be exact) which utilizes some ldap() API calls. I have noticed a discrepency in making a call to ldap_simple_bind_s().

According to the man pages for ldap_simple_bind_s() I need to do a check against LDAP_SUCCESS as a returned status message.

here is the code I am using for a regular binary:
/* open a connection & failover if necessary */
z = 0;
ld = ldap_init( servs[z], LDAP_PORT );
while( ldap_simple_bind_s( ld, "username", "password" ) != LDAP_SUCCESS ) {
rc = ldap_result( ld, msgid, z, &zerotime, &res );


where do you get the msgid?  what's that call to ldap_result() for?
ldap_result() must be called only after an ASYNCHRONOUS call,
while ldap_simple_bind_s() is SYNCHRONOUS.


if( ( z < 5 ) || ( rc == -1 ) ) { ld = ldap_init( servs[z], LDAP_PORT ); } printf( "Bind failed on: %s\n", servs[z]); z++; } ldap_perror( ld, "ldap_simple_bind_s");

This works fine,

I can hardly believe it.

now if I perform the same check as a shared object any attempt to check against LDAP_SUCCESS fails, as of yet i have only been able to do the following to get it to work:

/* open a connection & failover if necessary */
z = 0;
ld = ldap_init( servs[z], LDAP_PORT );
while( ! ldap_simple_bind_s( ld, "ldapaccess", "access6ldap" ) ) {

note that you can't bind with "username" or "ldapaccess"; you need to turn that
into a valid DN, because ldap_*_bind_*() calls (and the LDAP BIND operation
they implement) require a DN as user identifier. Please read the API documentation.



rc = ldap_result( ld, msgid, z, &zerotime, &res ); if( ( z < 5 ) || ( rc == -1 ) ) { ld = ldap_init( servs[z], LDAP_PORT ); } printf( "Bind failed on: %s\n", servs[z]); z++; } ldap_perror( ld, "ldap_simple_bind_s");

has anyone else ran into this problem?

here are my compile commands if this is necessary:
binary: gcc -o search ldap.c -lldap
shared object: gcc -fPIC -o pam_ldap.o -c pam_ldap.c
ld -x --shared -o pam_ldap.so pam_ldap.o -lpam -lldap


If what you intend to do is some sort of failover, in case one of the hosts is down,
all you need to do is provide ldap_init() a space separated list of hosts, like
"host1 host2 host#" (I suggest you also look at the ldap_initialize() call, which
I note is currently undocumented).


Your code should look like

/*
* This code comes with no copyright nor WARRANTY
*/

#include <stdio.h>
#include <ldap.h>

extern char *username2dn( char * );

int
your_func(void)
{
   LDAP *ld;
   int rc;
   char *hosts = "host1 host2 host#"; /* to be read from config */
   int port = LDAP_PORT; /* to be read from config */
   char *username, *credentials; /* you get these from PAM */
   char *dn;

   ld = ldap_init( hosts, port );
   if ( ld == NULL ) {
       /* error; handle it! */
   }

/* you need a way to turn PAM's username into a valid DN by implement this function */
dn = username2dn( username );
if ( dn == NULL ) {
/* error; handle it! */
}


   rc = ldap_simple_bind_s( ld, dn, credentials );

   /* do all cleanup here */

switch ( rc ) {
case LDAP_SUCCESS:
/* authenticated; take measures */
puts( "success\n" );
break;
case LDAP_INVALID_CREDENTIALS:
/* not authenticated; take measures */
puts( "invalid credentials\n" );
break;
default:
/* something happened; trap all protocol/API errors that may be significant to you */
printf( "%s\n", ldap_str2error() );
break;
}
return 0;
}





SysNet - via Dossi,8 27100 Pavia Tel: +390382573859 Fax: +390382476497