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.
41 * Specify name to be used.
43 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
44 if( ldapServer->name ) g_free( ldapServer->name );
45 if( value ) ldapServer->name = g_strdup( value );
46 g_strstrip( ldapServer->name );
50 * Specify hostname to be used.
52 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
53 mgu_refresh_cache( ldapServer->addressCache );
55 if( ldapServer->hostName ) g_free( ldapServer->hostName );
56 if( value ) ldapServer->hostName = g_strdup( value );
57 g_strstrip( ldapServer->hostName );
61 * Specify port to be used.
63 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
64 mgu_refresh_cache( ldapServer->addressCache );
67 ldapServer->port = value;
70 ldapServer->port = SYLDAP_DFL_PORT;
75 * Specify base DN to be used.
77 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
78 mgu_refresh_cache( ldapServer->addressCache );
80 if( ldapServer->baseDN ) g_free( ldapServer->baseDN );
81 if( value ) ldapServer->baseDN = g_strdup( value );
82 g_strstrip( ldapServer->baseDN );
86 * Specify bind DN to be used.
88 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
89 mgu_refresh_cache( ldapServer->addressCache );
91 if( ldapServer->bindDN ) g_free( ldapServer->bindDN );
92 if( value ) ldapServer->bindDN = g_strdup( value );
93 g_strstrip( ldapServer->bindDN );
97 * Specify bind password to be used.
99 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
100 mgu_refresh_cache( ldapServer->addressCache );
102 if( ldapServer->bindPass ) g_free( ldapServer->bindPass );
103 if( value ) ldapServer->bindPass = g_strdup( value );
104 g_strstrip( ldapServer->bindPass );
108 * Specify search criteria to be used.
110 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
111 mgu_refresh_cache( ldapServer->addressCache );
113 if( ldapServer->searchCriteria ) g_free( ldapServer->searchCriteria );
114 if( value ) ldapServer->searchCriteria = g_strdup( value );
115 g_strstrip( ldapServer->searchCriteria );
116 ldapServer->newSearch = TRUE;
120 * Specify search value to be searched for.
122 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
123 mgu_refresh_cache( ldapServer->addressCache );
125 if( ldapServer->searchValue ) g_free( ldapServer->searchValue );
126 if( value ) ldapServer->searchValue = g_strdup( value );
127 g_strstrip( ldapServer->searchValue );
128 ldapServer->newSearch = TRUE;
132 * Specify maximum number of entries to retrieve.
134 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
135 mgu_refresh_cache( ldapServer->addressCache );
137 ldapServer->maxEntries = value;
140 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
145 * Specify timeout value for LDAP operation (in seconds).
147 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
148 mgu_refresh_cache( ldapServer->addressCache );
150 ldapServer->timeOut = value;
153 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
158 * Register a callback function. When called, the function will be passed
159 * this object as an argument.
161 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
162 ldapServer->callBack = func;
166 * Create new LDAP server interface object.
168 SyldapServer *syldap_create() {
169 SyldapServer *ldapServer;
170 ldapServer = g_new( SyldapServer, 1 );
171 ldapServer->name = NULL;
172 ldapServer->hostName = NULL;
173 ldapServer->port = SYLDAP_DFL_PORT;
174 ldapServer->baseDN = NULL;
175 ldapServer->bindDN = NULL;
176 ldapServer->bindPass = NULL;
177 ldapServer->searchCriteria = NULL;
178 ldapServer->searchValue = NULL;
179 ldapServer->entriesRead = 0;
180 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
181 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
182 ldapServer->newSearch = TRUE;
183 ldapServer->addressCache = mgu_create_cache();
184 ldapServer->thread = NULL;
185 ldapServer->busyFlag = FALSE;
186 ldapServer->retVal = MGU_SUCCESS;
187 ldapServer->callBack = NULL;
192 * Refresh internal variables to force a file read.
194 void syldap_force_refresh( SyldapServer *ldapServer ) {
195 mgu_refresh_cache( ldapServer->addressCache );
196 ldapServer->newSearch = TRUE;
200 * Free up LDAP server interface object by releasing internal memory.
202 void syldap_free( SyldapServer *ldapServer ) {
203 g_return_if_fail( ldapServer != NULL );
205 ldapServer->callBack = NULL;
206 // fprintf( stdout, "freeing... SyldapServer\n" );
208 /* Free internal stuff */
209 g_free( ldapServer->name );
210 g_free( ldapServer->hostName );
211 g_free( ldapServer->baseDN );
212 g_free( ldapServer->bindDN );
213 g_free( ldapServer->bindPass );
214 g_free( ldapServer->searchCriteria );
215 g_free( ldapServer->searchValue );
217 ldapServer->port = 0;
218 ldapServer->entriesRead = 0;
219 ldapServer->maxEntries = 0;
220 ldapServer->newSearch = FALSE;
223 mgu_clear_cache( ldapServer->addressCache );
224 mgu_free_cache( ldapServer->addressCache );
227 ldapServer->name = NULL;
228 ldapServer->hostName = NULL;
229 ldapServer->baseDN = NULL;
230 ldapServer->bindDN = NULL;
231 ldapServer->bindPass = NULL;
232 ldapServer->searchCriteria = NULL;
233 ldapServer->searchValue = NULL;
234 ldapServer->addressCache = NULL;
235 ldapServer->thread = NULL;
236 ldapServer->busyFlag = FALSE;
237 ldapServer->retVal = MGU_SUCCESS;
239 /* Now release file object */
240 g_free( ldapServer );
242 // fprintf( stdout, "freeing... SyldapServer done\n" );
247 * Display object to specified stream.
249 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
251 g_return_if_fail( ldapServer != NULL );
252 fprintf( stream, "SyldapServer:\n" );
253 fprintf( stream, " name: '%s'\n", ldapServer->name );
254 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
255 fprintf( stream, " port: %d\n", ldapServer->port );
256 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
257 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
258 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
259 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
260 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
261 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
262 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
263 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
264 mgu_print_cache( ldapServer->addressCache, stream );
268 * Display object to specified stream.
270 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
272 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 );
288 * Build an address list entry and append to list of address items. Name is formatted
289 * as it appears in the common name (cn) attribute.
291 void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
292 AddressItem *addrItem = NULL;
293 GSList *nodeName = listName;
295 GSList *nodeAddress = listAddr;
296 while( nodeAddress ) {
297 addrItem = mgu_create_address();
298 addrItem->name = g_strdup( nodeName->data );
299 addrItem->address = g_strdup( nodeAddress->data );
300 addrItem->remarks = g_strdup( "" );
301 mgu_add_cache( ldapServer->addressCache, addrItem );
302 nodeAddress = g_slist_next( nodeAddress );
303 ldapServer->entriesRead++;
305 nodeName = g_slist_next( nodeName );
311 * Build an address list entry and append to list of address items. Name is formatted
312 * as "<first-name> <last-name>".
314 void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
315 AddressItem *addrItem = NULL;
316 GSList *nodeFirst = listFirst;
317 GSList *nodeAddress = listAddr;
318 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
319 gint iLen = 0, iLenT = 0;
321 // Find longest first name in list
323 if( firstName == NULL ) {
324 firstName = nodeFirst->data;
325 iLen = strlen( firstName );
328 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
329 firstName = nodeFirst->data;
333 nodeFirst = g_slist_next( nodeFirst );
338 lastName = listLast->data;
343 fullName = g_strdup_printf( "%s %s", firstName, lastName );
346 fullName = g_strdup_printf( "%s", firstName );
351 fullName = g_strdup_printf( "%s", lastName );
355 g_strchug( fullName ); g_strchomp( fullName );
359 while( nodeAddress ) {
360 addrItem = mgu_create_address();
362 addrItem->name = g_strdup( fullName );
365 addrItem->name = g_strdup( "" );
367 addrItem->address = g_strdup( nodeAddress->data );
368 addrItem->remarks = g_strdup( "" );
369 mgu_add_cache( ldapServer->addressCache, addrItem );
371 nodeAddress = g_slist_next( nodeAddress );
372 ldapServer->entriesRead++;
375 fullName = firstName = lastName = NULL;
380 * Add all attribute values to a list.
382 GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
386 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
387 for( i = 0; vals[i] != NULL; i++ ) {
388 // printf( "lv\t%s: %s\n", attr, vals[i] );
389 list = g_slist_append( list, g_strdup( vals[i] ) );
392 ldap_value_free( vals );
397 * Add a single attribute value to a list.
399 GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
402 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
403 if( vals[0] != NULL ) {
404 // printf( "sv\t%s: %s\n", attr, vals[0] );
405 list = g_slist_append( list, g_strdup( vals[0] ) );
408 ldap_value_free( vals );
413 * Free linked lists of character strings.
415 void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
416 mgu_free_list( listName );
417 mgu_free_list( listAddr );
418 mgu_free_list( listID );
419 mgu_free_list( listDN );
420 mgu_free_list( listFirst );
421 mgu_free_list( listLast );
425 * Check parameters that are required for a search. This should
426 * be called before performing a search.
427 * Return: TRUE if search criteria appear OK.
429 gboolean syldap_check_search( SyldapServer *ldapServer ) {
430 g_return_if_fail( ldapServer != NULL );
431 ldapServer->retVal = MGU_LDAP_CRITERIA;
433 // Test search criteria
434 if( ldapServer->searchCriteria == NULL ) {
437 if( strlen( ldapServer->searchCriteria ) < 1 ) {
441 if( ldapServer->searchValue == NULL ) {
444 if( strlen( ldapServer->searchValue ) < 1 ) {
448 ldapServer->retVal = MGU_SUCCESS;
453 * Perform the LDAP search, reading LDAP entries into cache.
454 * Note that one LDAP entry can have multiple values for many of its
455 * attributes. If these attributes are E-Mail addresses; these are
456 * broken out into separate address items. For any other attribute,
457 * only the first occurrence is read.
459 gint syldap_search( SyldapServer *ldapServer ) {
461 LDAPMessage *result, *e;
467 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
468 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
469 struct timeval timeout;
470 gboolean entriesFound = FALSE;
472 g_return_if_fail( ldapServer != NULL );
474 ldapServer->retVal = MGU_SUCCESS;
475 if( ! syldap_check_search( ldapServer ) ) {
476 return ldapServer->retVal;
480 timeout.tv_sec = ldapServer->timeOut;
481 timeout.tv_usec = 0L;
483 ldapServer->entriesRead = 0;
484 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
485 ldapServer->retVal = MGU_LDAP_INIT;
486 return ldapServer->retVal;
489 // printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port );
491 // Bind to the server, if required
492 if( ldapServer->bindDN ) {
493 if( * ldapServer->bindDN != '\0' ) {
494 // printf( "binding...\n" );
495 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
496 // printf( "rc=%d\n", rc );
497 if( rc != LDAP_SUCCESS ) {
498 // printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
500 ldapServer->retVal = MGU_LDAP_BIND;
501 return ldapServer->retVal;
506 // Define all attributes we are interested in.
507 attribs[0] = SYLDAP_ATTR_DN;
508 attribs[1] = SYLDAP_ATTR_COMMONNAME;
509 attribs[2] = SYLDAP_ATTR_GIVENNAME;
510 attribs[3] = SYLDAP_ATTR_SURNAME;
511 attribs[4] = SYLDAP_ATTR_EMAIL;
512 attribs[5] = SYLDAP_ATTR_UID;
515 // Create LDAP search string and apply search criteria
516 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
517 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
518 &timeout, 0, &result );
521 if( rc == LDAP_TIMEOUT ) {
523 ldapServer->retVal = MGU_LDAP_TIMEOUT;
524 return ldapServer->retVal;
526 if( rc != LDAP_SUCCESS ) {
527 // printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
529 ldapServer->retVal = MGU_LDAP_SEARCH;
530 return ldapServer->retVal;
533 // printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
535 // Clear the cache if we have new entries, otherwise leave untouched.
536 if( ldap_count_entries( ld, result ) > 0 ) {
537 mgu_clear_cache( ldapServer->addressCache );
541 ldapServer->entriesRead = 0;
542 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
544 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
545 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
547 // Process all attributes
548 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
549 attribute = ldap_next_attribute( ld, e, ber ) ) {
550 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
551 listName = syldap_add_list_values( ld, e, attribute );
553 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
554 listAddress = syldap_add_list_values( ld, e, attribute );
556 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
557 listID = syldap_add_single_value( ld, e, attribute );
559 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
560 listFirst = syldap_add_list_values( ld, e, attribute );
562 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
563 listLast = syldap_add_single_value( ld, e, attribute );
565 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
566 listDN = syldap_add_single_value( ld, e, attribute );
570 // Free memory used to store attribute
571 ldap_memfree( attribute );
573 // Format and add items to cache
574 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
577 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
578 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
585 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
586 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
588 // Free up and disconnect
589 ldap_msgfree( result );
591 ldapServer->newSearch = FALSE;
593 ldapServer->retVal = MGU_SUCCESS;
596 ldapServer->retVal = MGU_LDAP_NOENTRIES;
598 return ldapServer->retVal;
601 // ============================================================================================
603 * Read data into list. Main entry point
604 * Return: TRUE if file read successfully.
606 // ============================================================================================
607 gint syldap_read_data( SyldapServer *ldapServer ) {
608 g_return_if_fail( ldapServer != NULL );
610 pthread_detach( pthread_self() );
611 if( ldapServer->newSearch ) {
612 // Read data into the list
613 syldap_search( ldapServer );
616 ldapServer->addressCache->modified = FALSE;
617 ldapServer->addressCache->dataRead = TRUE;
621 ldapServer->busyFlag = FALSE;
622 if( ldapServer->callBack ) {
624 ( ldapServer->callBack )( ldapServer );
626 ldapServer->thread = NULL;
627 pthread_exit( NULL );
628 return ldapServer->retVal;
631 // ============================================================================================
633 * Cancel read with thread.
635 // ============================================================================================
636 void syldap_cancel_read( SyldapServer *ldapServer ) {
637 g_return_if_fail( ldapServer != NULL );
638 if( ldapServer->thread ) {
639 printf( "thread cancelled\n" );
640 pthread_cancel( *ldapServer->thread );
642 ldapServer->thread = NULL;
643 ldapServer->busyFlag = FALSE;
646 // ============================================================================================
648 * Read data into list using a background thread.
649 * Return: TRUE if file read successfully. Callback function will be
650 * notified when search is complete.
652 // ============================================================================================
653 gint syldap_read_data_th( SyldapServer *ldapServer ) {
655 g_return_if_fail( ldapServer != NULL );
657 ldapServer->busyFlag = FALSE;
658 syldap_check_search( ldapServer );
659 if( ldapServer->retVal == MGU_SUCCESS ) {
660 ldapServer->busyFlag = TRUE;
661 ldapServer->thread = &thread;
662 pthread_create( ldapServer->thread, NULL, (void *) &syldap_read_data, (void *) ldapServer );
664 return ldapServer->retVal;
668 * Return link list of address items.
669 * Return: TRUE if file read successfully.
671 GList *syldap_get_address_list( const SyldapServer *ldapServer ) {
672 g_return_if_fail( ldapServer != NULL );
673 return ldapServer->addressCache->addressList;
676 #define SYLDAP_TEST_FILTER "(objectclass=*)"
677 #define SYLDAP_SEARCHBASE_V2 "cn=config"
678 #define SYLDAP_SEARCHBASE_V3 ""
679 #define SYLDAP_V2_TEST_ATTR "database"
680 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
683 * Attempt to discover the base DN for the server.
687 * bindDN Bind DN (optional).
688 * bindPW Bind PW (optional).
689 * tov Timeout value (seconds), or 0 for none, default 30 secs.
690 * Return: List of Base DN's, or NULL if could not read. Base DN should
691 * be g_free() when done.
693 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
694 GList *baseDN = NULL;
697 LDAPMessage *result, *e;
702 struct timeval timeout;
704 if( host == NULL ) return baseDN;
705 if( port < 1 ) return baseDN;
708 timeout.tv_usec = 0L;
710 timeout.tv_sec = tov;
713 timeout.tv_sec = 30L;
716 // Connect to server.
717 if( ( ld = ldap_init( host, port ) ) == NULL ) {
721 // Bind to the server, if required
723 if( *bindDN != '\0' ) {
724 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
725 if( rc != LDAP_SUCCESS ) {
726 // printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
733 // Test for LDAP version 3
734 attribs[0] = SYLDAP_V3_TEST_ATTR;
736 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
737 0, NULL, NULL, &timeout, 0, &result );
738 if( rc == LDAP_SUCCESS ) {
740 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
741 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
743 // Process attributes
744 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
745 attribute = ldap_next_attribute( ld, e, ber ) ) {
746 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
747 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
748 for( i = 0; vals[i] != NULL; i++ ) {
749 // printf( "\t%s: %s\n", attribute, vals[i] );
750 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
753 ldap_value_free( vals );
756 ldap_memfree( attribute );
761 ldap_msgfree( result );
766 if( baseDN == NULL ) {
767 // Test for LDAP version 2
769 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
770 0, NULL, NULL, &timeout, 0, &result );
771 if( rc == LDAP_SUCCESS ) {
773 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
774 // if( baseDN ) break;
775 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
777 // Process attributes
778 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
779 attribute = ldap_next_attribute( ld, e, ber ) ) {
780 // if( baseDN ) break;
781 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
782 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
783 for( i = 0; vals[i] != NULL; i++ ) {
785 // Strip the 'ldb:' from the front of the value
786 ch = ( char * ) strchr( vals[i], ':' );
788 gchar *bn = g_strdup( ++ch );
791 baseDN = g_list_append( baseDN, g_strdup( bn ) );
795 ldap_value_free( vals );
798 ldap_memfree( attribute );
803 ldap_msgfree( result );
811 * Attempt to discover the base DN for the server.
812 * Enter: ldapServer Server to test.
813 * Return: List of Base DN's, or NULL if could not read. Base DN should
814 * be g_free() when done. Return code set in ldapServer.
816 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
817 GList *baseDN = NULL;
820 LDAPMessage *result, *e;
825 struct timeval timeout;
827 ldapServer->retVal = MGU_BAD_ARGS;
828 if( ldapServer == NULL ) return baseDN;
829 if( ldapServer->hostName == NULL ) return baseDN;
830 if( ldapServer->port < 1 ) return baseDN;
833 timeout.tv_usec = 0L;
834 if( ldapServer->timeOut > 0 ) {
835 timeout.tv_sec = ldapServer->timeOut;
838 timeout.tv_sec = 30L;
841 // Connect to server.
842 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
843 ldapServer->retVal = MGU_LDAP_INIT;
847 // Bind to the server, if required
848 if( ldapServer->bindDN ) {
849 if( *ldapServer->bindDN != '\0' ) {
850 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
851 if( rc != LDAP_SUCCESS ) {
852 //printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
854 ldapServer->retVal = MGU_LDAP_BIND;
860 ldapServer->retVal = MGU_LDAP_SEARCH;
862 // Test for LDAP version 3
863 attribs[0] = SYLDAP_V3_TEST_ATTR;
865 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
866 0, NULL, NULL, &timeout, 0, &result );
867 if( rc == LDAP_SUCCESS ) {
869 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
870 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
872 // Process attributes
873 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
874 attribute = ldap_next_attribute( ld, e, ber ) ) {
875 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
876 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
877 for( i = 0; vals[i] != NULL; i++ ) {
878 // printf( "\t%s: %s\n", attribute, vals[i] );
879 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
882 ldap_value_free( vals );
885 ldap_memfree( attribute );
890 ldap_msgfree( result );
891 ldapServer->retVal = MGU_SUCCESS;
893 else if( rc == LDAP_TIMEOUT ) {
894 ldapServer->retVal = MGU_LDAP_TIMEOUT;
897 if( baseDN == NULL ) {
898 // Test for LDAP version 2
900 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
901 0, NULL, NULL, &timeout, 0, &result );
902 if( rc == LDAP_SUCCESS ) {
904 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
905 // if( baseDN ) break;
906 // printf( "DN: %s\n", ldap_get_dn( ld, e ) );
908 // Process attributes
909 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
910 attribute = ldap_next_attribute( ld, e, ber ) ) {
911 // if( baseDN ) break;
912 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
913 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
914 for( i = 0; vals[i] != NULL; i++ ) {
916 // Strip the 'ldb:' from the front of the value
917 ch = ( char * ) strchr( vals[i], ':' );
919 gchar *bn = g_strdup( ++ch );
922 baseDN = g_list_append( baseDN, g_strdup( bn ) );
926 ldap_value_free( vals );
929 ldap_memfree( attribute );
934 ldap_msgfree( result );
935 ldapServer->retVal = MGU_SUCCESS;
937 else if( rc == LDAP_TIMEOUT ) {
938 ldapServer->retVal = MGU_LDAP_TIMEOUT;
947 * Attempt to connect to the server.
951 * Return: TRUE if connected successfully.
953 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
954 gboolean retVal = FALSE;
956 if( host == NULL ) return retVal;
957 if( port < 1 ) return retVal;
958 if( ( ld = ldap_open( host, port ) ) != NULL ) {
968 * Attempt to connect to the server.
969 * Enter: ldapServer Server to test.
970 * Return: TRUE if connected successfully. Return code set in ldapServer.
972 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
973 gboolean retVal = FALSE;
975 ldapServer->retVal = MGU_BAD_ARGS;
976 if( ldapServer == NULL ) return retVal;
977 if( ldapServer->hostName == NULL ) return retVal;
978 if( ldapServer->port < 1 ) return retVal;
979 ldapServer->retVal = MGU_LDAP_INIT;
980 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
981 ldapServer->retVal = MGU_SUCCESS;
990 #define LDAP_LINK_LIB_NAME_1 "libldap.so"
991 #define LDAP_LINK_LIB_NAME_2 "liblber.so"
992 #define LDAP_LINK_LIB_NAME_3 "libresolv.so"
993 #define LDAP_LINK_LIB_NAME_4 "libpthread.so"
996 * Test whether LDAP libraries installed.
997 * Return: TRUE if library available.
999 gboolean syldap_test_ldap_lib() {
1003 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1008 // Test for symbols we need
1009 fun = dlsym( handle, "ldap_init" );
1014 dlclose( handle ); handle = NULL; fun = NULL;
1016 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1020 fun = dlsym( handle, "ber_init" );
1025 dlclose( handle ); handle = NULL; fun = NULL;
1027 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1031 fun = dlsym( handle, "res_query" );
1036 dlclose( handle ); handle = NULL; fun = NULL;
1038 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1042 fun = dlsym( handle, "pthread_create" );
1047 dlclose( handle ); handle = NULL; fun = NULL;
1052 #endif /* USE_LDAP */