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.
40 #include "addrcache.h"
45 * Create new LDAP server interface object.
47 SyldapServer *syldap_create() {
48 SyldapServer *ldapServer;
50 debug_print("Creating LDAP server interface object\n");
52 ldapServer = g_new0( SyldapServer, 1 );
53 ldapServer->name = NULL;
54 ldapServer->hostName = NULL;
55 ldapServer->port = SYLDAP_DFL_PORT;
56 ldapServer->baseDN = NULL;
57 ldapServer->bindDN = NULL;
58 ldapServer->bindPass = NULL;
59 ldapServer->searchCriteria = NULL;
60 ldapServer->searchValue = NULL;
61 ldapServer->entriesRead = 0;
62 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
63 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
64 ldapServer->newSearch = TRUE;
65 ldapServer->addressCache = addrcache_create();
66 ldapServer->thread = NULL;
67 ldapServer->busyFlag = FALSE;
68 ldapServer->retVal = MGU_SUCCESS;
69 ldapServer->callBack = NULL;
70 ldapServer->accessFlag = FALSE;
75 * Specify name to be used.
77 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
78 ldapServer->name = mgu_replace_string( ldapServer->name, value );
79 g_strstrip( ldapServer->name );
83 * Specify hostname to be used.
85 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
86 addrcache_refresh( ldapServer->addressCache );
87 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
88 g_strstrip( ldapServer->hostName );
92 * Specify port to be used.
94 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
95 addrcache_refresh( ldapServer->addressCache );
97 ldapServer->port = value;
100 ldapServer->port = SYLDAP_DFL_PORT;
105 * Specify base DN to be used.
107 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
108 addrcache_refresh( ldapServer->addressCache );
109 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
110 g_strstrip( ldapServer->baseDN );
114 * Specify bind DN to be used.
116 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
117 addrcache_refresh( ldapServer->addressCache );
118 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
119 g_strstrip( ldapServer->bindDN );
123 * Specify bind password to be used.
125 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
126 addrcache_refresh( ldapServer->addressCache );
127 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
128 g_strstrip( ldapServer->bindPass );
132 * Specify search criteria to be used.
134 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
135 addrcache_refresh( ldapServer->addressCache );
136 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
137 g_strstrip( ldapServer->searchCriteria );
138 ldapServer->newSearch = TRUE;
142 * Specify search value to be searched for.
144 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
145 addrcache_refresh( ldapServer->addressCache );
146 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
147 g_strstrip( ldapServer->searchValue );
148 ldapServer->newSearch = TRUE;
152 * Specify maximum number of entries to retrieve.
154 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
155 addrcache_refresh( ldapServer->addressCache );
157 ldapServer->maxEntries = value;
160 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
165 * Specify timeout value for LDAP operation (in seconds).
167 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
168 addrcache_refresh( ldapServer->addressCache );
170 ldapServer->timeOut = value;
173 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
178 * Register a callback function. When called, the function will be passed
179 * this object as an argument.
181 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
182 ldapServer->callBack = func;
185 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
186 g_return_if_fail( ldapServer != NULL );
187 ldapServer->accessFlag = value;
191 * Refresh internal variables to force a file read.
193 void syldap_force_refresh( SyldapServer *ldapServer ) {
194 addrcache_refresh( ldapServer->addressCache );
195 ldapServer->newSearch = TRUE;
198 gint syldap_get_status( SyldapServer *ldapServer ) {
199 g_return_val_if_fail( ldapServer != NULL, -1 );
200 return ldapServer->retVal;
203 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
204 g_return_val_if_fail( ldapServer != NULL, NULL );
205 return addrcache_get_root_folder( ldapServer->addressCache );
208 gchar *syldap_get_name( SyldapServer *ldapServer ) {
209 g_return_val_if_fail( ldapServer != NULL, NULL );
210 return ldapServer->name;
213 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
214 g_return_val_if_fail( ldapServer != NULL, FALSE );
215 return ldapServer->accessFlag;
219 * Free up LDAP server interface object by releasing internal memory.
221 void syldap_free( SyldapServer *ldapServer ) {
222 g_return_if_fail( ldapServer != NULL );
224 debug_print("Freeing LDAP server interface object\n");
226 ldapServer->callBack = NULL;
228 /* Free internal stuff */
229 g_free( ldapServer->name );
230 g_free( ldapServer->hostName );
231 g_free( ldapServer->baseDN );
232 g_free( ldapServer->bindDN );
233 g_free( ldapServer->bindPass );
234 g_free( ldapServer->searchCriteria );
235 g_free( ldapServer->searchValue );
237 ldapServer->port = 0;
238 ldapServer->entriesRead = 0;
239 ldapServer->maxEntries = 0;
240 ldapServer->newSearch = FALSE;
243 addrcache_clear( ldapServer->addressCache );
244 addrcache_free( ldapServer->addressCache );
247 ldapServer->name = NULL;
248 ldapServer->hostName = NULL;
249 ldapServer->baseDN = NULL;
250 ldapServer->bindDN = NULL;
251 ldapServer->bindPass = NULL;
252 ldapServer->searchCriteria = NULL;
253 ldapServer->searchValue = NULL;
254 ldapServer->addressCache = NULL;
255 g_free(ldapServer->thread);
256 ldapServer->thread = NULL;
257 ldapServer->busyFlag = FALSE;
258 ldapServer->retVal = MGU_SUCCESS;
259 ldapServer->accessFlag = FALSE;
261 /* Now release LDAP object */
262 g_free( ldapServer );
267 * Display object to specified stream.
269 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
270 g_return_if_fail( ldapServer != NULL );
272 fprintf( stream, "SyldapServer:\n" );
273 fprintf( stream, " name: '%s'\n", ldapServer->name );
274 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
275 fprintf( stream, " port: %d\n", ldapServer->port );
276 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
277 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
278 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
279 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
280 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
281 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
282 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
283 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
284 addrcache_print( ldapServer->addressCache, stream );
285 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
289 * Display object to specified stream.
291 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
292 g_return_if_fail( ldapServer != NULL );
294 fprintf( stream, "SyldapServer:\n" );
295 fprintf( stream, " name: '%s'\n", ldapServer->name );
296 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
297 fprintf( stream, " port: %d\n", ldapServer->port );
298 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
299 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
300 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
301 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
302 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
303 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
304 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
305 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
309 * Build an address list entry and append to list of address items. Name is formatted
310 * as it appears in the common name (cn) attribute.
312 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
315 GSList *nodeName = listName;
318 GSList *nodeAddress = listAddr;
319 person = addritem_create_item_person();
320 addritem_person_set_common_name( person, nodeName->data );
321 addrcache_id_person( ldapServer->addressCache, person );
322 addrcache_add_person( ldapServer->addressCache, person );
324 while( nodeAddress ) {
325 email = addritem_create_item_email();
326 addritem_email_set_address( email, nodeAddress->data );
327 addrcache_id_email( ldapServer->addressCache, email );
328 addrcache_person_add_email( ldapServer->addressCache, person, email );
329 nodeAddress = g_slist_next( nodeAddress );
330 ldapServer->entriesRead++;
332 nodeName = g_slist_next( nodeName );
337 * Build an address list entry and append to list of address items. Name is formatted
338 * as "<first-name> <last-name>".
340 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
341 GSList *nodeFirst = listFirst;
342 GSList *nodeAddress = listAddr;
343 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
344 gint iLen = 0, iLenT = 0;
348 /* Find longest first name in list */
350 if( firstName == NULL ) {
351 firstName = nodeFirst->data;
352 iLen = strlen( firstName );
355 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
356 firstName = nodeFirst->data;
360 nodeFirst = g_slist_next( nodeFirst );
365 lastName = listLast->data;
370 fullName = g_strdup_printf( "%s %s", firstName, lastName );
373 fullName = g_strdup_printf( "%s", firstName );
378 fullName = g_strdup_printf( "%s", lastName );
382 g_strchug( fullName ); g_strchomp( fullName );
386 person = addritem_create_item_person();
387 addritem_person_set_common_name( person, fullName );
388 addritem_person_set_first_name( person, firstName );
389 addritem_person_set_last_name( person, lastName );
390 addrcache_id_person( ldapServer->addressCache, person );
391 addrcache_add_person( ldapServer->addressCache, person );
394 /* Add address item */
395 while( nodeAddress ) {
396 email = addritem_create_item_email();
397 addritem_email_set_address( email, nodeAddress->data );
398 addrcache_id_email( ldapServer->addressCache, email );
399 addrcache_person_add_email( ldapServer->addressCache, person, email );
400 nodeAddress = g_slist_next( nodeAddress );
401 ldapServer->entriesRead++;
404 fullName = firstName = lastName = NULL;
409 * Add all attribute values to a list.
411 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
416 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
417 for( i = 0; vals[i] != NULL; i++ ) {
418 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
419 list = g_slist_append( list, g_strdup( vals[i] ) );
422 ldap_value_free( vals );
427 * Add a single attribute value to a list.
429 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
433 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
434 if( vals[0] != NULL ) {
435 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
436 list = g_slist_append( list, g_strdup( vals[0] ) );
439 ldap_value_free( vals );
444 * Free linked lists of character strings.
446 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
447 mgu_free_list( listName );
448 mgu_free_list( listAddr );
449 mgu_free_list( listID );
450 mgu_free_list( listDN );
451 mgu_free_list( listFirst );
452 mgu_free_list( listLast );
456 * Check parameters that are required for a search. This should
457 * be called before performing a search.
458 * Return: TRUE if search criteria appear OK.
460 gboolean syldap_check_search( SyldapServer *ldapServer ) {
461 g_return_val_if_fail( ldapServer != NULL, FALSE );
463 ldapServer->retVal = MGU_LDAP_CRITERIA;
465 /* Test search criteria */
466 if( ldapServer->searchCriteria == NULL ) {
469 if( strlen( ldapServer->searchCriteria ) < 1 ) {
473 if( ldapServer->searchValue == NULL ) {
476 if( strlen( ldapServer->searchValue ) < 1 ) {
480 ldapServer->retVal = MGU_SUCCESS;
485 * Perform the LDAP search, reading LDAP entries into cache.
486 * Note that one LDAP entry can have multiple values for many of its
487 * attributes. If these attributes are E-Mail addresses; these are
488 * broken out into separate address items. For any other attribute,
489 * only the first occurrence is read.
491 gint syldap_search( SyldapServer *ldapServer ) {
493 LDAPMessage *result, *e;
499 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
500 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
501 struct timeval timeout;
502 gboolean entriesFound = FALSE;
504 g_return_val_if_fail( ldapServer != NULL, -1 );
506 ldapServer->retVal = MGU_SUCCESS;
507 if( ! syldap_check_search( ldapServer ) ) {
508 return ldapServer->retVal;
512 timeout.tv_sec = ldapServer->timeOut;
513 timeout.tv_usec = 0L;
515 ldapServer->entriesRead = 0;
516 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
517 ldapServer->retVal = MGU_LDAP_INIT;
518 return ldapServer->retVal;
521 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
523 /* Bind to the server, if required */
524 if( ldapServer->bindDN ) {
525 if( * ldapServer->bindDN != '\0' ) {
526 /* printf( "binding...\n" ); */
527 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
528 /* printf( "rc=%d\n", rc ); */
529 if( rc != LDAP_SUCCESS ) {
530 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
532 ldapServer->retVal = MGU_LDAP_BIND;
533 return ldapServer->retVal;
538 /* Define all attributes we are interested in. */
539 attribs[0] = SYLDAP_ATTR_DN;
540 attribs[1] = SYLDAP_ATTR_COMMONNAME;
541 attribs[2] = SYLDAP_ATTR_GIVENNAME;
542 attribs[3] = SYLDAP_ATTR_SURNAME;
543 attribs[4] = SYLDAP_ATTR_EMAIL;
544 attribs[5] = SYLDAP_ATTR_UID;
547 /* Create LDAP search string and apply search criteria */
548 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
549 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
550 &timeout, 0, &result );
553 if( rc == LDAP_TIMEOUT ) {
555 ldapServer->retVal = MGU_LDAP_TIMEOUT;
556 return ldapServer->retVal;
558 if( rc != LDAP_SUCCESS ) {
559 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
561 ldapServer->retVal = MGU_LDAP_SEARCH;
562 return ldapServer->retVal;
565 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
567 /* Clear the cache if we have new entries, otherwise leave untouched. */
568 if( ldap_count_entries( ld, result ) > 0 ) {
569 addrcache_clear( ldapServer->addressCache );
572 /* Process results */
573 ldapServer->entriesRead = 0;
574 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
576 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
577 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
579 /* Process all attributes */
580 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
581 attribute = ldap_next_attribute( ld, e, ber ) ) {
582 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
583 listName = syldap_add_list_values( ld, e, attribute );
585 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
586 listAddress = syldap_add_list_values( ld, e, attribute );
588 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
589 listID = syldap_add_single_value( ld, e, attribute );
591 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
592 listFirst = syldap_add_list_values( ld, e, attribute );
594 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
595 listLast = syldap_add_single_value( ld, e, attribute );
597 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
598 listDN = syldap_add_single_value( ld, e, attribute );
602 /* Free memory used to store attribute */
603 ldap_memfree( attribute );
605 /* Format and add items to cache */
606 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
609 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
610 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
617 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
618 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
620 /* Free up and disconnect */
621 ldap_msgfree( result );
623 ldapServer->newSearch = FALSE;
625 ldapServer->retVal = MGU_SUCCESS;
628 ldapServer->retVal = MGU_LDAP_NOENTRIES;
630 return ldapServer->retVal;
633 /* ============================================================================================ */
635 * Read data into list. Main entry point
636 * Return: TRUE if file read successfully.
638 /* ============================================================================================ */
639 gint syldap_read_data( SyldapServer *ldapServer ) {
640 g_return_val_if_fail( ldapServer != NULL, -1 );
642 ldapServer->accessFlag = FALSE;
643 pthread_detach( pthread_self() );
644 if( ldapServer->newSearch ) {
645 /* Read data into the list */
646 syldap_search( ldapServer );
649 ldapServer->addressCache->modified = FALSE;
650 ldapServer->addressCache->dataRead = TRUE;
651 ldapServer->accessFlag = FALSE;
655 ldapServer->busyFlag = FALSE;
656 if( ldapServer->callBack ) {
657 ( ldapServer->callBack )( ldapServer );
659 /* The thread struct should not be freed inside the thread
660 g_free(ldapServer->thread);
661 ldapServer->thread = NULL;
662 pthread_exit( NULL );
664 return ldapServer->retVal;
667 /* ============================================================================================ */
669 * Cancel read with thread.
671 /* ============================================================================================ */
672 void syldap_cancel_read( SyldapServer *ldapServer ) {
673 g_return_if_fail( ldapServer != NULL );
675 if( ldapServer->thread ) {
676 /* printf( "thread cancelled\n" ); */
677 /* The thread is cancleing itself, ok?
678 pthread_cancel( *ldapServer->thread );
681 /* The thread struct should not be freed inside the thread
682 g_free(ldapServer->thread);
683 ldapServer->thread = NULL;
685 ldapServer->busyFlag = FALSE;
688 /* ============================================================================================ */
690 * Read data into list using a background thread.
691 * Return: TRUE if file read successfully. Callback function will be
692 * notified when search is complete.
694 /* ============================================================================================ */
695 gint syldap_read_data_th( SyldapServer *ldapServer ) {
696 g_return_val_if_fail( ldapServer != NULL, -1 );
698 ldapServer->busyFlag = FALSE;
699 syldap_check_search( ldapServer );
700 if( ldapServer->retVal == MGU_SUCCESS ) {
701 debug_print("Staring LDAP read thread\n");
703 ldapServer->busyFlag = TRUE;
704 ldapServer->thread = g_new0(pthread_t, 1);
705 pthread_create( ldapServer->thread, NULL, (void *) &syldap_read_data, (void *) ldapServer );
707 return ldapServer->retVal;
711 * Return link list of persons.
713 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
714 g_return_val_if_fail( ldapServer != NULL, NULL );
715 return addrcache_get_list_person( ldapServer->addressCache );
719 * Return link list of folders. This is always NULL since there are
720 * no folders in GnomeCard.
723 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
724 g_return_val_if_fail( ldapServer != NULL, NULL );
728 #define SYLDAP_TEST_FILTER "(objectclass=*)"
729 #define SYLDAP_SEARCHBASE_V2 "cn=config"
730 #define SYLDAP_SEARCHBASE_V3 ""
731 #define SYLDAP_V2_TEST_ATTR "database"
732 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
735 * Attempt to discover the base DN for the server.
739 * bindDN Bind DN (optional).
740 * bindPW Bind PW (optional).
741 * tov Timeout value (seconds), or 0 for none, default 30 secs.
742 * Return: List of Base DN's, or NULL if could not read. Base DN should
743 * be g_free() when done.
745 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
746 GList *baseDN = NULL;
749 LDAPMessage *result, *e;
754 struct timeval timeout;
756 if( host == NULL ) return baseDN;
757 if( port < 1 ) return baseDN;
760 timeout.tv_usec = 0L;
762 timeout.tv_sec = tov;
765 timeout.tv_sec = 30L;
768 /* Connect to server. */
769 if( ( ld = ldap_init( host, port ) ) == NULL ) {
773 /* Bind to the server, if required */
775 if( *bindDN != '\0' ) {
776 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
777 if( rc != LDAP_SUCCESS ) {
778 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
785 /* Test for LDAP version 3 */
786 attribs[0] = SYLDAP_V3_TEST_ATTR;
788 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
789 0, NULL, NULL, &timeout, 0, &result );
790 if( rc == LDAP_SUCCESS ) {
791 /* Process entries */
792 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
793 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
795 /* Process attributes */
796 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
797 attribute = ldap_next_attribute( ld, e, ber ) ) {
798 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
799 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
800 for( i = 0; vals[i] != NULL; i++ ) {
801 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
802 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
805 ldap_value_free( vals );
808 ldap_memfree( attribute );
813 ldap_msgfree( result );
818 if( baseDN == NULL ) {
819 /* Test for LDAP version 2 */
821 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
822 0, NULL, NULL, &timeout, 0, &result );
823 if( rc == LDAP_SUCCESS ) {
824 /* Process entries */
825 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
826 /* if( baseDN ) break; */
827 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
829 /* Process attributes */
830 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
831 attribute = ldap_next_attribute( ld, e, ber ) ) {
832 /* if( baseDN ) break; */
833 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
834 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
835 for( i = 0; vals[i] != NULL; i++ ) {
837 /* Strip the 'ldb:' from the front of the value */
838 ch = ( char * ) strchr( vals[i], ':' );
840 gchar *bn = g_strdup( ++ch );
843 baseDN = g_list_append( baseDN, g_strdup( bn ) );
847 ldap_value_free( vals );
850 ldap_memfree( attribute );
855 ldap_msgfree( result );
863 * Attempt to discover the base DN for the server.
864 * Enter: ldapServer Server to test.
865 * Return: List of Base DN's, or NULL if could not read. Base DN should
866 * be g_free() when done. Return code set in ldapServer.
868 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
869 GList *baseDN = NULL;
872 LDAPMessage *result, *e;
877 struct timeval timeout;
879 ldapServer->retVal = MGU_BAD_ARGS;
880 if( ldapServer == NULL ) return baseDN;
881 if( ldapServer->hostName == NULL ) return baseDN;
882 if( ldapServer->port < 1 ) return baseDN;
885 timeout.tv_usec = 0L;
886 if( ldapServer->timeOut > 0 ) {
887 timeout.tv_sec = ldapServer->timeOut;
890 timeout.tv_sec = 30L;
893 /* Connect to server. */
894 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
895 ldapServer->retVal = MGU_LDAP_INIT;
899 /* Bind to the server, if required */
900 if( ldapServer->bindDN ) {
901 if( *ldapServer->bindDN != '\0' ) {
902 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
903 if( rc != LDAP_SUCCESS ) {
904 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
906 ldapServer->retVal = MGU_LDAP_BIND;
912 ldapServer->retVal = MGU_LDAP_SEARCH;
914 /* Test for LDAP version 3 */
915 attribs[0] = SYLDAP_V3_TEST_ATTR;
917 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
918 0, NULL, NULL, &timeout, 0, &result );
919 if( rc == LDAP_SUCCESS ) {
920 /* Process entries */
921 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
922 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
924 /* Process attributes */
925 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
926 attribute = ldap_next_attribute( ld, e, ber ) ) {
927 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
928 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
929 for( i = 0; vals[i] != NULL; i++ ) {
930 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
931 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
934 ldap_value_free( vals );
937 ldap_memfree( attribute );
942 ldap_msgfree( result );
943 ldapServer->retVal = MGU_SUCCESS;
945 else if( rc == LDAP_TIMEOUT ) {
946 ldapServer->retVal = MGU_LDAP_TIMEOUT;
949 if( baseDN == NULL ) {
950 /* Test for LDAP version 2 */
952 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
953 0, NULL, NULL, &timeout, 0, &result );
954 if( rc == LDAP_SUCCESS ) {
955 /* Process entries */
956 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
957 /* if( baseDN ) break; */
958 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
960 /* Process attributes */
961 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
962 attribute = ldap_next_attribute( ld, e, ber ) ) {
963 /* if( baseDN ) break; */
964 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
965 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
966 for( i = 0; vals[i] != NULL; i++ ) {
968 /* Strip the 'ldb:' from the front of the value */
969 ch = ( char * ) strchr( vals[i], ':' );
971 gchar *bn = g_strdup( ++ch );
974 baseDN = g_list_append( baseDN, g_strdup( bn ) );
978 ldap_value_free( vals );
981 ldap_memfree( attribute );
986 ldap_msgfree( result );
987 ldapServer->retVal = MGU_SUCCESS;
989 else if( rc == LDAP_TIMEOUT ) {
990 ldapServer->retVal = MGU_LDAP_TIMEOUT;
999 * Attempt to connect to the server.
1003 * Return: TRUE if connected successfully.
1005 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1006 gboolean retVal = FALSE;
1009 if( host == NULL ) return retVal;
1010 if( port < 1 ) return retVal;
1011 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1021 * Attempt to connect to the server.
1022 * Enter: ldapServer Server to test.
1023 * Return: TRUE if connected successfully. Return code set in ldapServer.
1025 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1026 gboolean retVal = FALSE;
1029 ldapServer->retVal = MGU_BAD_ARGS;
1030 if( ldapServer == NULL ) return retVal;
1031 if( ldapServer->hostName == NULL ) return retVal;
1032 if( ldapServer->port < 1 ) return retVal;
1033 ldapServer->retVal = MGU_LDAP_INIT;
1034 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1035 ldapServer->retVal = MGU_SUCCESS;
1044 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
1045 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
1046 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1047 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1050 * Test whether LDAP libraries installed.
1051 * Return: TRUE if library available.
1053 gboolean syldap_test_ldap_lib() {
1057 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1062 /* Test for symbols we need */
1063 fun = dlsym( handle, "ldap_init" );
1068 dlclose( handle ); handle = NULL; fun = NULL;
1070 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1074 fun = dlsym( handle, "ber_init" );
1079 dlclose( handle ); handle = NULL; fun = NULL;
1081 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1085 fun = dlsym( handle, "res_query" );
1090 dlclose( handle ); handle = NULL; fun = NULL;
1092 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1096 fun = dlsym( handle, "pthread_create" );
1101 dlclose( handle ); handle = NULL; fun = NULL;
1106 #endif /* USE_LDAP */