2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2002 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>
42 #include "addrcache.h"
45 #include "adbookbase.h"
48 * Create new LDAP server interface object.
50 SyldapServer *syldap_create() {
51 SyldapServer *ldapServer;
53 debug_print("Creating LDAP server interface object\n");
55 ldapServer = g_new0( SyldapServer, 1 );
56 ldapServer->type = ADBOOKTYPE_LDAP;
57 ldapServer->addressCache = addrcache_create();
58 ldapServer->accessFlag = FALSE;
59 ldapServer->retVal = MGU_SUCCESS;
60 ldapServer->hostName = NULL;
61 ldapServer->port = SYLDAP_DFL_PORT;
62 ldapServer->baseDN = NULL;
63 ldapServer->bindDN = NULL;
64 ldapServer->bindPass = NULL;
65 ldapServer->searchCriteria = NULL;
66 ldapServer->searchValue = NULL;
67 ldapServer->entriesRead = 0;
68 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
69 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
70 ldapServer->newSearch = TRUE;
71 ldapServer->thread = NULL;
72 ldapServer->busyFlag = FALSE;
73 ldapServer->callBack = NULL;
74 ldapServer->idleId = 0;
79 * Specify name to be used.
81 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
82 g_return_if_fail( ldapServer != NULL );
83 addrcache_set_name( ldapServer->addressCache, value );
87 * Specify hostname to be used.
89 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
90 addrcache_refresh( ldapServer->addressCache );
91 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
92 g_strstrip( ldapServer->hostName );
96 * Specify port to be used.
98 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
99 addrcache_refresh( ldapServer->addressCache );
101 ldapServer->port = value;
104 ldapServer->port = SYLDAP_DFL_PORT;
109 * Specify base DN to be used.
111 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
112 addrcache_refresh( ldapServer->addressCache );
113 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
114 g_strstrip( ldapServer->baseDN );
118 * Specify bind DN to be used.
120 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
121 addrcache_refresh( ldapServer->addressCache );
122 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
123 g_strstrip( ldapServer->bindDN );
127 * Specify bind password to be used.
129 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
130 addrcache_refresh( ldapServer->addressCache );
131 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
132 g_strstrip( ldapServer->bindPass );
136 * Specify search criteria to be used.
138 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
139 addrcache_refresh( ldapServer->addressCache );
140 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
141 g_strstrip( ldapServer->searchCriteria );
142 ldapServer->newSearch = TRUE;
146 * Specify search value to be searched for.
148 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
149 addrcache_refresh( ldapServer->addressCache );
150 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
151 g_strstrip( ldapServer->searchValue );
152 ldapServer->newSearch = TRUE;
156 * Specify maximum number of entries to retrieve.
158 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
159 addrcache_refresh( ldapServer->addressCache );
161 ldapServer->maxEntries = value;
164 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
169 * Specify timeout value for LDAP operation (in seconds).
171 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
172 addrcache_refresh( ldapServer->addressCache );
174 ldapServer->timeOut = value;
177 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
182 * Register a callback function. When called, the function will be passed
183 * this object as an argument.
185 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
186 ldapServer->callBack = func;
189 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
190 g_return_if_fail( ldapServer != NULL );
191 ldapServer->accessFlag = value;
195 * Refresh internal variables to force a file read.
197 void syldap_force_refresh( SyldapServer *ldapServer ) {
198 addrcache_refresh( ldapServer->addressCache );
199 ldapServer->newSearch = TRUE;
202 gint syldap_get_status( SyldapServer *ldapServer ) {
203 g_return_val_if_fail( ldapServer != NULL, -1 );
204 return ldapServer->retVal;
207 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
208 g_return_val_if_fail( ldapServer != NULL, NULL );
209 return addrcache_get_root_folder( ldapServer->addressCache );
212 gchar *syldap_get_name( SyldapServer *ldapServer ) {
213 g_return_val_if_fail( ldapServer != NULL, NULL );
214 return addrcache_get_name( ldapServer->addressCache );
217 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
218 g_return_val_if_fail( ldapServer != NULL, FALSE );
219 return ldapServer->accessFlag;
223 * Free up LDAP server interface object by releasing internal memory.
225 void syldap_free( SyldapServer *ldapServer ) {
226 g_return_if_fail( ldapServer != NULL );
228 debug_print("Freeing LDAP server interface object\n");
230 ldapServer->callBack = NULL;
233 addrcache_clear( ldapServer->addressCache );
234 addrcache_free( ldapServer->addressCache );
236 /* Free internal stuff */
237 g_free( ldapServer->hostName );
238 g_free( ldapServer->baseDN );
239 g_free( ldapServer->bindDN );
240 g_free( ldapServer->bindPass );
241 g_free( ldapServer->searchCriteria );
242 g_free( ldapServer->searchValue );
243 g_free( ldapServer->thread );
247 ldapServer->hostName = NULL;
248 ldapServer->port = 0;
249 ldapServer->baseDN = NULL;
250 ldapServer->bindDN = NULL;
251 ldapServer->bindPass = NULL;
252 ldapServer->searchCriteria = NULL;
253 ldapServer->searchValue = NULL;
254 ldapServer->entriesRead = 0;
255 ldapServer->maxEntries = 0;
256 ldapServer->timeOut = 0;
257 ldapServer->newSearch = FALSE;
258 ldapServer->thread = NULL;
259 ldapServer->busyFlag = FALSE;
260 ldapServer->callBack = NULL;
261 ldapServer->idleId = 0;
263 ldapServer->type = ADBOOKTYPE_NONE;
264 ldapServer->addressCache = NULL;
265 ldapServer->accessFlag = FALSE;
266 ldapServer->retVal = MGU_SUCCESS;
268 /* Now release LDAP object */
269 g_free( ldapServer );
273 * Display object to specified stream.
275 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
276 g_return_if_fail( ldapServer != NULL );
278 fprintf( stream, "SyldapServer:\n" );
279 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
280 fprintf( stream, " port: %d\n", ldapServer->port );
281 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
282 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
283 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
284 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
285 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
286 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
287 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
288 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
289 addrcache_print( ldapServer->addressCache, stream );
290 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
294 * Display object to specified stream.
296 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
297 g_return_if_fail( ldapServer != NULL );
299 fprintf( stream, "SyldapServer:\n" );
300 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
301 fprintf( stream, " port: %d\n", ldapServer->port );
302 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
303 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
304 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
305 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
306 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
307 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
308 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
309 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
313 * Build an address list entry and append to list of address items. Name is formatted
314 * as it appears in the common name (cn) attribute.
316 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
319 GSList *nodeName = listName;
322 GSList *nodeAddress = listAddr;
323 person = addritem_create_item_person();
324 addritem_person_set_common_name( person, nodeName->data );
325 addrcache_id_person( ldapServer->addressCache, person );
326 addrcache_add_person( ldapServer->addressCache, person );
328 while( nodeAddress ) {
329 email = addritem_create_item_email();
330 addritem_email_set_address( email, nodeAddress->data );
331 addrcache_id_email( ldapServer->addressCache, email );
332 addrcache_person_add_email( ldapServer->addressCache, person, email );
333 nodeAddress = g_slist_next( nodeAddress );
334 ldapServer->entriesRead++;
336 nodeName = g_slist_next( nodeName );
341 * Build an address list entry and append to list of address items. Name is formatted
342 * as "<first-name> <last-name>".
344 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
345 GSList *nodeFirst = listFirst;
346 GSList *nodeAddress = listAddr;
347 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
348 gint iLen = 0, iLenT = 0;
352 /* Find longest first name in list */
354 if( firstName == NULL ) {
355 firstName = nodeFirst->data;
356 iLen = strlen( firstName );
359 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
360 firstName = nodeFirst->data;
364 nodeFirst = g_slist_next( nodeFirst );
369 lastName = listLast->data;
374 fullName = g_strdup_printf( "%s %s", firstName, lastName );
377 fullName = g_strdup_printf( "%s", firstName );
382 fullName = g_strdup_printf( "%s", lastName );
386 g_strchug( fullName ); g_strchomp( fullName );
390 person = addritem_create_item_person();
391 addritem_person_set_common_name( person, fullName );
392 addritem_person_set_first_name( person, firstName );
393 addritem_person_set_last_name( person, lastName );
394 addrcache_id_person( ldapServer->addressCache, person );
395 addrcache_add_person( ldapServer->addressCache, person );
398 /* Add address item */
399 while( nodeAddress ) {
400 email = addritem_create_item_email();
401 addritem_email_set_address( email, nodeAddress->data );
402 addrcache_id_email( ldapServer->addressCache, email );
403 addrcache_person_add_email( ldapServer->addressCache, person, email );
404 nodeAddress = g_slist_next( nodeAddress );
405 ldapServer->entriesRead++;
408 fullName = firstName = lastName = NULL;
413 * Add all attribute values to a list.
415 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
420 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
421 for( i = 0; vals[i] != NULL; i++ ) {
422 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
423 list = g_slist_append( list, g_strdup( vals[i] ) );
426 ldap_value_free( vals );
431 * Add a single attribute value to a list.
433 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
437 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
438 if( vals[0] != NULL ) {
439 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
440 list = g_slist_append( list, g_strdup( vals[0] ) );
443 ldap_value_free( vals );
448 * Free linked lists of character strings.
450 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
451 mgu_free_list( listName );
452 mgu_free_list( listAddr );
453 mgu_free_list( listID );
454 mgu_free_list( listDN );
455 mgu_free_list( listFirst );
456 mgu_free_list( listLast );
460 * Check parameters that are required for a search. This should
461 * be called before performing a search.
462 * Return: TRUE if search criteria appear OK.
464 gboolean syldap_check_search( SyldapServer *ldapServer ) {
465 g_return_val_if_fail( ldapServer != NULL, FALSE );
467 ldapServer->retVal = MGU_LDAP_CRITERIA;
469 /* Test search criteria */
470 if( ldapServer->searchCriteria == NULL ) {
473 if( strlen( ldapServer->searchCriteria ) < 1 ) {
477 if( ldapServer->searchValue == NULL ) {
480 if( strlen( ldapServer->searchValue ) < 1 ) {
484 ldapServer->retVal = MGU_SUCCESS;
489 * Perform the LDAP search, reading LDAP entries into cache.
490 * Note that one LDAP entry can have multiple values for many of its
491 * attributes. If these attributes are E-Mail addresses; these are
492 * broken out into separate address items. For any other attribute,
493 * only the first occurrence is read.
495 gint syldap_search( SyldapServer *ldapServer ) {
497 LDAPMessage *result, *e;
503 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
504 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
505 struct timeval timeout;
506 gboolean entriesFound = FALSE;
508 g_return_val_if_fail( ldapServer != NULL, -1 );
510 ldapServer->retVal = MGU_SUCCESS;
511 if( ! syldap_check_search( ldapServer ) ) {
512 return ldapServer->retVal;
516 timeout.tv_sec = ldapServer->timeOut;
517 timeout.tv_usec = 0L;
519 ldapServer->entriesRead = 0;
520 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
521 ldapServer->retVal = MGU_LDAP_INIT;
522 return ldapServer->retVal;
525 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
527 /* Bind to the server, if required */
528 if( ldapServer->bindDN ) {
529 if( * ldapServer->bindDN != '\0' ) {
530 /* printf( "binding...\n" ); */
531 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
532 /* printf( "rc=%d\n", rc ); */
533 if( rc != LDAP_SUCCESS ) {
534 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
536 ldapServer->retVal = MGU_LDAP_BIND;
537 return ldapServer->retVal;
542 /* Define all attributes we are interested in. */
543 attribs[0] = SYLDAP_ATTR_DN;
544 attribs[1] = SYLDAP_ATTR_COMMONNAME;
545 attribs[2] = SYLDAP_ATTR_GIVENNAME;
546 attribs[3] = SYLDAP_ATTR_SURNAME;
547 attribs[4] = SYLDAP_ATTR_EMAIL;
548 attribs[5] = SYLDAP_ATTR_UID;
551 /* Create LDAP search string and apply search criteria */
552 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
553 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
554 &timeout, 0, &result );
557 if( rc == LDAP_TIMEOUT ) {
559 ldapServer->retVal = MGU_LDAP_TIMEOUT;
560 return ldapServer->retVal;
562 if( rc != LDAP_SUCCESS ) {
563 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
565 ldapServer->retVal = MGU_LDAP_SEARCH;
566 return ldapServer->retVal;
569 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
571 /* Clear the cache if we have new entries, otherwise leave untouched. */
572 if( ldap_count_entries( ld, result ) > 0 ) {
573 addrcache_clear( ldapServer->addressCache );
576 /* Process results */
577 ldapServer->entriesRead = 0;
578 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
580 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
581 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
583 /* Process all attributes */
584 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
585 attribute = ldap_next_attribute( ld, e, ber ) ) {
586 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
587 listName = syldap_add_list_values( ld, e, attribute );
589 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
590 listAddress = syldap_add_list_values( ld, e, attribute );
592 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
593 listID = syldap_add_single_value( ld, e, attribute );
595 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
596 listFirst = syldap_add_list_values( ld, e, attribute );
598 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
599 listLast = syldap_add_single_value( ld, e, attribute );
601 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
602 listDN = syldap_add_single_value( ld, e, attribute );
606 /* Free memory used to store attribute */
607 ldap_memfree( attribute );
609 /* Format and add items to cache */
610 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
613 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
614 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
621 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
622 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
624 /* Free up and disconnect */
625 ldap_msgfree( result );
627 ldapServer->newSearch = FALSE;
629 ldapServer->retVal = MGU_SUCCESS;
632 ldapServer->retVal = MGU_LDAP_NOENTRIES;
634 return ldapServer->retVal;
637 /* syldap_display_search_results() - updates the ui. this function is called from the
638 * main thread (the thread running the GTK event loop). */
639 static gint syldap_display_search_results(SyldapServer *ldapServer)
641 /* NOTE: when this function is called the accompanying thread should
642 * already be terminated. */
643 gtk_idle_remove(ldapServer->idleId);
644 ldapServer->callBack(ldapServer);
645 /* FIXME: match should know whether to free this SyldapServer stuff. */
646 g_free(ldapServer->thread);
647 ldapServer->thread = NULL;
651 /* ============================================================================================ */
653 * Read data into list. Main entry point
654 * Return: TRUE if file read successfully.
656 /* ============================================================================================ */
657 gint syldap_read_data( SyldapServer *ldapServer ) {
658 g_return_val_if_fail( ldapServer != NULL, -1 );
660 ldapServer->accessFlag = FALSE;
661 pthread_detach( pthread_self() );
662 if( ldapServer->newSearch ) {
663 /* Read data into the list */
664 syldap_search( ldapServer );
667 ldapServer->addressCache->modified = FALSE;
668 ldapServer->addressCache->dataRead = TRUE;
669 ldapServer->accessFlag = FALSE;
673 ldapServer->busyFlag = FALSE;
674 if( ldapServer->callBack ) {
675 /* make the ui thread update the search results */
676 /* TODO: really necessary to call gdk_threads_XXX()??? gtk_idle_add()
677 * should do this - could someone check the GTK sources please? */
679 ldapServer->idleId = gtk_idle_add((GtkFunction)syldap_display_search_results,
684 return ldapServer->retVal;
687 /* ============================================================================================ */
689 * Cancel read with thread.
691 /* ============================================================================================ */
692 void syldap_cancel_read( SyldapServer *ldapServer ) {
693 g_return_if_fail( ldapServer != NULL );
695 /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */
696 if( ldapServer->thread ) {
697 /* printf( "thread cancelled\n" ); */
698 pthread_cancel( *ldapServer->thread );
700 g_free(ldapServer->thread);
701 ldapServer->thread = NULL;
702 ldapServer->busyFlag = FALSE;
705 /* ============================================================================================ */
707 * Read data into list using a background thread.
708 * Return: TRUE if file read successfully. Callback function will be
709 * notified when search is complete.
711 /* ============================================================================================ */
712 gint syldap_read_data_th( SyldapServer *ldapServer ) {
713 g_return_val_if_fail( ldapServer != NULL, -1 );
715 ldapServer->busyFlag = FALSE;
716 syldap_check_search( ldapServer );
717 if( ldapServer->retVal == MGU_SUCCESS ) {
718 /* debug_print("Staring LDAP read thread\n"); */
720 ldapServer->busyFlag = TRUE;
721 ldapServer->thread = g_new0(pthread_t, 1);
722 pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer );
724 return ldapServer->retVal;
728 * Return link list of persons.
730 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
731 g_return_val_if_fail( ldapServer != NULL, NULL );
732 return addrcache_get_list_person( ldapServer->addressCache );
736 * Return link list of folders. This is always NULL since there are
737 * no folders in GnomeCard.
740 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
741 g_return_val_if_fail( ldapServer != NULL, NULL );
745 #define SYLDAP_TEST_FILTER "(objectclass=*)"
746 #define SYLDAP_SEARCHBASE_V2 "cn=config"
747 #define SYLDAP_SEARCHBASE_V3 ""
748 #define SYLDAP_V2_TEST_ATTR "database"
749 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
752 * Attempt to discover the base DN for the server.
756 * bindDN Bind DN (optional).
757 * bindPW Bind PW (optional).
758 * tov Timeout value (seconds), or 0 for none, default 30 secs.
759 * Return: List of Base DN's, or NULL if could not read. Base DN should
760 * be g_free() when done.
762 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
763 GList *baseDN = NULL;
766 LDAPMessage *result, *e;
771 struct timeval timeout;
773 if( host == NULL ) return baseDN;
774 if( port < 1 ) return baseDN;
777 timeout.tv_usec = 0L;
779 timeout.tv_sec = tov;
782 timeout.tv_sec = 30L;
785 /* Connect to server. */
786 if( ( ld = ldap_init( host, port ) ) == NULL ) {
790 /* Bind to the server, if required */
792 if( *bindDN != '\0' ) {
793 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
794 if( rc != LDAP_SUCCESS ) {
795 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
802 /* Test for LDAP version 3 */
803 attribs[0] = SYLDAP_V3_TEST_ATTR;
805 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
806 0, NULL, NULL, &timeout, 0, &result );
807 if( rc == LDAP_SUCCESS ) {
808 /* Process entries */
809 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
810 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
812 /* Process attributes */
813 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
814 attribute = ldap_next_attribute( ld, e, ber ) ) {
815 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
816 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
817 for( i = 0; vals[i] != NULL; i++ ) {
818 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
819 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
822 ldap_value_free( vals );
825 ldap_memfree( attribute );
830 ldap_msgfree( result );
835 if( baseDN == NULL ) {
836 /* Test for LDAP version 2 */
838 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
839 0, NULL, NULL, &timeout, 0, &result );
840 if( rc == LDAP_SUCCESS ) {
841 /* Process entries */
842 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
843 /* if( baseDN ) break; */
844 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
846 /* Process attributes */
847 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
848 attribute = ldap_next_attribute( ld, e, ber ) ) {
849 /* if( baseDN ) break; */
850 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
851 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
852 for( i = 0; vals[i] != NULL; i++ ) {
854 /* Strip the 'ldb:' from the front of the value */
855 ch = ( char * ) strchr( vals[i], ':' );
857 gchar *bn = g_strdup( ++ch );
860 baseDN = g_list_append( baseDN, g_strdup( bn ) );
864 ldap_value_free( vals );
867 ldap_memfree( attribute );
872 ldap_msgfree( result );
880 * Attempt to discover the base DN for the server.
881 * Enter: ldapServer Server to test.
882 * Return: List of Base DN's, or NULL if could not read. Base DN should
883 * be g_free() when done. Return code set in ldapServer.
885 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
886 GList *baseDN = NULL;
889 LDAPMessage *result, *e;
894 struct timeval timeout;
896 ldapServer->retVal = MGU_BAD_ARGS;
897 if( ldapServer == NULL ) return baseDN;
898 if( ldapServer->hostName == NULL ) return baseDN;
899 if( ldapServer->port < 1 ) return baseDN;
902 timeout.tv_usec = 0L;
903 if( ldapServer->timeOut > 0 ) {
904 timeout.tv_sec = ldapServer->timeOut;
907 timeout.tv_sec = 30L;
910 /* Connect to server. */
911 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
912 ldapServer->retVal = MGU_LDAP_INIT;
916 /* Bind to the server, if required */
917 if( ldapServer->bindDN ) {
918 if( *ldapServer->bindDN != '\0' ) {
919 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
920 if( rc != LDAP_SUCCESS ) {
921 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
923 ldapServer->retVal = MGU_LDAP_BIND;
929 ldapServer->retVal = MGU_LDAP_SEARCH;
931 /* Test for LDAP version 3 */
932 attribs[0] = SYLDAP_V3_TEST_ATTR;
934 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
935 0, NULL, NULL, &timeout, 0, &result );
936 if( rc == LDAP_SUCCESS ) {
937 /* Process entries */
938 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
939 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
941 /* Process attributes */
942 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
943 attribute = ldap_next_attribute( ld, e, ber ) ) {
944 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
945 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
946 for( i = 0; vals[i] != NULL; i++ ) {
947 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
948 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
951 ldap_value_free( vals );
954 ldap_memfree( attribute );
959 ldap_msgfree( result );
960 ldapServer->retVal = MGU_SUCCESS;
962 else if( rc == LDAP_TIMEOUT ) {
963 ldapServer->retVal = MGU_LDAP_TIMEOUT;
966 if( baseDN == NULL ) {
967 /* Test for LDAP version 2 */
969 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
970 0, NULL, NULL, &timeout, 0, &result );
971 if( rc == LDAP_SUCCESS ) {
972 /* Process entries */
973 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
974 /* if( baseDN ) break; */
975 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
977 /* Process attributes */
978 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
979 attribute = ldap_next_attribute( ld, e, ber ) ) {
980 /* if( baseDN ) break; */
981 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
982 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
983 for( i = 0; vals[i] != NULL; i++ ) {
985 /* Strip the 'ldb:' from the front of the value */
986 ch = ( char * ) strchr( vals[i], ':' );
988 gchar *bn = g_strdup( ++ch );
991 baseDN = g_list_append( baseDN, g_strdup( bn ) );
995 ldap_value_free( vals );
998 ldap_memfree( attribute );
1003 ldap_msgfree( result );
1004 ldapServer->retVal = MGU_SUCCESS;
1006 else if( rc == LDAP_TIMEOUT ) {
1007 ldapServer->retVal = MGU_LDAP_TIMEOUT;
1016 * Attempt to connect to the server.
1020 * Return: TRUE if connected successfully.
1022 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1023 gboolean retVal = FALSE;
1026 if( host == NULL ) return retVal;
1027 if( port < 1 ) return retVal;
1028 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1038 * Attempt to connect to the server.
1039 * Enter: ldapServer Server to test.
1040 * Return: TRUE if connected successfully. Return code set in ldapServer.
1042 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1043 gboolean retVal = FALSE;
1046 ldapServer->retVal = MGU_BAD_ARGS;
1047 if( ldapServer == NULL ) return retVal;
1048 if( ldapServer->hostName == NULL ) return retVal;
1049 if( ldapServer->port < 1 ) return retVal;
1050 ldapServer->retVal = MGU_LDAP_INIT;
1051 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1052 ldapServer->retVal = MGU_SUCCESS;
1061 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
1062 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
1063 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1064 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1067 * Test whether LDAP libraries installed.
1068 * Return: TRUE if library available.
1070 gboolean syldap_test_ldap_lib() {
1074 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1079 /* Test for symbols we need */
1080 fun = dlsym( handle, "ldap_init" );
1085 dlclose( handle ); handle = NULL; fun = NULL;
1087 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1091 fun = dlsym( handle, "ber_init" );
1096 dlclose( handle ); handle = NULL; fun = NULL;
1098 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1102 fun = dlsym( handle, "res_query" );
1107 dlclose( handle ); handle = NULL; fun = NULL;
1109 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1113 fun = dlsym( handle, "pthread_create" );
1118 dlclose( handle ); handle = NULL; fun = NULL;
1123 #endif /* USE_LDAP */