summaryrefslogtreecommitdiff
path: root/src/syldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/syldap.c')
-rw-r--r--src/syldap.c1127
1 files changed, 1127 insertions, 0 deletions
diff --git a/src/syldap.c b/src/syldap.c
new file mode 100644
index 0000000..6c609ad
--- /dev/null
+++ b/src/syldap.c
@@ -0,0 +1,1127 @@
1/*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001 Match Grun
4 *
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.
9 *
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.
14 *
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.
18 */
19
20/*
21 * Functions necessary to access LDAP servers.
22 */
23
24#ifdef HAVE_CONFIG_H
25# include "config.h"
26#endif
27
28#ifdef USE_LDAP
29
30#include <glib.h>
31#include <gdk/gdk.h>
32#include <gtk/gtkmain.h>
33#include <sys/time.h>
34#include <string.h>
35#define LDAP_DEPRECATED 1
36#include <ldap.h>
37#include <lber.h>
38#include <pthread.h>
39/* #include <dlfcn.h> */
40
41#include "mgutils.h"
42#include "addritem.h"
43#include "addrcache.h"
44#include "syldap.h"
45#include "utils.h"
46
47/*
48* Create new LDAP server interface object.
49*/
50SyldapServer *syldap_create() {
51 SyldapServer *ldapServer;
52
53 debug_print("Creating LDAP server interface object\n");
54
55 ldapServer = g_new0( SyldapServer, 1 );
56 ldapServer->name = NULL;
57 ldapServer->hostName = NULL;
58 ldapServer->port = SYLDAP_DFL_PORT;
59 ldapServer->baseDN = NULL;
60 ldapServer->bindDN = NULL;
61 ldapServer->bindPass = NULL;
62 ldapServer->searchCriteria = NULL;
63 ldapServer->searchValue = NULL;
64 ldapServer->entriesRead = 0;
65 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
66 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
67 ldapServer->newSearch = TRUE;
68 ldapServer->addressCache = addrcache_create();
69 ldapServer->thread = NULL;
70 ldapServer->busyFlag = FALSE;
71 ldapServer->retVal = MGU_SUCCESS;
72 ldapServer->callBack = NULL;
73 ldapServer->accessFlag = FALSE;
74 ldapServer->idleId = 0;
75 return ldapServer;
76}
77
78/*
79* Specify name to be used.
80*/
81void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
82 ldapServer->name = mgu_replace_string( ldapServer->name, value );
83 g_strstrip( ldapServer->name );
84}
85
86/*
87* Specify hostname to be used.
88*/
89void 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 );
93}
94
95/*
96* Specify port to be used.
97*/
98void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
99 addrcache_refresh( ldapServer->addressCache );
100 if( value > 0 ) {
101 ldapServer->port = value;
102 }
103 else {
104 ldapServer->port = SYLDAP_DFL_PORT;
105 }
106}
107
108/*
109* Specify base DN to be used.
110*/
111void 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 );
115}
116
117/*
118* Specify bind DN to be used.
119*/
120void 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 );
124}
125
126/*
127* Specify bind password to be used.
128*/
129void 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 );
133}
134
135/*
136* Specify search criteria to be used.
137*/
138void 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;
143}
144
145/*
146* Specify search value to be searched for.
147*/
148void 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;
153}
154
155/*
156* Specify maximum number of entries to retrieve.
157*/
158void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
159 addrcache_refresh( ldapServer->addressCache );
160 if( value > 0 ) {
161 ldapServer->maxEntries = value;
162 }
163 else {
164 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
165 }
166}
167
168/*
169* Specify timeout value for LDAP operation (in seconds).
170*/
171void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
172 addrcache_refresh( ldapServer->addressCache );
173 if( value > 0 ) {
174 ldapServer->timeOut = value;
175 }
176 else {
177 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
178 }
179}
180
181/*
182* Register a callback function. When called, the function will be passed
183* this object as an argument.
184*/
185void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
186 ldapServer->callBack = func;
187}
188
189void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
190 g_return_if_fail( ldapServer != NULL );
191 ldapServer->accessFlag = value;
192}
193
194/*
195* Refresh internal variables to force a file read.
196*/
197void syldap_force_refresh( SyldapServer *ldapServer ) {
198 addrcache_refresh( ldapServer->addressCache );
199 ldapServer->newSearch = TRUE;
200}
201
202gint syldap_get_status( SyldapServer *ldapServer ) {
203 g_return_val_if_fail( ldapServer != NULL, -1 );
204 return ldapServer->retVal;
205}
206
207ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
208 g_return_val_if_fail( ldapServer != NULL, NULL );
209 return addrcache_get_root_folder( ldapServer->addressCache );
210}
211
212gchar *syldap_get_name( SyldapServer *ldapServer ) {
213 g_return_val_if_fail( ldapServer != NULL, NULL );
214 return ldapServer->name;
215}
216
217gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
218 g_return_val_if_fail( ldapServer != NULL, FALSE );
219 return ldapServer->accessFlag;
220}
221
222/*
223* Free up LDAP server interface object by releasing internal memory.
224*/
225void syldap_free( SyldapServer *ldapServer ) {
226 g_return_if_fail( ldapServer != NULL );
227
228 debug_print("Freeing LDAP server interface object\n");
229
230 ldapServer->callBack = NULL;
231
232 /* Free internal stuff */
233 g_free( ldapServer->name );
234 g_free( ldapServer->hostName );
235 g_free( ldapServer->baseDN );
236 g_free( ldapServer->bindDN );
237 g_free( ldapServer->bindPass );
238 g_free( ldapServer->searchCriteria );
239 g_free( ldapServer->searchValue );
240 g_free( ldapServer->thread );
241
242 ldapServer->port = 0;
243 ldapServer->entriesRead = 0;
244 ldapServer->maxEntries = 0;
245 ldapServer->newSearch = FALSE;
246
247 /* Clear cache */
248 addrcache_clear( ldapServer->addressCache );
249 addrcache_free( ldapServer->addressCache );
250
251 /* Clear pointers */
252 ldapServer->name = NULL;
253 ldapServer->hostName = NULL;
254 ldapServer->baseDN = NULL;
255 ldapServer->bindDN = NULL;
256 ldapServer->bindPass = NULL;
257 ldapServer->searchCriteria = NULL;
258 ldapServer->searchValue = NULL;
259 ldapServer->addressCache = NULL;
260 ldapServer->thread = NULL;
261 ldapServer->busyFlag = FALSE;
262 ldapServer->retVal = MGU_SUCCESS;
263 ldapServer->accessFlag = FALSE;
264
265 /* Now release LDAP object */
266 g_free( ldapServer );
267
268}
269
270/*
271* Display object to specified stream.
272*/
273void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
274 g_return_if_fail( ldapServer != NULL );
275
276 fprintf( stream, "SyldapServer:\n" );
277 fprintf( stream, " name: '%s'\n", ldapServer->name );
278 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
279 fprintf( stream, " port: %d\n", ldapServer->port );
280 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
281 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
282 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
283 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
284 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
285 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
286 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
287 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
288 addrcache_print( ldapServer->addressCache, stream );
289 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
290}
291
292/*
293* Display object to specified stream.
294*/
295void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
296 g_return_if_fail( ldapServer != NULL );
297
298 fprintf( stream, "SyldapServer:\n" );
299 fprintf( stream, " name: '%s'\n", ldapServer->name );
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 );
310}
311
312#if 0
313/*
314* Build an address list entry and append to list of address items. Name is formatted
315* as it appears in the common name (cn) attribute.
316*/
317static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
318 ItemPerson *person;
319 ItemEMail *email;
320 GSList *nodeName = listName;
321
322 while( nodeName ) {
323 GSList *nodeAddress = listAddr;
324 person = addritem_create_item_person();
325 addritem_person_set_common_name( person, nodeName->data );
326 addrcache_id_person( ldapServer->addressCache, person );
327 addrcache_add_person( ldapServer->addressCache, person );
328
329 while( nodeAddress ) {
330 email = addritem_create_item_email();
331 addritem_email_set_address( email, nodeAddress->data );
332 addrcache_id_email( ldapServer->addressCache, email );
333 addrcache_person_add_email( ldapServer->addressCache, person, email );
334 nodeAddress = g_slist_next( nodeAddress );
335 ldapServer->entriesRead++;
336 }
337 nodeName = g_slist_next( nodeName );
338 }
339}
340#endif
341
342/*
343* Build an address list entry and append to list of address items. Name is formatted
344* as "<first-name> <last-name>".
345*/
346static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
347 GSList *nodeFirst = listFirst;
348 GSList *nodeAddress = listAddr;
349 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
350 gint iLen = 0, iLenT = 0;
351 ItemPerson *person;
352 ItemEMail *email;
353
354 /* Find longest first name in list */
355 while( nodeFirst ) {
356 if( firstName == NULL ) {
357 firstName = nodeFirst->data;
358 iLen = strlen( firstName );
359 }
360 else {
361 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
362 firstName = nodeFirst->data;
363 iLen = iLenT;
364 }
365 }
366 nodeFirst = g_slist_next( nodeFirst );
367 }
368
369 /* Format name */
370 if( listLast ) {
371 lastName = listLast->data;
372 }
373
374 if( firstName ) {
375 if( lastName ) {
376 fullName = g_strdup_printf( "%s %s", firstName, lastName );
377 }
378 else {
379 fullName = g_strdup_printf( "%s", firstName );
380 }
381 }
382 else {
383 if( lastName ) {
384 fullName = g_strdup_printf( "%s", lastName );
385 }
386 }
387 if( fullName ) {
388 g_strchug( fullName ); g_strchomp( fullName );
389 }
390
391 if( nodeAddress ) {
392 person = addritem_create_item_person();
393 addritem_person_set_common_name( person, fullName );
394 addritem_person_set_first_name( person, firstName );
395 addritem_person_set_last_name( person, lastName );
396 addrcache_id_person( ldapServer->addressCache, person );
397 addrcache_add_person( ldapServer->addressCache, person );
398 }
399
400 /* Add address item */
401 while( nodeAddress ) {
402 email = addritem_create_item_email();
403 addritem_email_set_address( email, nodeAddress->data );
404 addrcache_id_email( ldapServer->addressCache, email );
405 addrcache_person_add_email( ldapServer->addressCache, person, email );
406 nodeAddress = g_slist_next( nodeAddress );
407 ldapServer->entriesRead++;
408 }
409 g_free( fullName );
410 fullName = firstName = lastName = NULL;
411
412}
413
414/*
415* Add all attribute values to a list.
416*/
417static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
418 GSList *list = NULL;
419 gint i;
420 gchar **vals;
421
422 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
423 for( i = 0; vals[i] != NULL; i++ ) {
424 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
425 list = g_slist_append( list, g_strdup( vals[i] ) );
426 }
427 }
428 ldap_value_free( vals );
429 return list;
430}
431
432/*
433* Add a single attribute value to a list.
434*/
435static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
436 GSList *list = NULL;
437 gchar **vals;
438
439 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
440 if( vals[0] != NULL ) {
441 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
442 list = g_slist_append( list, g_strdup( vals[0] ) );
443 }
444 }
445 ldap_value_free( vals );
446 return list;
447}
448
449/*
450* Free linked lists of character strings.
451*/
452static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
453 mgu_free_list( listName );
454 mgu_free_list( listAddr );
455 mgu_free_list( listID );
456 mgu_free_list( listDN );
457 mgu_free_list( listFirst );
458 mgu_free_list( listLast );
459}
460
461/*
462* Check parameters that are required for a search. This should
463* be called before performing a search.
464* Return: TRUE if search criteria appear OK.
465*/
466gboolean syldap_check_search( SyldapServer *ldapServer ) {
467 g_return_val_if_fail( ldapServer != NULL, FALSE );
468
469 ldapServer->retVal = MGU_LDAP_CRITERIA;
470
471 /* Test search criteria */
472 if( ldapServer->searchCriteria == NULL ) {
473 return FALSE;
474 }
475 if( strlen( ldapServer->searchCriteria ) < 1 ) {
476 return FALSE;
477 }
478
479 if( ldapServer->searchValue == NULL ) {
480 return FALSE;
481 }
482 if( strlen( ldapServer->searchValue ) < 1 ) {
483 return FALSE;
484 }
485
486 ldapServer->retVal = MGU_SUCCESS;
487 return TRUE;
488}
489
490/*
491* Perform the LDAP search, reading LDAP entries into cache.
492* Note that one LDAP entry can have multiple values for many of its
493* attributes. If these attributes are E-Mail addresses; these are
494* broken out into separate address items. For any other attribute,
495* only the first occurrence is read.
496*/
497gint syldap_search( SyldapServer *ldapServer ) {
498 LDAP *ld;
499 LDAPMessage *result, *e;
500 char *attribs[10];
501 char *attribute;
502 gchar *criteria;
503 BerElement *ber;
504 gint rc;
505 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
506 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
507 struct timeval timeout;
508 gboolean entriesFound = FALSE;
509
510 g_return_val_if_fail( ldapServer != NULL, -1 );
511
512 ldapServer->retVal = MGU_SUCCESS;
513 if( ! syldap_check_search( ldapServer ) ) {
514 return ldapServer->retVal;
515 }
516
517 /* Set timeout */
518 timeout.tv_sec = ldapServer->timeOut;
519 timeout.tv_usec = 0L;
520
521 ldapServer->entriesRead = 0;
522 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
523 ldapServer->retVal = MGU_LDAP_INIT;
524 return ldapServer->retVal;
525 }
526
527 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
528
529 /* Bind to the server, if required */
530 if( ldapServer->bindDN ) {
531 if( * ldapServer->bindDN != '\0' ) {
532 /* printf( "binding...\n" ); */
533 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
534 /* printf( "rc=%d\n", rc ); */
535 if( rc != LDAP_SUCCESS ) {
536 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
537 ldap_unbind( ld );
538 ldapServer->retVal = MGU_LDAP_BIND;
539 return ldapServer->retVal;
540 }
541 }
542 }
543
544 /* Define all attributes we are interested in. */
545 attribs[0] = SYLDAP_ATTR_DN;
546 attribs[1] = SYLDAP_ATTR_COMMONNAME;
547 attribs[2] = SYLDAP_ATTR_GIVENNAME;
548 attribs[3] = SYLDAP_ATTR_SURNAME;
549 attribs[4] = SYLDAP_ATTR_EMAIL;
550 attribs[5] = SYLDAP_ATTR_UID;
551 attribs[6] = NULL;
552
553 /* Create LDAP search string and apply search criteria */
554 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
555 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
556 &timeout, 0, &result );
557 g_free( criteria );
558 criteria = NULL;
559 if( rc == LDAP_TIMEOUT ) {
560 ldap_unbind( ld );
561 ldapServer->retVal = MGU_LDAP_TIMEOUT;
562 return ldapServer->retVal;
563 }
564 if( rc != LDAP_SUCCESS ) {
565 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
566 ldap_unbind( ld );
567 ldapServer->retVal = MGU_LDAP_SEARCH;
568 return ldapServer->retVal;
569 }
570
571 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
572
573 /* Clear the cache if we have new entries, otherwise leave untouched. */
574 if( ldap_count_entries( ld, result ) > 0 ) {
575 addrcache_clear( ldapServer->addressCache );
576 }
577
578 /* Process results */
579 ldapServer->entriesRead = 0;
580 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
581 entriesFound = TRUE;
582 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
583 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
584
585 /* Process all attributes */
586 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
587 attribute = ldap_next_attribute( ld, e, ber ) ) {
588 if( g_ascii_strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
589 listName = syldap_add_list_values( ld, e, attribute );
590 }
591 if( g_ascii_strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
592 listAddress = syldap_add_list_values( ld, e, attribute );
593 }
594 if( g_ascii_strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
595 listID = syldap_add_single_value( ld, e, attribute );
596 }
597 if( g_ascii_strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
598 listFirst = syldap_add_list_values( ld, e, attribute );
599 }
600 if( g_ascii_strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
601 listLast = syldap_add_single_value( ld, e, attribute );
602 }
603 if( g_ascii_strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
604 listDN = syldap_add_single_value( ld, e, attribute );
605 }
606
607 /* Free memory used to store attribute */
608 ldap_memfree( attribute );
609 }
610
611 /* Format and add items to cache */
612 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
613
614 /* Free up */
615 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
616 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
617
618 if( ber != NULL ) {
619 ber_free( ber, 0 );
620 }
621 }
622
623 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
624 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
625
626 /* Free up and disconnect */
627 ldap_msgfree( result );
628 ldap_unbind( ld );
629 ldapServer->newSearch = FALSE;
630 if( entriesFound ) {
631 ldapServer->retVal = MGU_SUCCESS;
632 }
633 else {
634 ldapServer->retVal = MGU_LDAP_NOENTRIES;
635 }
636 return ldapServer->retVal;
637}
638
639/* syldap_display_search_results() - updates the ui. this function is called from the
640 * main thread (the thread running the GTK event loop). */
641static gboolean syldap_display_search_results(SyldapServer *ldapServer)
642{
643 /* NOTE: when this function is called the accompanying thread should
644 * already be terminated. */
645 gdk_threads_enter();
646 ldapServer->callBack(ldapServer);
647 gdk_threads_leave();
648 /* FIXME: match should know whether to free this SyldapServer stuff. */
649 g_free(ldapServer->thread);
650 ldapServer->thread = NULL;
651 return FALSE;
652}
653
654/* ============================================================================================ */
655/*
656* Read data into list. Main entry point
657* Return: TRUE if file read successfully.
658*/
659/* ============================================================================================ */
660gint syldap_read_data( SyldapServer *ldapServer ) {
661 g_return_val_if_fail( ldapServer != NULL, -1 );
662
663 ldapServer->accessFlag = FALSE;
664 pthread_detach( pthread_self() );
665 if( ldapServer->newSearch ) {
666 /* Read data into the list */
667 syldap_search( ldapServer );
668
669 /* Mark cache */
670 ldapServer->addressCache->modified = FALSE;
671 ldapServer->addressCache->dataRead = TRUE;
672 ldapServer->accessFlag = FALSE;
673 }
674
675 /* Callback */
676 ldapServer->busyFlag = FALSE;
677 if( ldapServer->callBack ) {
678 /* make the ui thread update the search results */
679 ldapServer->idleId = g_idle_add((GSourceFunc)syldap_display_search_results, ldapServer);
680 }
681
682 return ldapServer->retVal;
683}
684
685/* ============================================================================================ */
686/*
687* Cancel read with thread.
688*/
689/* ============================================================================================ */
690void syldap_cancel_read( SyldapServer *ldapServer ) {
691 g_return_if_fail( ldapServer != NULL );
692
693 /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */
694 if( ldapServer->thread ) {
695 /* printf( "thread cancelled\n" ); */
696 pthread_cancel( *ldapServer->thread );
697 }
698 g_free(ldapServer->thread);
699 ldapServer->thread = NULL;
700 ldapServer->busyFlag = FALSE;
701}
702
703/* ============================================================================================ */
704/*
705* Read data into list using a background thread.
706* Return: TRUE if file read successfully. Callback function will be
707* notified when search is complete.
708*/
709/* ============================================================================================ */
710gint syldap_read_data_th( SyldapServer *ldapServer ) {
711 g_return_val_if_fail( ldapServer != NULL, -1 );
712
713 ldapServer->busyFlag = FALSE;
714 syldap_check_search( ldapServer );
715 if( ldapServer->retVal == MGU_SUCCESS ) {
716 /* debug_print("Staring LDAP read thread\n"); */
717
718 ldapServer->busyFlag = TRUE;
719 ldapServer->thread = g_new0(pthread_t, 1);
720 pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer );
721 }
722 return ldapServer->retVal;
723}
724
725/*
726* Return link list of persons.
727*/
728GList *syldap_get_list_person( SyldapServer *ldapServer ) {
729 g_return_val_if_fail( ldapServer != NULL, NULL );
730 return addrcache_get_list_person( ldapServer->addressCache );
731}
732
733/*
734* Return link list of folders. This is always NULL since there are
735* no folders in GnomeCard.
736* Return: NULL.
737*/
738GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
739 g_return_val_if_fail( ldapServer != NULL, NULL );
740 return NULL;
741}
742
743#define SYLDAP_TEST_FILTER "(objectclass=*)"
744#define SYLDAP_SEARCHBASE_V2 "cn=config"
745#define SYLDAP_SEARCHBASE_V3 ""
746#define SYLDAP_V2_TEST_ATTR "database"
747#define SYLDAP_V3_TEST_ATTR "namingcontexts"
748
749/*
750* Attempt to discover the base DN for the server.
751* Enter:
752* host Host name
753* port Port number
754* bindDN Bind DN (optional).
755* bindPW Bind PW (optional).
756* tov Timeout value (seconds), or 0 for none, default 30 secs.
757* Return: List of Base DN's, or NULL if could not read. Base DN should
758* be g_free() when done.
759*/
760GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
761 GList *baseDN = NULL;
762 LDAP *ld;
763 gint rc, i;
764 LDAPMessage *result, *e;
765 gchar *attribs[10];
766 BerElement *ber;
767 gchar *attribute;
768 gchar **vals;
769 struct timeval timeout;
770
771 if( host == NULL ) return baseDN;
772 if( port < 1 ) return baseDN;
773
774 /* Set timeout */
775 timeout.tv_usec = 0L;
776 if( tov > 0 ) {
777 timeout.tv_sec = tov;
778 }
779 else {
780 timeout.tv_sec = 30L;
781 }
782
783 /* Connect to server. */
784 if( ( ld = ldap_init( host, port ) ) == NULL ) {
785 return baseDN;
786 }
787
788 /* Bind to the server, if required */
789 if( bindDN ) {
790 if( *bindDN != '\0' ) {
791 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
792 if( rc != LDAP_SUCCESS ) {
793 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
794 ldap_unbind( ld );
795 return baseDN;
796 }
797 }
798 }
799
800 /* Test for LDAP version 3 */
801 attribs[0] = SYLDAP_V3_TEST_ATTR;
802 attribs[1] = NULL;
803 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
804 0, NULL, NULL, &timeout, 0, &result );
805 if( rc == LDAP_SUCCESS ) {
806 /* Process entries */
807 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
808 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
809
810 /* Process attributes */
811 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
812 attribute = ldap_next_attribute( ld, e, ber ) ) {
813 if( g_ascii_strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
814 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
815 for( i = 0; vals[i] != NULL; i++ ) {
816 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
817 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
818 }
819 }
820 ldap_value_free( vals );
821 }
822 ldap_memfree( attribute );
823 }
824 if( ber != NULL ) {
825 ber_free( ber, 0 );
826 }
827 }
828 ldap_msgfree( result );
829 }
830 else {
831 }
832
833 if( baseDN == NULL ) {
834 /* Test for LDAP version 2 */
835 attribs[0] = NULL;
836 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
837 0, NULL, NULL, &timeout, 0, &result );
838 if( rc == LDAP_SUCCESS ) {
839 /* Process entries */
840 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
841 /* if( baseDN ) break; */
842 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
843
844 /* Process attributes */
845 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
846 attribute = ldap_next_attribute( ld, e, ber ) ) {
847 /* if( baseDN ) break; */
848 if( g_ascii_strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
849 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
850 for( i = 0; vals[i] != NULL; i++ ) {
851 char *ch;
852 /* Strip the 'ldb:' from the front of the value */
853 ch = ( char * ) strchr( vals[i], ':' );
854 if( ch ) {
855 gchar *bn = g_strdup( ++ch );
856 g_strchomp( bn );
857 g_strchug( bn );
858 baseDN = g_list_append( baseDN, g_strdup( bn ) );
859 }
860 }
861 }
862 ldap_value_free( vals );
863 }
864 ldap_memfree( attribute );
865 }
866 if( ber != NULL ) {
867 ber_free( ber, 0 );
868 }
869 }
870 ldap_msgfree( result );
871 }
872 }
873 ldap_unbind( ld );
874 return baseDN;
875}
876
877/*
878* Attempt to discover the base DN for the server.
879* Enter: ldapServer Server to test.
880* Return: List of Base DN's, or NULL if could not read. Base DN should
881* be g_free() when done. Return code set in ldapServer.
882*/
883GList *syldap_read_basedn( SyldapServer *ldapServer ) {
884 GList *baseDN = NULL;
885 LDAP *ld;
886 gint rc, i;
887 LDAPMessage *result, *e;
888 gchar *attribs[10];
889 BerElement *ber;
890 gchar *attribute;
891 gchar **vals;
892 struct timeval timeout;
893
894 if( ldapServer == NULL ) return baseDN;
895 ldapServer->retVal = MGU_BAD_ARGS;
896 if( ldapServer->hostName == NULL ) return baseDN;
897 if( ldapServer->port < 1 ) return baseDN;
898
899 /* Set timeout */
900 timeout.tv_usec = 0L;
901 if( ldapServer->timeOut > 0 ) {
902 timeout.tv_sec = ldapServer->timeOut;
903 }
904 else {
905 timeout.tv_sec = 30L;
906 }
907
908 /* Connect to server. */
909 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
910 ldapServer->retVal = MGU_LDAP_INIT;
911 return baseDN;
912 }
913
914 /* Bind to the server, if required */
915 if( ldapServer->bindDN ) {
916 if( *ldapServer->bindDN != '\0' ) {
917 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
918 if( rc != LDAP_SUCCESS ) {
919 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
920 ldap_unbind( ld );
921 ldapServer->retVal = MGU_LDAP_BIND;
922 return baseDN;
923 }
924 }
925 }
926
927 ldapServer->retVal = MGU_LDAP_SEARCH;
928
929 /* Test for LDAP version 3 */
930 attribs[0] = SYLDAP_V3_TEST_ATTR;
931 attribs[1] = NULL;
932 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
933 0, NULL, NULL, &timeout, 0, &result );
934 if( rc == LDAP_SUCCESS ) {
935 /* Process entries */
936 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
937 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
938
939 /* Process attributes */
940 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
941 attribute = ldap_next_attribute( ld, e, ber ) ) {
942 if( g_ascii_strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
943 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
944 for( i = 0; vals[i] != NULL; i++ ) {
945 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
946 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
947 }
948 }
949 ldap_value_free( vals );
950 }
951 ldap_memfree( attribute );
952 }
953 if( ber != NULL ) {
954 ber_free( ber, 0 );
955 }
956 }
957 ldap_msgfree( result );
958 ldapServer->retVal = MGU_SUCCESS;
959 }
960 else if( rc == LDAP_TIMEOUT ) {
961 ldapServer->retVal = MGU_LDAP_TIMEOUT;
962 }
963
964 if( baseDN == NULL ) {
965 /* Test for LDAP version 2 */
966 attribs[0] = NULL;
967 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
968 0, NULL, NULL, &timeout, 0, &result );
969 if( rc == LDAP_SUCCESS ) {
970 /* Process entries */
971 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
972 /* if( baseDN ) break; */
973 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
974
975 /* Process attributes */
976 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
977 attribute = ldap_next_attribute( ld, e, ber ) ) {
978 /* if( baseDN ) break; */
979 if( g_ascii_strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
980 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
981 for( i = 0; vals[i] != NULL; i++ ) {
982 char *ch;
983 /* Strip the 'ldb:' from the front of the value */
984 ch = ( char * ) strchr( vals[i], ':' );
985 if( ch ) {
986 gchar *bn = g_strdup( ++ch );
987 g_strchomp( bn );
988 g_strchug( bn );
989 baseDN = g_list_append( baseDN, g_strdup( bn ) );
990 }
991 }
992 }
993 ldap_value_free( vals );
994 }
995 ldap_memfree( attribute );
996 }
997 if( ber != NULL ) {
998 ber_free( ber, 0 );
999 }
1000 }
1001 ldap_msgfree( result );
1002 ldapServer->retVal = MGU_SUCCESS;
1003 }
1004 else if( rc == LDAP_TIMEOUT ) {
1005 ldapServer->retVal = MGU_LDAP_TIMEOUT;
1006 }
1007 }
1008 ldap_unbind( ld );
1009
1010 return baseDN;
1011}
1012
1013/*
1014* Attempt to connect to the server.
1015* Enter:
1016* host Host name
1017* port Port number
1018* Return: TRUE if connected successfully.
1019*/
1020gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1021 gboolean retVal = FALSE;
1022 LDAP *ld;
1023
1024 if( host == NULL ) return retVal;
1025 if( port < 1 ) return retVal;
1026 if( ( ld = ldap_open( host, port ) ) != NULL ) {
1027 retVal = TRUE;
1028 }
1029 if( ld != NULL ) {
1030 ldap_unbind( ld );
1031 }
1032 return retVal;
1033}
1034
1035/*
1036* Attempt to connect to the server.
1037* Enter: ldapServer Server to test.
1038* Return: TRUE if connected successfully. Return code set in ldapServer.
1039*/
1040gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1041 gboolean retVal = FALSE;
1042 LDAP *ld;
1043
1044 if( ldapServer == NULL ) return retVal;
1045 ldapServer->retVal = MGU_BAD_ARGS;
1046 if( ldapServer->hostName == NULL ) return retVal;
1047 if( ldapServer->port < 1 ) return retVal;
1048 ldapServer->retVal = MGU_LDAP_INIT;
1049 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1050 ldapServer->retVal = MGU_SUCCESS;
1051 retVal = TRUE;
1052 }
1053 if( ld != NULL ) {
1054 ldap_unbind( ld );
1055 }
1056 return retVal;
1057}
1058
1059#define LDAP_LINK_LIB_NAME_1 "libldap.so"
1060#define LDAP_LINK_LIB_NAME_2 "liblber.so"
1061#define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1062#define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1063
1064/*
1065* Test whether LDAP libraries installed.
1066* Return: TRUE if library available.
1067*/
1068#if 0
1069gboolean syldap_test_ldap_lib() {
1070 void *handle, *fun;
1071
1072 /* Get library */
1073 handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1074 if( ! handle ) {
1075 return FALSE;
1076 }
1077
1078 /* Test for symbols we need */
1079 fun = dlsym( handle, "ldap_init" );
1080 if( ! fun ) {
1081 dlclose( handle );
1082 return FALSE;
1083 }
1084 dlclose( handle ); handle = NULL; fun = NULL;
1085
1086 handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1087 if( ! handle ) {
1088 return FALSE;
1089 }
1090 fun = dlsym( handle, "ber_init" );
1091 if( ! fun ) {
1092 dlclose( handle );
1093 return FALSE;
1094 }
1095 dlclose( handle ); handle = NULL; fun = NULL;
1096
1097 handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1098 if( ! handle ) {
1099 return FALSE;
1100 }
1101 fun = dlsym( handle, "res_query" );
1102 if( ! fun ) {
1103 dlclose( handle );
1104 return FALSE;
1105 }
1106 dlclose( handle ); handle = NULL; fun = NULL;
1107
1108 handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1109 if( ! handle ) {
1110 return FALSE;
1111 }
1112 fun = dlsym( handle, "pthread_create" );
1113 if( ! fun ) {
1114 dlclose( handle );
1115 return FALSE;
1116 }
1117 dlclose( handle ); handle = NULL; fun = NULL;
1118
1119 return TRUE;
1120}
1121#endif /* 0 */
1122
1123#endif /* USE_LDAP */
1124
1125/*
1126* End of Source.
1127*/