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.
39 #include "addrcache.h"
43 * Create new LDAP server interface object.
45 SyldapServer *syldap_create() {
46 SyldapServer *ldapServer;
47 ldapServer = g_new0( SyldapServer, 1 );
48 ldapServer->name = NULL;
49 ldapServer->hostName = NULL;
50 ldapServer->port = SYLDAP_DFL_PORT;
51 ldapServer->baseDN = NULL;
52 ldapServer->bindDN = NULL;
53 ldapServer->bindPass = NULL;
54 ldapServer->searchCriteria = NULL;
55 ldapServer->searchValue = NULL;
56 ldapServer->entriesRead = 0;
57 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
58 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
59 ldapServer->newSearch = TRUE;
60 ldapServer->addressCache = addrcache_create();
61 ldapServer->thread = NULL;
62 ldapServer->busyFlag = FALSE;
63 ldapServer->retVal = MGU_SUCCESS;
64 ldapServer->callBack = NULL;
65 ldapServer->accessFlag = FALSE;
70 * Specify name to be used.
72 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
73 ldapServer->name = mgu_replace_string( ldapServer->name, value );
74 g_strstrip( ldapServer->name );
78 * Specify hostname to be used.
80 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
81 addrcache_refresh( ldapServer->addressCache );
82 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
83 g_strstrip( ldapServer->hostName );
87 * Specify port to be used.
89 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
90 addrcache_refresh( ldapServer->addressCache );
92 ldapServer->port = value;
95 ldapServer->port = SYLDAP_DFL_PORT;
100 * Specify base DN to be used.
102 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
103 addrcache_refresh( ldapServer->addressCache );
104 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
105 g_strstrip( ldapServer->baseDN );
109 * Specify bind DN to be used.
111 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
112 addrcache_refresh( ldapServer->addressCache );
113 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
114 g_strstrip( ldapServer->bindDN );
118 * Specify bind password to be used.
120 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
121 addrcache_refresh( ldapServer->addressCache );
122 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
123 g_strstrip( ldapServer->bindPass );
127 * Specify search criteria to be used.
129 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
130 addrcache_refresh( ldapServer->addressCache );
131 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
132 g_strstrip( ldapServer->searchCriteria );
133 ldapServer->newSearch = TRUE;
137 * Specify search value to be searched for.
139 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
140 addrcache_refresh( ldapServer->addressCache );
141 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
142 g_strstrip( ldapServer->searchValue );
143 ldapServer->newSearch = TRUE;
147 * Specify maximum number of entries to retrieve.
149 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
150 addrcache_refresh( ldapServer->addressCache );
152 ldapServer->maxEntries = value;
155 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
160 * Specify timeout value for LDAP operation (in seconds).
162 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
163 addrcache_refresh( ldapServer->addressCache );
165 ldapServer->timeOut = value;
168 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
173 * Register a callback function. When called, the function will be passed
174 * this object as an argument.
176 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
177 ldapServer->callBack = func;
180 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
181 g_return_if_fail( ldapServer != NULL );
182 ldapServer->accessFlag = value;
186 * Refresh internal variables to force a file read.
188 void syldap_force_refresh( SyldapServer *ldapServer ) {
189 addrcache_refresh( ldapServer->addressCache );
190 ldapServer->newSearch = TRUE;
193 gint syldap_get_status( SyldapServer *ldapServer ) {
194 g_return_if_fail( ldapServer != NULL );
195 return ldapServer->retVal;
197 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
198 g_return_if_fail( ldapServer != NULL );
199 return addrcache_get_root_folder( ldapServer->addressCache );
201 gchar *syldap_get_name( SyldapServer *ldapServer ) {
202 g_return_if_fail( ldapServer != NULL );
203 return ldapServer->name;
205 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
206 g_return_if_fail( ldapServer != NULL );
207 return ldapServer->accessFlag;
211 * Free up LDAP server interface object by releasing internal memory.
213 void syldap_free( SyldapServer *ldapServer ) {
214 g_return_if_fail( ldapServer != NULL );
216 ldapServer->callBack = NULL;
218 // Free internal stuff
219 g_free( ldapServer->name );
220 g_free( ldapServer->hostName );
221 g_free( ldapServer->baseDN );
222 g_free( ldapServer->bindDN );
223 g_free( ldapServer->bindPass );
224 g_free( ldapServer->searchCriteria );
225 g_free( ldapServer->searchValue );
227 ldapServer->port = 0;
228 ldapServer->entriesRead = 0;
229 ldapServer->maxEntries = 0;
230 ldapServer->newSearch = FALSE;
233 addrcache_clear( ldapServer->addressCache );
234 addrcache_free( ldapServer->addressCache );
237 ldapServer->name = NULL;
238 ldapServer->hostName = NULL;
239 ldapServer->baseDN = NULL;
240 ldapServer->bindDN = NULL;
241 ldapServer->bindPass = NULL;
242 ldapServer->searchCriteria = NULL;
243 ldapServer->searchValue = NULL;
244 ldapServer->addressCache = NULL;
245 ldapServer->thread = NULL;
246 ldapServer->busyFlag = FALSE;
247 ldapServer->retVal = MGU_SUCCESS;
248 ldapServer->accessFlag = FALSE;
250 // Now release LDAP object
251 g_free( ldapServer );
256 * Display object to specified stream.
258 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
260 g_return_if_fail( ldapServer != NULL );
261 fprintf( stream, "SyldapServer:\n" );
262 fprintf( stream, " name: '%s'\n", ldapServer->name );
263 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
264 fprintf( stream, " port: %d\n", ldapServer->port );
265 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
266 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
267 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
268 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
269 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
270 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
271 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
272 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
273 addrcache_print( ldapServer->addressCache, stream );
274 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
278 * Display object to specified stream.
280 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
282 g_return_if_fail( ldapServer != NULL );
283 fprintf( stream, "SyldapServer:\n" );
284 fprintf( stream, " name: '%s'\n", ldapServer->name );
285 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
286 fprintf( stream, " port: %d\n", ldapServer->port );
287 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
288 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
289 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
290 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
291 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
292 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
293 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
294 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
298 * Build an address list entry and append to list of address items. Name is formatted
299 * as it appears in the common name (cn) attribute.
301 static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
304 GSList *nodeName = listName;
306 GSList *nodeAddress = listAddr;
307 person = addritem_create_item_person();
308 addritem_person_set_common_name( person, nodeName->data );
309 addrcache_id_person( ldapServer->addressCache, person );
310 addrcache_add_person( ldapServer->addressCache, person );
312 while( nodeAddress ) {
313 email = addritem_create_item_email();
314 addritem_email_set_address( email, nodeAddress->data );
315 addrcache_id_email( ldapServer->addressCache, email );
316 addrcache_person_add_email( ldapServer->addressCache, person, email );
317 nodeAddress = g_slist_next( nodeAddress );
318 ldapServer->entriesRead++;
320 nodeName = g_slist_next( nodeName );
325 * Build an address list entry and append to list of address items. Name is formatted
326 * as "<first-name> <last-name>".
328 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
329 GSList *nodeFirst = listFirst;
330 GSList *nodeAddress = listAddr;
331 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
332 gint iLen = 0, iLenT = 0;
336 // Find longest first name in list
338 if( firstName == NULL ) {
339 firstName = nodeFirst->data;
340 iLen = strlen( firstName );
343 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
344 firstName = nodeFirst->data;
348 nodeFirst = g_slist_next( nodeFirst );
353 lastName = listLast->data;
358 fullName = g_strdup_printf( "%s %s", firstName, lastName );
361 fullName = g_strdup_printf( "%s", firstName );
366 fullName = g_strdup_printf( "%s", lastName );
370 g_strchug( fullName ); g_strchomp( fullName );
374 person = addritem_create_item_person();
375 addritem_person_set_common_name( person, fullName );
376 addritem_person_set_first_name( person, firstName );
377 addritem_person_set_last_name( person, lastName );
378 addrcache_id_person( ldapServer->addressCache, person );
379 addrcache_add_person( ldapServer->addressCache, person );
383 while( nodeAddress ) {
384 email = addritem_create_item_email();
385 addritem_email_set_address( email, nodeAddress->data );
386 addrcache_id_email( ldapServer->addressCache, email );
387 addrcache_person_add_email( ldapServer->addressCache, person, email );
388 nodeAddress = g_slist_next( nodeAddress );
389 ldapServer->entriesRead++;
392 fullName = firstName = lastName = NULL;
397 * Add all attribute values to a list.
399 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
403 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
404 for( i = 0; vals[i] != NULL; i++ ) {
405 // printf( "lv\t%s: %s\n", attr, vals[i] );
406 list = g_slist_append( list, g_strdup( vals[i] ) );
409 ldap_value_free( vals );
414 * Add a single attribute value to a list.
416 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
419 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
420 if( vals[0] != NULL ) {
421 // printf( "sv\t%s: %s\n", attr, vals[0] );
422 list = g_slist_append( list, g_strdup( vals[0] ) );
425 ldap_value_free( vals );
430 * Free linked lists of character strings.
432 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
433 mgu_free_list( listName );
434 mgu_free_list( listAddr );
435 mgu_free_list( listID );
436 mgu_free_list( listDN );
437 mgu_free_list( listFirst );
438 mgu_free_list( listLast );
442 * Check parameters that are required for a search. This should
443 * be called before performing a search.
444 * Return: TRUE if search criteria appear OK.
446 gboolean syldap_check_search( SyldapServer *ldapServer ) {
447 g_return_if_fail( ldapServer != NULL );
448 ldapServer->retVal = MGU_LDAP_CRITERIA;
450 // Test search criteria
451 if( ldapServer->searchCriteria == NULL ) {
454 if( strlen( ldapServer->searchCriteria ) < 1 ) {
458 if( ldapServer->searchValue == NULL ) {
461 if( strlen( ldapServer->searchValue ) < 1 ) {
465 ldapServer->retVal = MGU_SUCCESS;
470 * Perform the LDAP search, reading LDAP entries into cache.
471 * Note that one LDAP entry can have multiple values for many of its
472 * attributes. If these attributes are E-Mail addresses; these are
473 * broken out into separate address items. For any other attribute,
474 * only the first occurrence is read.
476 gint syldap_search( SyldapServer *ldapServer ) {
478 LDAPMessage *result, *e;
484 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
485 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
486 struct timeval timeout;
487 gboolean entriesFound = FALSE;
489 g_return_if_fail( ldapServer != NULL );
491 ldapServer->retVal = MGU_SUCCESS;
492 if( ! syldap_check_search( ldapServer ) ) {
493 return ldapServer->retVal;
497 timeout.tv_sec = ldapServer->timeOut;
498 timeout.tv_usec = 0L;
500 ldapServer->entriesRead = 0;
501 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
502 ldapServer->retVal = MGU_LDAP_INIT;
503 return ldapServer->retVal;
506 // printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port );
508 // Bind to the server, if required
509 if( ldapServer->bindDN ) {
510 if( * ldapServer->bindDN != '\0' ) {
511 // printf( "binding...\n" );
512 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
513 // printf( "rc=%d\n", rc );
514 if( rc != LDAP_SUCCESS ) {
515 // printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
517 ldapServer->retVal = MGU_LDAP_BIND;
518 return ldapServer->retVal;
523 // Define all attributes we are interested in.
524 attribs[0] = SYLDAP_ATTR_DN;
525 attribs[1] = SYLDAP_ATTR_COMMONNAME;
526 attribs[2] = SYLDAP_ATTR_GIVENNAME;
527 attribs[3] = SYLDAP_ATTR_SURNAME;
528 attribs[4] = SYLDAP_ATTR_EMAIL;
529 attribs[5] = SYLDAP_ATTR_UID;
532 // Create LDAP search string and apply search criteria
533 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
534 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
535 &timeout, 0, &result );
538 if( rc == LDAP_TIMEOUT ) {
540 ldapServer->retVal = MGU_LDAP_TIMEOUT;
541 return ldapServer->retVal;
543 if( rc != LDAP_SUCCESS ) {
544 // printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
546 ldapServer->retVal = MGU_LDAP_SEARCH;
547 return ldapServer->retVal;
550 // printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
552 // Clear the cache if we have new entries, otherwise leave untouched.
553 if( ldap_count_entries( ld, result ) > 0 ) {
554 addrcache_clear( ldapServer->addressCache );
558 ldapServer->entriesRead = 0;
559 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
561 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
562 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
564 // Process all attributes
565 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
566 attribute = ldap_next_attribute( ld, e, ber ) ) {
567 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
568 listName = syldap_add_list_values( ld, e, attribute );
570 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
571 listAddress = syldap_add_list_values( ld, e, attribute );
573 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
574 listID = syldap_add_single_value( ld, e, attribute );
576 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
577 listFirst = syldap_add_list_values( ld, e, attribute );
579 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
580 listLast = syldap_add_single_value( ld, e, attribute );
582 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
583 listDN = syldap_add_single_value( ld, e, attribute );
587 // Free memory used to store attribute
588 ldap_memfree( attribute );
590 // Format and add items to cache
591 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
594 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
595 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
602 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
603 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
605 // Free up and disconnect
606 ldap_msgfree( result );
608 ldapServer->newSearch = FALSE;
610 ldapServer->retVal = MGU_SUCCESS;
613 ldapServer->retVal = MGU_LDAP_NOENTRIES;
615 return ldapServer->retVal;
618 // ============================================================================================
620 * Read data into list. Main entry point
621 * Return: TRUE if file read successfully.
623 // ============================================================================================
624 gint syldap_read_data( SyldapServer *ldapServer ) {
625 g_return_if_fail( ldapServer != NULL );
627 ldapServer->accessFlag = FALSE;
628 pthread_detach( pthread_self() );
629 if( ldapServer->newSearch ) {
630 // Read data into the list
631 syldap_search( ldapServer );
634 ldapServer->addressCache->modified = FALSE;
635 ldapServer->addressCache->dataRead = TRUE;
636 ldapServer->accessFlag = FALSE;
640 ldapServer->busyFlag = FALSE;
641 if( ldapServer->callBack ) {
643 ( ldapServer->callBack )( ldapServer );
645 ldapServer->thread = NULL;
646 pthread_exit( NULL );
647 return ldapServer->retVal;
650 // ============================================================================================
652 * Cancel read with thread.
654 // ============================================================================================
655 void syldap_cancel_read( SyldapServer *ldapServer ) {
656 g_return_if_fail( ldapServer != NULL );
657 if( ldapServer->thread ) {
658 // printf( "thread cancelled\n" );
659 pthread_cancel( *ldapServer->thread );
661 ldapServer->thread = NULL;
662 ldapServer->busyFlag = FALSE;
665 // ============================================================================================
667 * Read data into list using a background thread.
668 * Return: TRUE if file read successfully. Callback function will be
669 * notified when search is complete.
671 // ============================================================================================
672 gint syldap_read_data_th( SyldapServer *ldapServer ) {
674 g_return_if_fail( ldapServer != NULL );
676 ldapServer->busyFlag = FALSE;
677 syldap_check_search( ldapServer );
678 if( ldapServer->retVal == MGU_SUCCESS ) {
679 ldapServer->busyFlag = TRUE;
680 ldapServer->thread = &thread;
681 pthread_create( ldapServer->thread, NULL, (void *) &syldap_read_data, (void *) ldapServer );
683 return ldapServer->retVal;
687 * Return link list of persons.
689 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
690 g_return_if_fail( ldapServer != NULL );
691 return addrcache_get_list_person( ldapServer->addressCache );
695 * Return link list of folders. This is always NULL since there are
696 * no folders in GnomeCard.
699 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
700 g_return_if_fail( ldapServer != NULL );
704 #define SYLDAP_TEST_FILTER "(objectclass=*)"
705 #define SYLDAP_SEARCHBASE_V2 "cn=config"
706 #define SYLDAP_SEARCHBASE_V3 ""
707 #define SYLDAP_V2_TEST_ATTR "database"
708 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
711 * Attempt to discover the base DN for the server.
715 * bindDN Bind DN (optional).
716 * bindPW Bind PW (optional).
717 * tov Timeout value (seconds), or 0 for none, default 30 secs.
718 * Return: List of Base DN's, or NULL if could not read. Base DN should
719 * be g_free() when done.
721 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
722 GList *baseDN = NULL;
725 LDAPMessage *result, *e;
730 struct timeval timeout;
732 if( host == NULL ) return baseDN;
733 if( port < 1 ) return baseDN;
736 timeout.tv_usec = 0L;
738 timeout.tv_sec = tov;
741 timeout.tv_sec = 30L;
744 // Connect to server.
745 if( ( ld = ldap_init( host, port ) ) == NULL ) {
749 // Bind to the server, if required
751 if( *bindDN != '\0' ) {
752 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
753 if( rc != LDAP_SUCCESS ) {
754 // printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
761 // Test for LDAP version 3
762 attribs[0] = SYLDAP_V3_TEST_ATTR;
764 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
765 0, NULL, NULL, &timeout, 0, &result );
766 if( rc == LDAP_SUCCESS ) {
768 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
769 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
771 // Process attributes
772 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
773 attribute = ldap_next_attribute( ld, e, ber ) ) {
774 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
775 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
776 for( i = 0; vals[i] != NULL; i++ ) {
777 // printf( "\t%s: %s\n", attribute, vals[i] );
778 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
781 ldap_value_free( vals );
784 ldap_memfree( attribute );
789 ldap_msgfree( result );
794 if( baseDN == NULL ) {
795 // Test for LDAP version 2
797 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
798 0, NULL, NULL, &timeout, 0, &result );
799 if( rc == LDAP_SUCCESS ) {
801 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
802 // if( baseDN ) break;
803 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
805 // Process attributes
806 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
807 attribute = ldap_next_attribute( ld, e, ber ) ) {
808 // if( baseDN ) break;
809 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
810 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
811 for( i = 0; vals[i] != NULL; i++ ) {
813 // Strip the 'ldb:' from the front of the value
814 ch = ( char * ) strchr( vals[i], ':' );
816 gchar *bn = g_strdup( ++ch );
819 baseDN = g_list_append( baseDN, g_strdup( bn ) );
823 ldap_value_free( vals );
826 ldap_memfree( attribute );
831 ldap_msgfree( result );
839 * Attempt to discover the base DN for the server.
840 * Enter: ldapServer Server to test.
841 * Return: List of Base DN's, or NULL if could not read. Base DN should
842 * be g_free() when done. Return code set in ldapServer.
844 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
845 GList *baseDN = NULL;
848 LDAPMessage *result, *e;
853 struct timeval timeout;
855 ldapServer->retVal = MGU_BAD_ARGS;
856 if( ldapServer == NULL ) return baseDN;
857 if( ldapServer->hostName == NULL ) return baseDN;
858 if( ldapServer->port < 1 ) return baseDN;
861 timeout.tv_usec = 0L;
862 if( ldapServer->timeOut > 0 ) {
863 timeout.tv_sec = ldapServer->timeOut;
866 timeout.tv_sec = 30L;
869 // Connect to server.
870 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
871 ldapServer->retVal = MGU_LDAP_INIT;
875 // Bind to the server, if required
876 if( ldapServer->bindDN ) {
877 if( *ldapServer->bindDN != '\0' ) {
878 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
879 if( rc != LDAP_SUCCESS ) {
880 //printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
882 ldapServer->retVal = MGU_LDAP_BIND;
888 ldapServer->retVal = MGU_LDAP_SEARCH;
890 // Test for LDAP version 3
891 attribs[0] = SYLDAP_V3_TEST_ATTR;
893 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
894 0, NULL, NULL, &timeout, 0, &result );
895 if( rc == LDAP_SUCCESS ) {
897 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
898 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
900 // Process attributes
901 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
902 attribute = ldap_next_attribute( ld, e, ber ) ) {
903 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
904 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
905 for( i = 0; vals[i] != NULL; i++ ) {
906 // printf( "\t%s: %s\n", attribute, vals[i] );
907 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
910 ldap_value_free( vals );
913 ldap_memfree( attribute );
918 ldap_msgfree( result );
919 ldapServer->retVal = MGU_SUCCESS;
921 else if( rc == LDAP_TIMEOUT ) {
922 ldapServer->retVal = MGU_LDAP_TIMEOUT;
925 if( baseDN == NULL ) {
926 // Test for LDAP version 2
928 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
929 0, NULL, NULL, &timeout, 0, &result );
930 if( rc == LDAP_SUCCESS ) {
932 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
933 // if( baseDN ) break;
934 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
936 // Process attributes
937 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
938 attribute = ldap_next_attribute( ld, e, ber ) ) {
939 // if( baseDN ) break;
940 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
941 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
942 for( i = 0; vals[i] != NULL; i++ ) {
944 // Strip the 'ldb:' from the front of the value
945 ch = ( char * ) strchr( vals[i], ':' );
947 gchar *bn = g_strdup( ++ch );
950 baseDN = g_list_append( baseDN, g_strdup( bn ) );
954 ldap_value_free( vals );
957 ldap_memfree( attribute );
962 ldap_msgfree( result );
963 ldapServer->retVal = MGU_SUCCESS;
965 else if( rc == LDAP_TIMEOUT ) {
966 ldapServer->retVal = MGU_LDAP_TIMEOUT;
975 * Attempt to connect to the server.
979 * Return: TRUE if connected successfully.
981 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
982 gboolean retVal = FALSE;
984 if( host == NULL ) return retVal;
985 if( port < 1 ) return retVal;
986 if( ( ld = ldap_open( host, port ) ) != NULL ) {
996 * Attempt to connect to the server.
997 * Enter: ldapServer Server to test.
998 * Return: TRUE if connected successfully. Return code set in ldapServer.
1000 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1001 gboolean retVal = FALSE;
1003 ldapServer->retVal = MGU_BAD_ARGS;
1004 if( ldapServer == NULL ) return retVal;
1005 if( ldapServer->hostName == NULL ) return retVal;
1006 if( ldapServer->port < 1 ) return retVal;
1007 ldapServer->retVal = MGU_LDAP_INIT;
1008 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1009 ldapServer->retVal = MGU_SUCCESS;
1018 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
1019 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
1020 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1021 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1024 * Test whether LDAP libraries installed.
1025 * Return: TRUE if library available.
1027 gboolean syldap_test_ldap_lib() {
1031 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1036 // Test for symbols we need
1037 fun = dlsym( handle, "ldap_init" );
1042 dlclose( handle ); handle = NULL; fun = NULL;
1044 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1048 fun = dlsym( handle, "ber_init" );
1053 dlclose( handle ); handle = NULL; fun = NULL;
1055 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1059 fun = dlsym( handle, "res_query" );
1064 dlclose( handle ); handle = NULL; fun = NULL;
1066 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1070 fun = dlsym( handle, "pthread_create" );
1075 dlclose( handle ); handle = NULL; fun = NULL;
1080 #endif /* USE_LDAP */