2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Functions necessary to access LDAP servers.
32 #include <gtk/gtkmain.h>
38 /* #include <dlfcn.h> */
42 #include "addrcache.h"
47 * Create new LDAP server interface object.
49 SyldapServer *syldap_create() {
50 SyldapServer *ldapServer;
52 debug_print("Creating LDAP server interface object\n");
54 ldapServer = g_new0( SyldapServer, 1 );
55 ldapServer->name = NULL;
56 ldapServer->hostName = NULL;
57 ldapServer->port = SYLDAP_DFL_PORT;
58 ldapServer->baseDN = NULL;
59 ldapServer->bindDN = NULL;
60 ldapServer->bindPass = NULL;
61 ldapServer->searchCriteria = NULL;
62 ldapServer->searchValue = NULL;
63 ldapServer->entriesRead = 0;
64 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
65 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
66 ldapServer->newSearch = TRUE;
67 ldapServer->addressCache = addrcache_create();
68 ldapServer->thread = NULL;
69 ldapServer->busyFlag = FALSE;
70 ldapServer->retVal = MGU_SUCCESS;
71 ldapServer->callBack = NULL;
72 ldapServer->accessFlag = FALSE;
73 ldapServer->idleId = 0;
78 * Specify name to be used.
80 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
81 ldapServer->name = mgu_replace_string( ldapServer->name, value );
82 g_strstrip( ldapServer->name );
86 * Specify hostname to be used.
88 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
89 addrcache_refresh( ldapServer->addressCache );
90 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
91 g_strstrip( ldapServer->hostName );
95 * Specify port to be used.
97 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
98 addrcache_refresh( ldapServer->addressCache );
100 ldapServer->port = value;
103 ldapServer->port = SYLDAP_DFL_PORT;
108 * Specify base DN to be used.
110 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
111 addrcache_refresh( ldapServer->addressCache );
112 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
113 g_strstrip( ldapServer->baseDN );
117 * Specify bind DN to be used.
119 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
120 addrcache_refresh( ldapServer->addressCache );
121 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
122 g_strstrip( ldapServer->bindDN );
126 * Specify bind password to be used.
128 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
129 addrcache_refresh( ldapServer->addressCache );
130 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
131 g_strstrip( ldapServer->bindPass );
135 * Specify search criteria to be used.
137 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
138 addrcache_refresh( ldapServer->addressCache );
139 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
140 g_strstrip( ldapServer->searchCriteria );
141 ldapServer->newSearch = TRUE;
145 * Specify search value to be searched for.
147 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
148 addrcache_refresh( ldapServer->addressCache );
149 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
150 g_strstrip( ldapServer->searchValue );
151 ldapServer->newSearch = TRUE;
155 * Specify maximum number of entries to retrieve.
157 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
158 addrcache_refresh( ldapServer->addressCache );
160 ldapServer->maxEntries = value;
163 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
168 * Specify timeout value for LDAP operation (in seconds).
170 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
171 addrcache_refresh( ldapServer->addressCache );
173 ldapServer->timeOut = value;
176 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
181 * Register a callback function. When called, the function will be passed
182 * this object as an argument.
184 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
185 ldapServer->callBack = func;
188 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
189 g_return_if_fail( ldapServer != NULL );
190 ldapServer->accessFlag = value;
194 * Refresh internal variables to force a file read.
196 void syldap_force_refresh( SyldapServer *ldapServer ) {
197 addrcache_refresh( ldapServer->addressCache );
198 ldapServer->newSearch = TRUE;
201 gint syldap_get_status( SyldapServer *ldapServer ) {
202 g_return_val_if_fail( ldapServer != NULL, -1 );
203 return ldapServer->retVal;
206 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
207 g_return_val_if_fail( ldapServer != NULL, NULL );
208 return addrcache_get_root_folder( ldapServer->addressCache );
211 gchar *syldap_get_name( SyldapServer *ldapServer ) {
212 g_return_val_if_fail( ldapServer != NULL, NULL );
213 return ldapServer->name;
216 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
217 g_return_val_if_fail( ldapServer != NULL, FALSE );
218 return ldapServer->accessFlag;
222 * Free up LDAP server interface object by releasing internal memory.
224 void syldap_free( SyldapServer *ldapServer ) {
225 g_return_if_fail( ldapServer != NULL );
227 debug_print("Freeing LDAP server interface object\n");
229 ldapServer->callBack = NULL;
231 /* Free internal stuff */
232 g_free( ldapServer->name );
233 g_free( ldapServer->hostName );
234 g_free( ldapServer->baseDN );
235 g_free( ldapServer->bindDN );
236 g_free( ldapServer->bindPass );
237 g_free( ldapServer->searchCriteria );
238 g_free( ldapServer->searchValue );
239 g_free( ldapServer->thread );
241 ldapServer->port = 0;
242 ldapServer->entriesRead = 0;
243 ldapServer->maxEntries = 0;
244 ldapServer->newSearch = FALSE;
247 addrcache_clear( ldapServer->addressCache );
248 addrcache_free( ldapServer->addressCache );
251 ldapServer->name = NULL;
252 ldapServer->hostName = NULL;
253 ldapServer->baseDN = NULL;
254 ldapServer->bindDN = NULL;
255 ldapServer->bindPass = NULL;
256 ldapServer->searchCriteria = NULL;
257 ldapServer->searchValue = NULL;
258 ldapServer->addressCache = NULL;
259 ldapServer->thread = NULL;
260 ldapServer->busyFlag = FALSE;
261 ldapServer->retVal = MGU_SUCCESS;
262 ldapServer->accessFlag = FALSE;
264 /* Now release LDAP object */
265 g_free( ldapServer );
270 * Display object to specified stream.
272 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
273 g_return_if_fail( ldapServer != NULL );
275 fprintf( stream, "SyldapServer:\n" );
276 fprintf( stream, " name: '%s'\n", ldapServer->name );
277 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
278 fprintf( stream, " port: %d\n", ldapServer->port );
279 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
280 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
281 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
282 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
283 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
284 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
285 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
286 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
287 addrcache_print( ldapServer->addressCache, stream );
288 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
292 * Display object to specified stream.
294 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
295 g_return_if_fail( ldapServer != NULL );
297 fprintf( stream, "SyldapServer:\n" );
298 fprintf( stream, " name: '%s'\n", ldapServer->name );
299 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
300 fprintf( stream, " port: %d\n", ldapServer->port );
301 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
302 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
303 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
304 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
305 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
306 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
307 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
308 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
312 * Build an address list entry and append to list of address items. Name is formatted
313 * as it appears in the common name (cn) attribute.
315 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
318 GSList *nodeName = listName;
321 GSList *nodeAddress = listAddr;
322 person = addritem_create_item_person();
323 addritem_person_set_common_name( person, nodeName->data );
324 addrcache_id_person( ldapServer->addressCache, person );
325 addrcache_add_person( ldapServer->addressCache, person );
327 while( nodeAddress ) {
328 email = addritem_create_item_email();
329 addritem_email_set_address( email, nodeAddress->data );
330 addrcache_id_email( ldapServer->addressCache, email );
331 addrcache_person_add_email( ldapServer->addressCache, person, email );
332 nodeAddress = g_slist_next( nodeAddress );
333 ldapServer->entriesRead++;
335 nodeName = g_slist_next( nodeName );
340 * Build an address list entry and append to list of address items. Name is formatted
341 * as "<first-name> <last-name>".
343 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
344 GSList *nodeFirst = listFirst;
345 GSList *nodeAddress = listAddr;
346 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
347 gint iLen = 0, iLenT = 0;
351 /* Find longest first name in list */
353 if( firstName == NULL ) {
354 firstName = nodeFirst->data;
355 iLen = strlen( firstName );
358 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
359 firstName = nodeFirst->data;
363 nodeFirst = g_slist_next( nodeFirst );
368 lastName = listLast->data;
373 fullName = g_strdup_printf( "%s %s", firstName, lastName );
376 fullName = g_strdup_printf( "%s", firstName );
381 fullName = g_strdup_printf( "%s", lastName );
385 g_strchug( fullName ); g_strchomp( fullName );
389 person = addritem_create_item_person();
390 addritem_person_set_common_name( person, fullName );
391 addritem_person_set_first_name( person, firstName );
392 addritem_person_set_last_name( person, lastName );
393 addrcache_id_person( ldapServer->addressCache, person );
394 addrcache_add_person( ldapServer->addressCache, person );
397 /* Add address item */
398 while( nodeAddress ) {
399 email = addritem_create_item_email();
400 addritem_email_set_address( email, nodeAddress->data );
401 addrcache_id_email( ldapServer->addressCache, email );
402 addrcache_person_add_email( ldapServer->addressCache, person, email );
403 nodeAddress = g_slist_next( nodeAddress );
404 ldapServer->entriesRead++;
407 fullName = firstName = lastName = NULL;
412 * Add all attribute values to a list.
414 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
419 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
420 for( i = 0; vals[i] != NULL; i++ ) {
421 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
422 list = g_slist_append( list, g_strdup( vals[i] ) );
425 ldap_value_free( vals );
430 * Add a single attribute value to a list.
432 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
436 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
437 if( vals[0] != NULL ) {
438 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
439 list = g_slist_append( list, g_strdup( vals[0] ) );
442 ldap_value_free( vals );
447 * Free linked lists of character strings.
449 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
450 mgu_free_list( listName );
451 mgu_free_list( listAddr );
452 mgu_free_list( listID );
453 mgu_free_list( listDN );
454 mgu_free_list( listFirst );
455 mgu_free_list( listLast );
459 * Check parameters that are required for a search. This should
460 * be called before performing a search.
461 * Return: TRUE if search criteria appear OK.
463 gboolean syldap_check_search( SyldapServer *ldapServer ) {
464 g_return_val_if_fail( ldapServer != NULL, FALSE );
466 ldapServer->retVal = MGU_LDAP_CRITERIA;
468 /* Test search criteria */
469 if( ldapServer->searchCriteria == NULL ) {
472 if( strlen( ldapServer->searchCriteria ) < 1 ) {
476 if( ldapServer->searchValue == NULL ) {
479 if( strlen( ldapServer->searchValue ) < 1 ) {
483 ldapServer->retVal = MGU_SUCCESS;
488 * Perform the LDAP search, reading LDAP entries into cache.
489 * Note that one LDAP entry can have multiple values for many of its
490 * attributes. If these attributes are E-Mail addresses; these are
491 * broken out into separate address items. For any other attribute,
492 * only the first occurrence is read.
494 gint syldap_search( SyldapServer *ldapServer ) {
496 LDAPMessage *result, *e;
502 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
503 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
504 struct timeval timeout;
505 gboolean entriesFound = FALSE;
507 g_return_val_if_fail( ldapServer != NULL, -1 );
509 ldapServer->retVal = MGU_SUCCESS;
510 if( ! syldap_check_search( ldapServer ) ) {
511 return ldapServer->retVal;
515 timeout.tv_sec = ldapServer->timeOut;
516 timeout.tv_usec = 0L;
518 ldapServer->entriesRead = 0;
519 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
520 ldapServer->retVal = MGU_LDAP_INIT;
521 return ldapServer->retVal;
524 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
526 /* Bind to the server, if required */
527 if( ldapServer->bindDN ) {
528 if( * ldapServer->bindDN != '\0' ) {
529 /* printf( "binding...\n" ); */
530 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
531 /* printf( "rc=%d\n", rc ); */
532 if( rc != LDAP_SUCCESS ) {
533 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
535 ldapServer->retVal = MGU_LDAP_BIND;
536 return ldapServer->retVal;
541 /* Define all attributes we are interested in. */
542 attribs[0] = SYLDAP_ATTR_DN;
543 attribs[1] = SYLDAP_ATTR_COMMONNAME;
544 attribs[2] = SYLDAP_ATTR_GIVENNAME;
545 attribs[3] = SYLDAP_ATTR_SURNAME;
546 attribs[4] = SYLDAP_ATTR_EMAIL;
547 attribs[5] = SYLDAP_ATTR_UID;
550 /* Create LDAP search string and apply search criteria */
551 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
552 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
553 &timeout, 0, &result );
556 if( rc == LDAP_TIMEOUT ) {
558 ldapServer->retVal = MGU_LDAP_TIMEOUT;
559 return ldapServer->retVal;
561 if( rc != LDAP_SUCCESS ) {
562 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
564 ldapServer->retVal = MGU_LDAP_SEARCH;
565 return ldapServer->retVal;
568 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
570 /* Clear the cache if we have new entries, otherwise leave untouched. */
571 if( ldap_count_entries( ld, result ) > 0 ) {
572 addrcache_clear( ldapServer->addressCache );
575 /* Process results */
576 ldapServer->entriesRead = 0;
577 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
579 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
580 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
582 /* Process all attributes */
583 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
584 attribute = ldap_next_attribute( ld, e, ber ) ) {
585 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
586 listName = syldap_add_list_values( ld, e, attribute );
588 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
589 listAddress = syldap_add_list_values( ld, e, attribute );
591 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
592 listID = syldap_add_single_value( ld, e, attribute );
594 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
595 listFirst = syldap_add_list_values( ld, e, attribute );
597 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
598 listLast = syldap_add_single_value( ld, e, attribute );
600 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
601 listDN = syldap_add_single_value( ld, e, attribute );
605 /* Free memory used to store attribute */
606 ldap_memfree( attribute );
608 /* Format and add items to cache */
609 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
612 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
613 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
620 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
621 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
623 /* Free up and disconnect */
624 ldap_msgfree( result );
626 ldapServer->newSearch = FALSE;
628 ldapServer->retVal = MGU_SUCCESS;
631 ldapServer->retVal = MGU_LDAP_NOENTRIES;
633 return ldapServer->retVal;
636 /* syldap_display_search_results() - updates the ui. this function is called from the
637 * main thread (the thread running the GTK event loop). */
638 static gint syldap_display_search_results(SyldapServer *ldapServer)
640 /* NOTE: when this function is called the accompanying thread should
641 * already be terminated. */
642 gtk_idle_remove(ldapServer->idleId);
643 ldapServer->callBack(ldapServer);
644 /* FIXME: match should know whether to free this SyldapServer stuff. */
645 g_free(ldapServer->thread);
646 ldapServer->thread = NULL;
650 /* ============================================================================================ */
652 * Read data into list. Main entry point
653 * Return: TRUE if file read successfully.
655 /* ============================================================================================ */
656 gint syldap_read_data( SyldapServer *ldapServer ) {
657 g_return_val_if_fail( ldapServer != NULL, -1 );
659 ldapServer->accessFlag = FALSE;
660 pthread_detach( pthread_self() );
661 if( ldapServer->newSearch ) {
662 /* Read data into the list */
663 syldap_search( ldapServer );
666 ldapServer->addressCache->modified = FALSE;
667 ldapServer->addressCache->dataRead = TRUE;
668 ldapServer->accessFlag = FALSE;
672 ldapServer->busyFlag = FALSE;
673 if( ldapServer->callBack ) {
674 /* make the ui thread update the search results */
675 /* TODO: really necessary to call gdk_threads_XXX()??? gtk_idle_add()
676 * should do this - could someone check the GTK sources please? */
678 ldapServer->idleId = gtk_idle_add((GtkFunction)syldap_display_search_results, ldapServer);
682 return ldapServer->retVal;
685 /* ============================================================================================ */
687 * Cancel read with thread.
689 /* ============================================================================================ */
690 void syldap_cancel_read( SyldapServer *ldapServer ) {
691 g_return_if_fail( ldapServer != NULL );
693 /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */
694 if( ldapServer->thread ) {
695 /* printf( "thread cancelled\n" ); */
696 pthread_cancel( *ldapServer->thread );
698 g_free(ldapServer->thread);
699 ldapServer->thread = NULL;
700 ldapServer->busyFlag = FALSE;
703 /* ============================================================================================ */
705 * Read data into list using a background thread.
706 * Return: TRUE if file read successfully. Callback function will be
707 * notified when search is complete.
709 /* ============================================================================================ */
710 gint syldap_read_data_th( SyldapServer *ldapServer ) {
711 g_return_val_if_fail( ldapServer != NULL, -1 );
713 ldapServer->busyFlag = FALSE;
714 syldap_check_search( ldapServer );
715 if( ldapServer->retVal == MGU_SUCCESS ) {
716 /* debug_print("Staring LDAP read thread\n"); */
718 ldapServer->busyFlag = TRUE;
719 ldapServer->thread = g_new0(pthread_t, 1);
720 pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer );
722 return ldapServer->retVal;
726 * Return link list of persons.
728 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
729 g_return_val_if_fail( ldapServer != NULL, NULL );
730 return addrcache_get_list_person( ldapServer->addressCache );
734 * Return link list of folders. This is always NULL since there are
735 * no folders in GnomeCard.
738 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
739 g_return_val_if_fail( ldapServer != NULL, NULL );
743 #define SYLDAP_TEST_FILTER "(objectclass=*)"
744 #define SYLDAP_SEARCHBASE_V2 "cn=config"
745 #define SYLDAP_SEARCHBASE_V3 ""
746 #define SYLDAP_V2_TEST_ATTR "database"
747 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
750 * Attempt to discover the base DN for the server.
754 * bindDN Bind DN (optional).
755 * bindPW Bind PW (optional).
756 * tov Timeout value (seconds), or 0 for none, default 30 secs.
757 * Return: List of Base DN's, or NULL if could not read. Base DN should
758 * be g_free() when done.
760 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
761 GList *baseDN = NULL;
764 LDAPMessage *result, *e;
769 struct timeval timeout;
771 if( host == NULL ) return baseDN;
772 if( port < 1 ) return baseDN;
775 timeout.tv_usec = 0L;
777 timeout.tv_sec = tov;
780 timeout.tv_sec = 30L;
783 /* Connect to server. */
784 if( ( ld = ldap_init( host, port ) ) == NULL ) {
788 /* Bind to the server, if required */
790 if( *bindDN != '\0' ) {
791 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
792 if( rc != LDAP_SUCCESS ) {
793 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
800 /* Test for LDAP version 3 */
801 attribs[0] = SYLDAP_V3_TEST_ATTR;
803 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
804 0, NULL, NULL, &timeout, 0, &result );
805 if( rc == LDAP_SUCCESS ) {
806 /* Process entries */
807 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
808 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
810 /* Process attributes */
811 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
812 attribute = ldap_next_attribute( ld, e, ber ) ) {
813 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
814 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
815 for( i = 0; vals[i] != NULL; i++ ) {
816 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
817 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
820 ldap_value_free( vals );
823 ldap_memfree( attribute );
828 ldap_msgfree( result );
833 if( baseDN == NULL ) {
834 /* Test for LDAP version 2 */
836 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
837 0, NULL, NULL, &timeout, 0, &result );
838 if( rc == LDAP_SUCCESS ) {
839 /* Process entries */
840 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
841 /* if( baseDN ) break; */
842 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
844 /* Process attributes */
845 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
846 attribute = ldap_next_attribute( ld, e, ber ) ) {
847 /* if( baseDN ) break; */
848 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
849 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
850 for( i = 0; vals[i] != NULL; i++ ) {
852 /* Strip the 'ldb:' from the front of the value */
853 ch = ( char * ) strchr( vals[i], ':' );
855 gchar *bn = g_strdup( ++ch );
858 baseDN = g_list_append( baseDN, g_strdup( bn ) );
862 ldap_value_free( vals );
865 ldap_memfree( attribute );
870 ldap_msgfree( result );
878 * Attempt to discover the base DN for the server.
879 * Enter: ldapServer Server to test.
880 * Return: List of Base DN's, or NULL if could not read. Base DN should
881 * be g_free() when done. Return code set in ldapServer.
883 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
884 GList *baseDN = NULL;
887 LDAPMessage *result, *e;
892 struct timeval timeout;
894 ldapServer->retVal = MGU_BAD_ARGS;
895 if( ldapServer == NULL ) return baseDN;
896 if( ldapServer->hostName == NULL ) return baseDN;
897 if( ldapServer->port < 1 ) return baseDN;
900 timeout.tv_usec = 0L;
901 if( ldapServer->timeOut > 0 ) {
902 timeout.tv_sec = ldapServer->timeOut;
905 timeout.tv_sec = 30L;
908 /* Connect to server. */
909 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
910 ldapServer->retVal = MGU_LDAP_INIT;
914 /* Bind to the server, if required */
915 if( ldapServer->bindDN ) {
916 if( *ldapServer->bindDN != '\0' ) {
917 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
918 if( rc != LDAP_SUCCESS ) {
919 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
921 ldapServer->retVal = MGU_LDAP_BIND;
927 ldapServer->retVal = MGU_LDAP_SEARCH;
929 /* Test for LDAP version 3 */
930 attribs[0] = SYLDAP_V3_TEST_ATTR;
932 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
933 0, NULL, NULL, &timeout, 0, &result );
934 if( rc == LDAP_SUCCESS ) {
935 /* Process entries */
936 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
937 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
939 /* Process attributes */
940 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
941 attribute = ldap_next_attribute( ld, e, ber ) ) {
942 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
943 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
944 for( i = 0; vals[i] != NULL; i++ ) {
945 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
946 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
949 ldap_value_free( vals );
952 ldap_memfree( attribute );
957 ldap_msgfree( result );
958 ldapServer->retVal = MGU_SUCCESS;
960 else if( rc == LDAP_TIMEOUT ) {
961 ldapServer->retVal = MGU_LDAP_TIMEOUT;
964 if( baseDN == NULL ) {
965 /* Test for LDAP version 2 */
967 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
968 0, NULL, NULL, &timeout, 0, &result );
969 if( rc == LDAP_SUCCESS ) {
970 /* Process entries */
971 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
972 /* if( baseDN ) break; */
973 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
975 /* Process attributes */
976 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
977 attribute = ldap_next_attribute( ld, e, ber ) ) {
978 /* if( baseDN ) break; */
979 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
980 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
981 for( i = 0; vals[i] != NULL; i++ ) {
983 /* Strip the 'ldb:' from the front of the value */
984 ch = ( char * ) strchr( vals[i], ':' );
986 gchar *bn = g_strdup( ++ch );
989 baseDN = g_list_append( baseDN, g_strdup( bn ) );
993 ldap_value_free( vals );
996 ldap_memfree( attribute );
1001 ldap_msgfree( result );
1002 ldapServer->retVal = MGU_SUCCESS;
1004 else if( rc == LDAP_TIMEOUT ) {
1005 ldapServer->retVal = MGU_LDAP_TIMEOUT;
1014 * Attempt to connect to the server.
1018 * Return: TRUE if connected successfully.
1020 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1021 gboolean retVal = FALSE;
1024 if( host == NULL ) return retVal;
1025 if( port < 1 ) return retVal;
1026 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1036 * Attempt to connect to the server.
1037 * Enter: ldapServer Server to test.
1038 * Return: TRUE if connected successfully. Return code set in ldapServer.
1040 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1041 gboolean retVal = FALSE;
1044 ldapServer->retVal = MGU_BAD_ARGS;
1045 if( ldapServer == NULL ) return retVal;
1046 if( ldapServer->hostName == NULL ) return retVal;
1047 if( ldapServer->port < 1 ) return retVal;
1048 ldapServer->retVal = MGU_LDAP_INIT;
1049 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1050 ldapServer->retVal = MGU_SUCCESS;
1059 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
1060 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
1061 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1062 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1065 * Test whether LDAP libraries installed.
1066 * Return: TRUE if library available.
1069 gboolean syldap_test_ldap_lib() {
1073 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1078 /* Test for symbols we need */
1079 fun = dlsym( handle, "ldap_init" );
1084 dlclose( handle ); handle = NULL; fun = NULL;
1086 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1090 fun = dlsym( handle, "ber_init" );
1095 dlclose( handle ); handle = NULL; fun = NULL;
1097 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1101 fun = dlsym( handle, "res_query" );
1106 dlclose( handle ); handle = NULL; fun = NULL;
1108 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1112 fun = dlsym( handle, "pthread_create" );
1117 dlclose( handle ); handle = NULL; fun = NULL;
1123 #endif /* USE_LDAP */