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;
71 ldapServer->idleId = 0;
76 * Specify name to be used.
78 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
79 ldapServer->name = mgu_replace_string( ldapServer->name, value );
80 g_strstrip( ldapServer->name );
84 * Specify hostname to be used.
86 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
87 addrcache_refresh( ldapServer->addressCache );
88 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
89 g_strstrip( ldapServer->hostName );
93 * Specify port to be used.
95 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
96 addrcache_refresh( ldapServer->addressCache );
98 ldapServer->port = value;
101 ldapServer->port = SYLDAP_DFL_PORT;
106 * Specify base DN to be used.
108 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
109 addrcache_refresh( ldapServer->addressCache );
110 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
111 g_strstrip( ldapServer->baseDN );
115 * Specify bind DN to be used.
117 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
118 addrcache_refresh( ldapServer->addressCache );
119 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
120 g_strstrip( ldapServer->bindDN );
124 * Specify bind password to be used.
126 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
127 addrcache_refresh( ldapServer->addressCache );
128 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
129 g_strstrip( ldapServer->bindPass );
133 * Specify search criteria to be used.
135 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
136 addrcache_refresh( ldapServer->addressCache );
137 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
138 g_strstrip( ldapServer->searchCriteria );
139 ldapServer->newSearch = TRUE;
143 * Specify search value to be searched for.
145 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
146 addrcache_refresh( ldapServer->addressCache );
147 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
148 g_strstrip( ldapServer->searchValue );
149 ldapServer->newSearch = TRUE;
153 * Specify maximum number of entries to retrieve.
155 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
156 addrcache_refresh( ldapServer->addressCache );
158 ldapServer->maxEntries = value;
161 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
166 * Specify timeout value for LDAP operation (in seconds).
168 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
169 addrcache_refresh( ldapServer->addressCache );
171 ldapServer->timeOut = value;
174 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
179 * Register a callback function. When called, the function will be passed
180 * this object as an argument.
182 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
183 ldapServer->callBack = func;
186 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
187 g_return_if_fail( ldapServer != NULL );
188 ldapServer->accessFlag = value;
192 * Refresh internal variables to force a file read.
194 void syldap_force_refresh( SyldapServer *ldapServer ) {
195 addrcache_refresh( ldapServer->addressCache );
196 ldapServer->newSearch = TRUE;
199 gint syldap_get_status( SyldapServer *ldapServer ) {
200 g_return_val_if_fail( ldapServer != NULL, -1 );
201 return ldapServer->retVal;
204 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
205 g_return_val_if_fail( ldapServer != NULL, NULL );
206 return addrcache_get_root_folder( ldapServer->addressCache );
209 gchar *syldap_get_name( SyldapServer *ldapServer ) {
210 g_return_val_if_fail( ldapServer != NULL, NULL );
211 return ldapServer->name;
214 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
215 g_return_val_if_fail( ldapServer != NULL, FALSE );
216 return ldapServer->accessFlag;
220 * Free up LDAP server interface object by releasing internal memory.
222 void syldap_free( SyldapServer *ldapServer ) {
223 g_return_if_fail( ldapServer != NULL );
225 debug_print("Freeing LDAP server interface object\n");
227 ldapServer->callBack = NULL;
229 /* Free internal stuff */
230 g_free( ldapServer->name );
231 g_free( ldapServer->hostName );
232 g_free( ldapServer->baseDN );
233 g_free( ldapServer->bindDN );
234 g_free( ldapServer->bindPass );
235 g_free( ldapServer->searchCriteria );
236 g_free( ldapServer->searchValue );
238 ldapServer->port = 0;
239 ldapServer->entriesRead = 0;
240 ldapServer->maxEntries = 0;
241 ldapServer->newSearch = FALSE;
244 addrcache_clear( ldapServer->addressCache );
245 addrcache_free( ldapServer->addressCache );
248 ldapServer->name = NULL;
249 ldapServer->hostName = NULL;
250 ldapServer->baseDN = NULL;
251 ldapServer->bindDN = NULL;
252 ldapServer->bindPass = NULL;
253 ldapServer->searchCriteria = NULL;
254 ldapServer->searchValue = NULL;
255 ldapServer->addressCache = NULL;
256 g_free(ldapServer->thread);
257 ldapServer->thread = NULL;
258 ldapServer->busyFlag = FALSE;
259 ldapServer->retVal = MGU_SUCCESS;
260 ldapServer->accessFlag = FALSE;
262 /* Now release LDAP object */
263 g_free( ldapServer );
268 * Display object to specified stream.
270 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
271 g_return_if_fail( ldapServer != NULL );
273 fprintf( stream, "SyldapServer:\n" );
274 fprintf( stream, " name: '%s'\n", ldapServer->name );
275 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
276 fprintf( stream, " port: %d\n", ldapServer->port );
277 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
278 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
279 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
280 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
281 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
282 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
283 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
284 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
285 addrcache_print( ldapServer->addressCache, stream );
286 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
290 * Display object to specified stream.
292 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
293 g_return_if_fail( ldapServer != NULL );
295 fprintf( stream, "SyldapServer:\n" );
296 fprintf( stream, " name: '%s'\n", ldapServer->name );
297 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
298 fprintf( stream, " port: %d\n", ldapServer->port );
299 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
300 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
301 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
302 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
303 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
304 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
305 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
306 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
310 * Build an address list entry and append to list of address items. Name is formatted
311 * as it appears in the common name (cn) attribute.
313 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
316 GSList *nodeName = listName;
319 GSList *nodeAddress = listAddr;
320 person = addritem_create_item_person();
321 addritem_person_set_common_name( person, nodeName->data );
322 addrcache_id_person( ldapServer->addressCache, person );
323 addrcache_add_person( ldapServer->addressCache, person );
325 while( nodeAddress ) {
326 email = addritem_create_item_email();
327 addritem_email_set_address( email, nodeAddress->data );
328 addrcache_id_email( ldapServer->addressCache, email );
329 addrcache_person_add_email( ldapServer->addressCache, person, email );
330 nodeAddress = g_slist_next( nodeAddress );
331 ldapServer->entriesRead++;
333 nodeName = g_slist_next( nodeName );
338 * Build an address list entry and append to list of address items. Name is formatted
339 * as "<first-name> <last-name>".
341 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
342 GSList *nodeFirst = listFirst;
343 GSList *nodeAddress = listAddr;
344 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
345 gint iLen = 0, iLenT = 0;
349 /* Find longest first name in list */
351 if( firstName == NULL ) {
352 firstName = nodeFirst->data;
353 iLen = strlen( firstName );
356 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
357 firstName = nodeFirst->data;
361 nodeFirst = g_slist_next( nodeFirst );
366 lastName = listLast->data;
371 fullName = g_strdup_printf( "%s %s", firstName, lastName );
374 fullName = g_strdup_printf( "%s", firstName );
379 fullName = g_strdup_printf( "%s", lastName );
383 g_strchug( fullName ); g_strchomp( fullName );
387 person = addritem_create_item_person();
388 addritem_person_set_common_name( person, fullName );
389 addritem_person_set_first_name( person, firstName );
390 addritem_person_set_last_name( person, lastName );
391 addrcache_id_person( ldapServer->addressCache, person );
392 addrcache_add_person( ldapServer->addressCache, person );
395 /* Add address item */
396 while( nodeAddress ) {
397 email = addritem_create_item_email();
398 addritem_email_set_address( email, nodeAddress->data );
399 addrcache_id_email( ldapServer->addressCache, email );
400 addrcache_person_add_email( ldapServer->addressCache, person, email );
401 nodeAddress = g_slist_next( nodeAddress );
402 ldapServer->entriesRead++;
405 fullName = firstName = lastName = NULL;
410 * Add all attribute values to a list.
412 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
417 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
418 for( i = 0; vals[i] != NULL; i++ ) {
419 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
420 list = g_slist_append( list, g_strdup( vals[i] ) );
423 ldap_value_free( vals );
428 * Add a single attribute value to a list.
430 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
434 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
435 if( vals[0] != NULL ) {
436 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
437 list = g_slist_append( list, g_strdup( vals[0] ) );
440 ldap_value_free( vals );
445 * Free linked lists of character strings.
447 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
448 mgu_free_list( listName );
449 mgu_free_list( listAddr );
450 mgu_free_list( listID );
451 mgu_free_list( listDN );
452 mgu_free_list( listFirst );
453 mgu_free_list( listLast );
457 * Check parameters that are required for a search. This should
458 * be called before performing a search.
459 * Return: TRUE if search criteria appear OK.
461 gboolean syldap_check_search( SyldapServer *ldapServer ) {
462 g_return_val_if_fail( ldapServer != NULL, FALSE );
464 ldapServer->retVal = MGU_LDAP_CRITERIA;
466 /* Test search criteria */
467 if( ldapServer->searchCriteria == NULL ) {
470 if( strlen( ldapServer->searchCriteria ) < 1 ) {
474 if( ldapServer->searchValue == NULL ) {
477 if( strlen( ldapServer->searchValue ) < 1 ) {
481 ldapServer->retVal = MGU_SUCCESS;
486 * Perform the LDAP search, reading LDAP entries into cache.
487 * Note that one LDAP entry can have multiple values for many of its
488 * attributes. If these attributes are E-Mail addresses; these are
489 * broken out into separate address items. For any other attribute,
490 * only the first occurrence is read.
492 gint syldap_search( SyldapServer *ldapServer ) {
494 LDAPMessage *result, *e;
500 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
501 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
502 struct timeval timeout;
503 gboolean entriesFound = FALSE;
505 g_return_val_if_fail( ldapServer != NULL, -1 );
507 ldapServer->retVal = MGU_SUCCESS;
508 if( ! syldap_check_search( ldapServer ) ) {
509 return ldapServer->retVal;
513 timeout.tv_sec = ldapServer->timeOut;
514 timeout.tv_usec = 0L;
516 ldapServer->entriesRead = 0;
517 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
518 ldapServer->retVal = MGU_LDAP_INIT;
519 return ldapServer->retVal;
522 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
524 /* Bind to the server, if required */
525 if( ldapServer->bindDN ) {
526 if( * ldapServer->bindDN != '\0' ) {
527 /* printf( "binding...\n" ); */
528 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
529 /* printf( "rc=%d\n", rc ); */
530 if( rc != LDAP_SUCCESS ) {
531 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
533 ldapServer->retVal = MGU_LDAP_BIND;
534 return ldapServer->retVal;
539 /* Define all attributes we are interested in. */
540 attribs[0] = SYLDAP_ATTR_DN;
541 attribs[1] = SYLDAP_ATTR_COMMONNAME;
542 attribs[2] = SYLDAP_ATTR_GIVENNAME;
543 attribs[3] = SYLDAP_ATTR_SURNAME;
544 attribs[4] = SYLDAP_ATTR_EMAIL;
545 attribs[5] = SYLDAP_ATTR_UID;
548 /* Create LDAP search string and apply search criteria */
549 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
550 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
551 &timeout, 0, &result );
554 if( rc == LDAP_TIMEOUT ) {
556 ldapServer->retVal = MGU_LDAP_TIMEOUT;
557 return ldapServer->retVal;
559 if( rc != LDAP_SUCCESS ) {
560 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
562 ldapServer->retVal = MGU_LDAP_SEARCH;
563 return ldapServer->retVal;
566 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
568 /* Clear the cache if we have new entries, otherwise leave untouched. */
569 if( ldap_count_entries( ld, result ) > 0 ) {
570 addrcache_clear( ldapServer->addressCache );
573 /* Process results */
574 ldapServer->entriesRead = 0;
575 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
577 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
578 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
580 /* Process all attributes */
581 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
582 attribute = ldap_next_attribute( ld, e, ber ) ) {
583 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
584 listName = syldap_add_list_values( ld, e, attribute );
586 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
587 listAddress = syldap_add_list_values( ld, e, attribute );
589 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
590 listID = syldap_add_single_value( ld, e, attribute );
592 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
593 listFirst = syldap_add_list_values( ld, e, attribute );
595 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
596 listLast = syldap_add_single_value( ld, e, attribute );
598 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
599 listDN = syldap_add_single_value( ld, e, attribute );
603 /* Free memory used to store attribute */
604 ldap_memfree( attribute );
606 /* Format and add items to cache */
607 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
610 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
611 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
618 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
619 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
621 /* Free up and disconnect */
622 ldap_msgfree( result );
624 ldapServer->newSearch = FALSE;
626 ldapServer->retVal = MGU_SUCCESS;
629 ldapServer->retVal = MGU_LDAP_NOENTRIES;
631 return ldapServer->retVal;
634 /* syldap_display_search_results() - updates the ui. this function is called from the
635 * main thread (the thread running the GTK event loop). */
636 static gint syldap_display_search_results(SyldapServer *ldapServer)
638 /* NOTE: when this function is called the accompanying thread should
639 * already be terminated. */
640 gtk_idle_remove(ldapServer->idleId);
641 ldapServer->callBack(ldapServer);
642 /* FIXME: match should know whether to free this SyldapServer stuff. */
643 g_free(ldapServer->thread);
644 ldapServer->thread = NULL;
648 /* ============================================================================================ */
650 * Read data into list. Main entry point
651 * Return: TRUE if file read successfully.
653 /* ============================================================================================ */
654 gint syldap_read_data( SyldapServer *ldapServer ) {
655 g_return_val_if_fail( ldapServer != NULL, -1 );
657 ldapServer->accessFlag = FALSE;
658 pthread_detach( pthread_self() );
659 if( ldapServer->newSearch ) {
660 /* Read data into the list */
661 syldap_search( ldapServer );
664 ldapServer->addressCache->modified = FALSE;
665 ldapServer->addressCache->dataRead = TRUE;
666 ldapServer->accessFlag = FALSE;
670 ldapServer->busyFlag = FALSE;
671 if( ldapServer->callBack ) {
672 /* make the ui thread update the search results */
673 /* TODO: really necessary to call gdk_threads_XXX()??? gtk_idle_add()
674 * should do this - could someone check the GTK sources please? */
676 ldapServer->idleId = gtk_idle_add(syldap_display_search_results, ldapServer);
681 return ldapServer->retVal;
684 /* ============================================================================================ */
686 * Cancel read with thread.
688 /* ============================================================================================ */
689 void syldap_cancel_read( SyldapServer *ldapServer ) {
690 g_return_if_fail( ldapServer != NULL );
692 /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */
693 if( ldapServer->thread ) {
694 /* printf( "thread cancelled\n" ); */
695 pthread_cancel( *ldapServer->thread );
697 g_free(ldapServer->thread);
698 ldapServer->thread = NULL;
699 ldapServer->busyFlag = FALSE;
702 /* ============================================================================================ */
704 * Read data into list using a background thread.
705 * Return: TRUE if file read successfully. Callback function will be
706 * notified when search is complete.
708 /* ============================================================================================ */
709 gint syldap_read_data_th( SyldapServer *ldapServer ) {
710 g_return_val_if_fail( ldapServer != NULL, -1 );
712 ldapServer->busyFlag = FALSE;
713 syldap_check_search( ldapServer );
714 if( ldapServer->retVal == MGU_SUCCESS ) {
715 // debug_print("Staring LDAP read thread\n");
717 ldapServer->busyFlag = TRUE;
718 ldapServer->thread = g_new0(pthread_t, 1);
719 pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer );
721 return ldapServer->retVal;
725 * Return link list of persons.
727 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
728 g_return_val_if_fail( ldapServer != NULL, NULL );
729 return addrcache_get_list_person( ldapServer->addressCache );
733 * Return link list of folders. This is always NULL since there are
734 * no folders in GnomeCard.
737 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
738 g_return_val_if_fail( ldapServer != NULL, NULL );
742 #define SYLDAP_TEST_FILTER "(objectclass=*)"
743 #define SYLDAP_SEARCHBASE_V2 "cn=config"
744 #define SYLDAP_SEARCHBASE_V3 ""
745 #define SYLDAP_V2_TEST_ATTR "database"
746 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
749 * Attempt to discover the base DN for the server.
753 * bindDN Bind DN (optional).
754 * bindPW Bind PW (optional).
755 * tov Timeout value (seconds), or 0 for none, default 30 secs.
756 * Return: List of Base DN's, or NULL if could not read. Base DN should
757 * be g_free() when done.
759 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
760 GList *baseDN = NULL;
763 LDAPMessage *result, *e;
768 struct timeval timeout;
770 if( host == NULL ) return baseDN;
771 if( port < 1 ) return baseDN;
774 timeout.tv_usec = 0L;
776 timeout.tv_sec = tov;
779 timeout.tv_sec = 30L;
782 /* Connect to server. */
783 if( ( ld = ldap_init( host, port ) ) == NULL ) {
787 /* Bind to the server, if required */
789 if( *bindDN != '\0' ) {
790 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
791 if( rc != LDAP_SUCCESS ) {
792 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
799 /* Test for LDAP version 3 */
800 attribs[0] = SYLDAP_V3_TEST_ATTR;
802 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
803 0, NULL, NULL, &timeout, 0, &result );
804 if( rc == LDAP_SUCCESS ) {
805 /* Process entries */
806 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
807 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
809 /* Process attributes */
810 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
811 attribute = ldap_next_attribute( ld, e, ber ) ) {
812 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
813 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
814 for( i = 0; vals[i] != NULL; i++ ) {
815 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
816 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
819 ldap_value_free( vals );
822 ldap_memfree( attribute );
827 ldap_msgfree( result );
832 if( baseDN == NULL ) {
833 /* Test for LDAP version 2 */
835 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
836 0, NULL, NULL, &timeout, 0, &result );
837 if( rc == LDAP_SUCCESS ) {
838 /* Process entries */
839 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
840 /* if( baseDN ) break; */
841 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
843 /* Process attributes */
844 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
845 attribute = ldap_next_attribute( ld, e, ber ) ) {
846 /* if( baseDN ) break; */
847 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
848 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
849 for( i = 0; vals[i] != NULL; i++ ) {
851 /* Strip the 'ldb:' from the front of the value */
852 ch = ( char * ) strchr( vals[i], ':' );
854 gchar *bn = g_strdup( ++ch );
857 baseDN = g_list_append( baseDN, g_strdup( bn ) );
861 ldap_value_free( vals );
864 ldap_memfree( attribute );
869 ldap_msgfree( result );
877 * Attempt to discover the base DN for the server.
878 * Enter: ldapServer Server to test.
879 * Return: List of Base DN's, or NULL if could not read. Base DN should
880 * be g_free() when done. Return code set in ldapServer.
882 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
883 GList *baseDN = NULL;
886 LDAPMessage *result, *e;
891 struct timeval timeout;
893 ldapServer->retVal = MGU_BAD_ARGS;
894 if( ldapServer == NULL ) return baseDN;
895 if( ldapServer->hostName == NULL ) return baseDN;
896 if( ldapServer->port < 1 ) return baseDN;
899 timeout.tv_usec = 0L;
900 if( ldapServer->timeOut > 0 ) {
901 timeout.tv_sec = ldapServer->timeOut;
904 timeout.tv_sec = 30L;
907 /* Connect to server. */
908 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
909 ldapServer->retVal = MGU_LDAP_INIT;
913 /* Bind to the server, if required */
914 if( ldapServer->bindDN ) {
915 if( *ldapServer->bindDN != '\0' ) {
916 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
917 if( rc != LDAP_SUCCESS ) {
918 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
920 ldapServer->retVal = MGU_LDAP_BIND;
926 ldapServer->retVal = MGU_LDAP_SEARCH;
928 /* Test for LDAP version 3 */
929 attribs[0] = SYLDAP_V3_TEST_ATTR;
931 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
932 0, NULL, NULL, &timeout, 0, &result );
933 if( rc == LDAP_SUCCESS ) {
934 /* Process entries */
935 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
936 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
938 /* Process attributes */
939 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
940 attribute = ldap_next_attribute( ld, e, ber ) ) {
941 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
942 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
943 for( i = 0; vals[i] != NULL; i++ ) {
944 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
945 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
948 ldap_value_free( vals );
951 ldap_memfree( attribute );
956 ldap_msgfree( result );
957 ldapServer->retVal = MGU_SUCCESS;
959 else if( rc == LDAP_TIMEOUT ) {
960 ldapServer->retVal = MGU_LDAP_TIMEOUT;
963 if( baseDN == NULL ) {
964 /* Test for LDAP version 2 */
966 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
967 0, NULL, NULL, &timeout, 0, &result );
968 if( rc == LDAP_SUCCESS ) {
969 /* Process entries */
970 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
971 /* if( baseDN ) break; */
972 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
974 /* Process attributes */
975 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
976 attribute = ldap_next_attribute( ld, e, ber ) ) {
977 /* if( baseDN ) break; */
978 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
979 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
980 for( i = 0; vals[i] != NULL; i++ ) {
982 /* Strip the 'ldb:' from the front of the value */
983 ch = ( char * ) strchr( vals[i], ':' );
985 gchar *bn = g_strdup( ++ch );
988 baseDN = g_list_append( baseDN, g_strdup( bn ) );
992 ldap_value_free( vals );
995 ldap_memfree( attribute );
1000 ldap_msgfree( result );
1001 ldapServer->retVal = MGU_SUCCESS;
1003 else if( rc == LDAP_TIMEOUT ) {
1004 ldapServer->retVal = MGU_LDAP_TIMEOUT;
1013 * Attempt to connect to the server.
1017 * Return: TRUE if connected successfully.
1019 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1020 gboolean retVal = FALSE;
1023 if( host == NULL ) return retVal;
1024 if( port < 1 ) return retVal;
1025 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1035 * Attempt to connect to the server.
1036 * Enter: ldapServer Server to test.
1037 * Return: TRUE if connected successfully. Return code set in ldapServer.
1039 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1040 gboolean retVal = FALSE;
1043 ldapServer->retVal = MGU_BAD_ARGS;
1044 if( ldapServer == NULL ) return retVal;
1045 if( ldapServer->hostName == NULL ) return retVal;
1046 if( ldapServer->port < 1 ) return retVal;
1047 ldapServer->retVal = MGU_LDAP_INIT;
1048 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1049 ldapServer->retVal = MGU_SUCCESS;
1058 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
1059 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
1060 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1061 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1064 * Test whether LDAP libraries installed.
1065 * Return: TRUE if library available.
1067 gboolean syldap_test_ldap_lib() {
1071 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1076 /* Test for symbols we need */
1077 fun = dlsym( handle, "ldap_init" );
1082 dlclose( handle ); handle = NULL; fun = NULL;
1084 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1088 fun = dlsym( handle, "ber_init" );
1093 dlclose( handle ); handle = NULL; fun = NULL;
1095 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1099 fun = dlsym( handle, "res_query" );
1104 dlclose( handle ); handle = NULL; fun = NULL;
1106 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1110 fun = dlsym( handle, "pthread_create" );
1115 dlclose( handle ); handle = NULL; fun = NULL;
1120 #endif /* USE_LDAP */