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 */