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"
44 * Create new LDAP server interface object.
46 SyldapServer *syldap_create() {
47 SyldapServer *ldapServer;
48 ldapServer = g_new0( SyldapServer, 1 );
49 ldapServer->name = NULL;
50 ldapServer->hostName = NULL;
51 ldapServer->port = SYLDAP_DFL_PORT;
52 ldapServer->baseDN = NULL;
53 ldapServer->bindDN = NULL;
54 ldapServer->bindPass = NULL;
55 ldapServer->searchCriteria = NULL;
56 ldapServer->searchValue = NULL;
57 ldapServer->entriesRead = 0;
58 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
59 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
60 ldapServer->newSearch = TRUE;
61 ldapServer->addressCache = addrcache_create();
62 ldapServer->thread = NULL;
63 ldapServer->busyFlag = FALSE;
64 ldapServer->retVal = MGU_SUCCESS;
65 ldapServer->callBack = NULL;
66 ldapServer->accessFlag = FALSE;
71 * Specify name to be used.
73 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
74 ldapServer->name = mgu_replace_string( ldapServer->name, value );
75 g_strstrip( ldapServer->name );
79 * Specify hostname to be used.
81 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
82 addrcache_refresh( ldapServer->addressCache );
83 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
84 g_strstrip( ldapServer->hostName );
88 * Specify port to be used.
90 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
91 addrcache_refresh( ldapServer->addressCache );
93 ldapServer->port = value;
96 ldapServer->port = SYLDAP_DFL_PORT;
101 * Specify base DN to be used.
103 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
104 addrcache_refresh( ldapServer->addressCache );
105 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
106 g_strstrip( ldapServer->baseDN );
110 * Specify bind DN to be used.
112 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
113 addrcache_refresh( ldapServer->addressCache );
114 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
115 g_strstrip( ldapServer->bindDN );
119 * Specify bind password to be used.
121 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
122 addrcache_refresh( ldapServer->addressCache );
123 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
124 g_strstrip( ldapServer->bindPass );
128 * Specify search criteria to be used.
130 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
131 addrcache_refresh( ldapServer->addressCache );
132 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
133 g_strstrip( ldapServer->searchCriteria );
134 ldapServer->newSearch = TRUE;
138 * Specify search value to be searched for.
140 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
141 addrcache_refresh( ldapServer->addressCache );
142 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
143 g_strstrip( ldapServer->searchValue );
144 ldapServer->newSearch = TRUE;
148 * Specify maximum number of entries to retrieve.
150 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
151 addrcache_refresh( ldapServer->addressCache );
153 ldapServer->maxEntries = value;
156 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
161 * Specify timeout value for LDAP operation (in seconds).
163 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
164 addrcache_refresh( ldapServer->addressCache );
166 ldapServer->timeOut = value;
169 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
174 * Register a callback function. When called, the function will be passed
175 * this object as an argument.
177 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
178 ldapServer->callBack = func;
181 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
182 g_return_if_fail( ldapServer != NULL );
183 ldapServer->accessFlag = value;
187 * Refresh internal variables to force a file read.
189 void syldap_force_refresh( SyldapServer *ldapServer ) {
190 addrcache_refresh( ldapServer->addressCache );
191 ldapServer->newSearch = TRUE;
194 gint syldap_get_status( SyldapServer *ldapServer ) {
195 g_return_val_if_fail( ldapServer != NULL, -1 );
196 return ldapServer->retVal;
199 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
200 g_return_val_if_fail( ldapServer != NULL, NULL );
201 return addrcache_get_root_folder( ldapServer->addressCache );
204 gchar *syldap_get_name( SyldapServer *ldapServer ) {
205 g_return_val_if_fail( ldapServer != NULL, NULL );
206 return ldapServer->name;
209 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
210 g_return_val_if_fail( ldapServer != NULL, FALSE );
211 return ldapServer->accessFlag;
215 * Free up LDAP server interface object by releasing internal memory.
217 void syldap_free( SyldapServer *ldapServer ) {
218 g_return_if_fail( ldapServer != NULL );
220 ldapServer->callBack = NULL;
222 /* Free internal stuff */
223 g_free( ldapServer->name );
224 g_free( ldapServer->hostName );
225 g_free( ldapServer->baseDN );
226 g_free( ldapServer->bindDN );
227 g_free( ldapServer->bindPass );
228 g_free( ldapServer->searchCriteria );
229 g_free( ldapServer->searchValue );
231 ldapServer->port = 0;
232 ldapServer->entriesRead = 0;
233 ldapServer->maxEntries = 0;
234 ldapServer->newSearch = FALSE;
237 addrcache_clear( ldapServer->addressCache );
238 addrcache_free( ldapServer->addressCache );
241 ldapServer->name = NULL;
242 ldapServer->hostName = NULL;
243 ldapServer->baseDN = NULL;
244 ldapServer->bindDN = NULL;
245 ldapServer->bindPass = NULL;
246 ldapServer->searchCriteria = NULL;
247 ldapServer->searchValue = NULL;
248 ldapServer->addressCache = NULL;
249 ldapServer->thread = NULL;
250 ldapServer->busyFlag = FALSE;
251 ldapServer->retVal = MGU_SUCCESS;
252 ldapServer->accessFlag = FALSE;
254 /* Now release LDAP object */
255 g_free( ldapServer );
260 * Display object to specified stream.
262 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
263 g_return_if_fail( ldapServer != NULL );
265 fprintf( stream, "SyldapServer:\n" );
266 fprintf( stream, " name: '%s'\n", ldapServer->name );
267 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
268 fprintf( stream, " port: %d\n", ldapServer->port );
269 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
270 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
271 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
272 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
273 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
274 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
275 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
276 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
277 addrcache_print( ldapServer->addressCache, stream );
278 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
282 * Display object to specified stream.
284 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
285 g_return_if_fail( ldapServer != NULL );
287 fprintf( stream, "SyldapServer:\n" );
288 fprintf( stream, " name: '%s'\n", ldapServer->name );
289 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
290 fprintf( stream, " port: %d\n", ldapServer->port );
291 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
292 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
293 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
294 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
295 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
296 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
297 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
298 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
302 * Build an address list entry and append to list of address items. Name is formatted
303 * as it appears in the common name (cn) attribute.
305 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
308 GSList *nodeName = listName;
311 GSList *nodeAddress = listAddr;
312 person = addritem_create_item_person();
313 addritem_person_set_common_name( person, nodeName->data );
314 addrcache_id_person( ldapServer->addressCache, person );
315 addrcache_add_person( ldapServer->addressCache, person );
317 while( nodeAddress ) {
318 email = addritem_create_item_email();
319 addritem_email_set_address( email, nodeAddress->data );
320 addrcache_id_email( ldapServer->addressCache, email );
321 addrcache_person_add_email( ldapServer->addressCache, person, email );
322 nodeAddress = g_slist_next( nodeAddress );
323 ldapServer->entriesRead++;
325 nodeName = g_slist_next( nodeName );
330 * Build an address list entry and append to list of address items. Name is formatted
331 * as "<first-name> <last-name>".
333 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
334 GSList *nodeFirst = listFirst;
335 GSList *nodeAddress = listAddr;
336 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
337 gint iLen = 0, iLenT = 0;
341 /* Find longest first name in list */
343 if( firstName == NULL ) {
344 firstName = nodeFirst->data;
345 iLen = strlen( firstName );
348 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
349 firstName = nodeFirst->data;
353 nodeFirst = g_slist_next( nodeFirst );
358 lastName = listLast->data;
363 fullName = g_strdup_printf( "%s %s", firstName, lastName );
366 fullName = g_strdup_printf( "%s", firstName );
371 fullName = g_strdup_printf( "%s", lastName );
375 g_strchug( fullName ); g_strchomp( fullName );
379 person = addritem_create_item_person();
380 addritem_person_set_common_name( person, fullName );
381 addritem_person_set_first_name( person, firstName );
382 addritem_person_set_last_name( person, lastName );
383 addrcache_id_person( ldapServer->addressCache, person );
384 addrcache_add_person( ldapServer->addressCache, person );
387 /* Add address item */
388 while( nodeAddress ) {
389 email = addritem_create_item_email();
390 addritem_email_set_address( email, nodeAddress->data );
391 addrcache_id_email( ldapServer->addressCache, email );
392 addrcache_person_add_email( ldapServer->addressCache, person, email );
393 nodeAddress = g_slist_next( nodeAddress );
394 ldapServer->entriesRead++;
397 fullName = firstName = lastName = NULL;
402 * Add all attribute values to a list.
404 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
409 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
410 for( i = 0; vals[i] != NULL; i++ ) {
411 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
412 list = g_slist_append( list, g_strdup( vals[i] ) );
415 ldap_value_free( vals );
420 * Add a single attribute value to a list.
422 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
426 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
427 if( vals[0] != NULL ) {
428 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
429 list = g_slist_append( list, g_strdup( vals[0] ) );
432 ldap_value_free( vals );
437 * Free linked lists of character strings.
439 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
440 mgu_free_list( listName );
441 mgu_free_list( listAddr );
442 mgu_free_list( listID );
443 mgu_free_list( listDN );
444 mgu_free_list( listFirst );
445 mgu_free_list( listLast );
449 * Check parameters that are required for a search. This should
450 * be called before performing a search.
451 * Return: TRUE if search criteria appear OK.
453 gboolean syldap_check_search( SyldapServer *ldapServer ) {
454 g_return_val_if_fail( ldapServer != NULL, FALSE );
456 ldapServer->retVal = MGU_LDAP_CRITERIA;
458 /* Test search criteria */
459 if( ldapServer->searchCriteria == NULL ) {
462 if( strlen( ldapServer->searchCriteria ) < 1 ) {
466 if( ldapServer->searchValue == NULL ) {
469 if( strlen( ldapServer->searchValue ) < 1 ) {
473 ldapServer->retVal = MGU_SUCCESS;
478 * Perform the LDAP search, reading LDAP entries into cache.
479 * Note that one LDAP entry can have multiple values for many of its
480 * attributes. If these attributes are E-Mail addresses; these are
481 * broken out into separate address items. For any other attribute,
482 * only the first occurrence is read.
484 gint syldap_search( SyldapServer *ldapServer ) {
486 LDAPMessage *result, *e;
492 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
493 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
494 struct timeval timeout;
495 gboolean entriesFound = FALSE;
497 g_return_val_if_fail( ldapServer != NULL, -1 );
499 ldapServer->retVal = MGU_SUCCESS;
500 if( ! syldap_check_search( ldapServer ) ) {
501 return ldapServer->retVal;
505 timeout.tv_sec = ldapServer->timeOut;
506 timeout.tv_usec = 0L;
508 ldapServer->entriesRead = 0;
509 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
510 ldapServer->retVal = MGU_LDAP_INIT;
511 return ldapServer->retVal;
514 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
516 /* Bind to the server, if required */
517 if( ldapServer->bindDN ) {
518 if( * ldapServer->bindDN != '\0' ) {
519 /* printf( "binding...\n" ); */
520 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
521 /* printf( "rc=%d\n", rc ); */
522 if( rc != LDAP_SUCCESS ) {
523 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
525 ldapServer->retVal = MGU_LDAP_BIND;
526 return ldapServer->retVal;
531 /* Define all attributes we are interested in. */
532 attribs[0] = SYLDAP_ATTR_DN;
533 attribs[1] = SYLDAP_ATTR_COMMONNAME;
534 attribs[2] = SYLDAP_ATTR_GIVENNAME;
535 attribs[3] = SYLDAP_ATTR_SURNAME;
536 attribs[4] = SYLDAP_ATTR_EMAIL;
537 attribs[5] = SYLDAP_ATTR_UID;
540 /* Create LDAP search string and apply search criteria */
541 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
542 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
543 &timeout, 0, &result );
546 if( rc == LDAP_TIMEOUT ) {
548 ldapServer->retVal = MGU_LDAP_TIMEOUT;
549 return ldapServer->retVal;
551 if( rc != LDAP_SUCCESS ) {
552 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
554 ldapServer->retVal = MGU_LDAP_SEARCH;
555 return ldapServer->retVal;
558 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
560 /* Clear the cache if we have new entries, otherwise leave untouched. */
561 if( ldap_count_entries( ld, result ) > 0 ) {
562 addrcache_clear( ldapServer->addressCache );
565 /* Process results */
566 ldapServer->entriesRead = 0;
567 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
569 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
570 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
572 /* Process all attributes */
573 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
574 attribute = ldap_next_attribute( ld, e, ber ) ) {
575 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
576 listName = syldap_add_list_values( ld, e, attribute );
578 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
579 listAddress = syldap_add_list_values( ld, e, attribute );
581 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
582 listID = syldap_add_single_value( ld, e, attribute );
584 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
585 listFirst = syldap_add_list_values( ld, e, attribute );
587 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
588 listLast = syldap_add_single_value( ld, e, attribute );
590 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
591 listDN = syldap_add_single_value( ld, e, attribute );
595 /* Free memory used to store attribute */
596 ldap_memfree( attribute );
598 /* Format and add items to cache */
599 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
602 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
603 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
610 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
611 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
613 /* Free up and disconnect */
614 ldap_msgfree( result );
616 ldapServer->newSearch = FALSE;
618 ldapServer->retVal = MGU_SUCCESS;
621 ldapServer->retVal = MGU_LDAP_NOENTRIES;
623 return ldapServer->retVal;
626 /* ============================================================================================ */
628 * Read data into list. Main entry point
629 * Return: TRUE if file read successfully.
631 /* ============================================================================================ */
632 gint syldap_read_data( SyldapServer *ldapServer ) {
633 g_return_val_if_fail( ldapServer != NULL, -1 );
635 ldapServer->accessFlag = FALSE;
636 pthread_detach( pthread_self() );
637 if( ldapServer->newSearch ) {
638 /* Read data into the list */
639 syldap_search( ldapServer );
642 ldapServer->addressCache->modified = FALSE;
643 ldapServer->addressCache->dataRead = TRUE;
644 ldapServer->accessFlag = FALSE;
648 ldapServer->busyFlag = FALSE;
649 if( ldapServer->callBack ) {
650 ( ldapServer->callBack )( ldapServer );
652 ldapServer->thread = NULL;
653 pthread_exit( NULL );
654 return ldapServer->retVal;
657 /* ============================================================================================ */
659 * Cancel read with thread.
661 /* ============================================================================================ */
662 void syldap_cancel_read( SyldapServer *ldapServer ) {
663 g_return_if_fail( ldapServer != NULL );
665 if( ldapServer->thread ) {
666 /* printf( "thread cancelled\n" ); */
667 pthread_cancel( *ldapServer->thread );
669 ldapServer->thread = NULL;
670 ldapServer->busyFlag = FALSE;
673 /* ============================================================================================ */
675 * Read data into list using a background thread.
676 * Return: TRUE if file read successfully. Callback function will be
677 * notified when search is complete.
679 /* ============================================================================================ */
680 gint syldap_read_data_th( SyldapServer *ldapServer ) {
683 g_return_val_if_fail( ldapServer != NULL, -1 );
685 ldapServer->busyFlag = FALSE;
686 syldap_check_search( ldapServer );
687 if( ldapServer->retVal == MGU_SUCCESS ) {
688 ldapServer->busyFlag = TRUE;
689 ldapServer->thread = &thread;
690 pthread_create( ldapServer->thread, NULL, (void *) &syldap_read_data, (void *) ldapServer );
692 return ldapServer->retVal;
696 * Return link list of persons.
698 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
699 g_return_val_if_fail( ldapServer != NULL, NULL );
700 return addrcache_get_list_person( ldapServer->addressCache );
704 * Return link list of folders. This is always NULL since there are
705 * no folders in GnomeCard.
708 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
709 g_return_val_if_fail( ldapServer != NULL, NULL );
713 #define SYLDAP_TEST_FILTER "(objectclass=*)"
714 #define SYLDAP_SEARCHBASE_V2 "cn=config"
715 #define SYLDAP_SEARCHBASE_V3 ""
716 #define SYLDAP_V2_TEST_ATTR "database"
717 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
720 * Attempt to discover the base DN for the server.
724 * bindDN Bind DN (optional).
725 * bindPW Bind PW (optional).
726 * tov Timeout value (seconds), or 0 for none, default 30 secs.
727 * Return: List of Base DN's, or NULL if could not read. Base DN should
728 * be g_free() when done.
730 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
731 GList *baseDN = NULL;
734 LDAPMessage *result, *e;
739 struct timeval timeout;
741 if( host == NULL ) return baseDN;
742 if( port < 1 ) return baseDN;
745 timeout.tv_usec = 0L;
747 timeout.tv_sec = tov;
750 timeout.tv_sec = 30L;
753 /* Connect to server. */
754 if( ( ld = ldap_init( host, port ) ) == NULL ) {
758 /* Bind to the server, if required */
760 if( *bindDN != '\0' ) {
761 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
762 if( rc != LDAP_SUCCESS ) {
763 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
770 /* Test for LDAP version 3 */
771 attribs[0] = SYLDAP_V3_TEST_ATTR;
773 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
774 0, NULL, NULL, &timeout, 0, &result );
775 if( rc == LDAP_SUCCESS ) {
776 /* Process entries */
777 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
778 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
780 /* Process attributes */
781 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
782 attribute = ldap_next_attribute( ld, e, ber ) ) {
783 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
784 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
785 for( i = 0; vals[i] != NULL; i++ ) {
786 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
787 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
790 ldap_value_free( vals );
793 ldap_memfree( attribute );
798 ldap_msgfree( result );
803 if( baseDN == NULL ) {
804 /* Test for LDAP version 2 */
806 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
807 0, NULL, NULL, &timeout, 0, &result );
808 if( rc == LDAP_SUCCESS ) {
809 /* Process entries */
810 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
811 /* if( baseDN ) break; */
812 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
814 /* Process attributes */
815 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
816 attribute = ldap_next_attribute( ld, e, ber ) ) {
817 /* if( baseDN ) break; */
818 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
819 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
820 for( i = 0; vals[i] != NULL; i++ ) {
822 /* Strip the 'ldb:' from the front of the value */
823 ch = ( char * ) strchr( vals[i], ':' );
825 gchar *bn = g_strdup( ++ch );
828 baseDN = g_list_append( baseDN, g_strdup( bn ) );
832 ldap_value_free( vals );
835 ldap_memfree( attribute );
840 ldap_msgfree( result );
848 * Attempt to discover the base DN for the server.
849 * Enter: ldapServer Server to test.
850 * Return: List of Base DN's, or NULL if could not read. Base DN should
851 * be g_free() when done. Return code set in ldapServer.
853 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
854 GList *baseDN = NULL;
857 LDAPMessage *result, *e;
862 struct timeval timeout;
864 ldapServer->retVal = MGU_BAD_ARGS;
865 if( ldapServer == NULL ) return baseDN;
866 if( ldapServer->hostName == NULL ) return baseDN;
867 if( ldapServer->port < 1 ) return baseDN;
870 timeout.tv_usec = 0L;
871 if( ldapServer->timeOut > 0 ) {
872 timeout.tv_sec = ldapServer->timeOut;
875 timeout.tv_sec = 30L;
878 /* Connect to server. */
879 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
880 ldapServer->retVal = MGU_LDAP_INIT;
884 /* Bind to the server, if required */
885 if( ldapServer->bindDN ) {
886 if( *ldapServer->bindDN != '\0' ) {
887 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
888 if( rc != LDAP_SUCCESS ) {
889 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
891 ldapServer->retVal = MGU_LDAP_BIND;
897 ldapServer->retVal = MGU_LDAP_SEARCH;
899 /* Test for LDAP version 3 */
900 attribs[0] = SYLDAP_V3_TEST_ATTR;
902 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
903 0, NULL, NULL, &timeout, 0, &result );
904 if( rc == LDAP_SUCCESS ) {
905 /* Process entries */
906 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
907 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
909 /* Process attributes */
910 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
911 attribute = ldap_next_attribute( ld, e, ber ) ) {
912 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
913 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
914 for( i = 0; vals[i] != NULL; i++ ) {
915 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
916 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
919 ldap_value_free( vals );
922 ldap_memfree( attribute );
927 ldap_msgfree( result );
928 ldapServer->retVal = MGU_SUCCESS;
930 else if( rc == LDAP_TIMEOUT ) {
931 ldapServer->retVal = MGU_LDAP_TIMEOUT;
934 if( baseDN == NULL ) {
935 /* Test for LDAP version 2 */
937 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
938 0, NULL, NULL, &timeout, 0, &result );
939 if( rc == LDAP_SUCCESS ) {
940 /* Process entries */
941 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
942 /* if( baseDN ) break; */
943 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
945 /* Process attributes */
946 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
947 attribute = ldap_next_attribute( ld, e, ber ) ) {
948 /* if( baseDN ) break; */
949 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
950 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
951 for( i = 0; vals[i] != NULL; i++ ) {
953 /* Strip the 'ldb:' from the front of the value */
954 ch = ( char * ) strchr( vals[i], ':' );
956 gchar *bn = g_strdup( ++ch );
959 baseDN = g_list_append( baseDN, g_strdup( bn ) );
963 ldap_value_free( vals );
966 ldap_memfree( attribute );
971 ldap_msgfree( result );
972 ldapServer->retVal = MGU_SUCCESS;
974 else if( rc == LDAP_TIMEOUT ) {
975 ldapServer->retVal = MGU_LDAP_TIMEOUT;
984 * Attempt to connect to the server.
988 * Return: TRUE if connected successfully.
990 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
991 gboolean retVal = FALSE;
994 if( host == NULL ) return retVal;
995 if( port < 1 ) return retVal;
996 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1006 * Attempt to connect to the server.
1007 * Enter: ldapServer Server to test.
1008 * Return: TRUE if connected successfully. Return code set in ldapServer.
1010 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1011 gboolean retVal = FALSE;
1014 ldapServer->retVal = MGU_BAD_ARGS;
1015 if( ldapServer == NULL ) return retVal;
1016 if( ldapServer->hostName == NULL ) return retVal;
1017 if( ldapServer->port < 1 ) return retVal;
1018 ldapServer->retVal = MGU_LDAP_INIT;
1019 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1020 ldapServer->retVal = MGU_SUCCESS;
1029 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
1030 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
1031 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1032 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1035 * Test whether LDAP libraries installed.
1036 * Return: TRUE if library available.
1038 gboolean syldap_test_ldap_lib() {
1042 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1047 /* Test for symbols we need */
1048 fun = dlsym( handle, "ldap_init" );
1053 dlclose( handle ); handle = NULL; fun = NULL;
1055 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1059 fun = dlsym( handle, "ber_init" );
1064 dlclose( handle ); handle = NULL; fun = NULL;
1066 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1070 fun = dlsym( handle, "res_query" );
1075 dlclose( handle ); handle = NULL; fun = NULL;
1077 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1081 fun = dlsym( handle, "pthread_create" );
1086 dlclose( handle ); handle = NULL; fun = NULL;
1091 #endif /* USE_LDAP */