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

LDAP API questions



I have some questions regarding the differences between OpenLDAP's 
libraries and the Netscape LDAP C SDK 3.0.  My goal is to develop 
an LDAP client that can be linked against either library.

I've included pseudo code for my LDAP client, below.  It is based 
upon various example programs and the book _Programming 
Directory-Enabled Applications with LDAP_ by Tim Howes and Mark Smith.  

My LDAP client is a daemon which allows network clients to connect 
and interactively issue one or more queries consisting of LDAP filter 
strings.  The base dn and attribute list are predefined by the 
application and cannot be changed by the user.

I'm using a Red Hat Linux 6.1 i386 distribution, but I've replaced 
their OpenLDAP packages with ones that I've built myself.  I'm using 
OpenLDAP 1.2.9 with BerkeleyDB 2.7.7.  I've populated the database 
and I can search it successfully with the ldapsearch program, with 
some custom PerLDAP scripts, and also with my LDAP client.

My questions:

  1.  How do you distinguish between the various LDAP SDK's, 
      programmatically?  Currently, if the LDAP_OPT_SIZELIMIT symbol 
      is defined, I assume that I'm using Netscape's SDK.  I selected 
      that symbol somewhat arbitrarily.

      Is there a better way to do this?

  2.  What differences exist in the LDAP API supplied by the various 
      LDAP SDK's?  Some differences that I know of are: 

      a. Netscape wants to treat the LDAP session handle (eg. LDAP *ld) 
         as an opaque structure, and therefore supplies functions to get 
         at its internals.  This affects how the programmer gets at 
         ld_errno, for example.  

      b. OpenLDAP returns a char pointer from ldap_first_attribute() and 
         ldap_next_attribute(), to a static buffer.  Therefore, you must 
         not free() the returned pointer.  The Netscape documentation 
         tells you to call ldap_memfree() on the pointer returned by 
         ldap_first_attribute() and ldap_next_attribute().  Note that 
         OpenLDAP has no ldap_memfree() function.

      c. OpenLDAP documents the ber_free() function, while Netscape's 
         documentation talks about ldap_ber_free().  However, Netscape's 
         example programs use ber_free() and that function *is* in their 
         library.  The book I cited above also uses ber_free().

      d. The Netscape SDK requires you to link in a threads library (eg. 
         -lpthread).  I have the Netscape SDK with SSL support.  I have not 
         used the one without SSL, so I don't know if it is any different. 
         This caused a problem for my application, which is not threaded. 
         My application would become wedged in __sigsuspend() after having 
         several of its clients connect and/or disconnect simultaneously. 
         Not being familiar with debugging threaded programs, my solution 
         was to switch to the OpenLDAP SDK.  This "solved" the problem.

      e. When using the OpenLDAP SDK, you will not normally call ber_free() 
         following the classic for(...) loop to fetch an entry's attributes.  
         Doing so will eventually cause a SIGSEGV (ie. a segmentation 
         violation).  This is because OpenLDAP's ldap_next_attribute() has 
         already freed the BerElement when it returns NULL, signaling the 
         end of the entry's attributes.  With the Netscape SDK, you *do* 
         need to call ber_free() (or ldap_ber_free(); see above).

      What other differences exist between LDAP SDK's?

I would appreciate hearing from anyone who has used more than one LDAP 
SDK.  Thanks in advance.


-- cut here for LDAP client pseudo code --

new_client() {
	connect();
	while ((filter = fgets(...)) != NULL) {
		search();
	}
	disconnect();
}

connect() {
	ld = ldap_init(host,port);
	ldap_simple_bind_s(ld,NULL,NULL);
}

search() {
	ldap_search_s(ld,base,scope,filter,attrs,attrsonly,&result);
	n = ldap_count_entries(ld,result);
	for (e = ldap_first_entry(ld,result); e != NULL;
		e = ldap_next_entry(ld,e)) {

		dn = ldap_get_dn(ld,e);
		for (a = ldap_first_attribute(ld,e,&ber); a != NULL;
			a = ldap_next_attribute(ld,e,ber)) {

			vals = ldap_get_values(ld,e,a);
#if (LDAP_SDK == NETSCAPE)
			ldap_memfree(a);
#endif
		}
#if (LDAP_SDK == NETSCAPE)
		if (ber != NULL)
			ldap_ber_free(ber,0);
#endif
#if (LDAP_SDK == OPENLDAP)
		if (a != NULL)
			ber_free(ber,0);
#endif
	}
	ldap_msgfree(result);
	/* memory for dn and vals gets freed before next search() */
}

disconnect() {
	ldap_unbind(ld);
}

-- end pseudo code --

-- 
Thomas J. Pinkl                         738 Louis Drive
Unix Systems Programmer                 Warminster, Pa 18974
Health Business Systems, Inc.           (215) 442-9300 x9260