Statistics
| Revision:

root / src / syldap.c @ 1

History | View | Annotate | Download (31.9 KB)

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
#include <ldap.h>
36
#include <lber.h>
37
#include <pthread.h>
38
/* #include <dlfcn.h> */
39

    
40
#include "mgutils.h"
41
#include "addritem.h"
42
#include "addrcache.h"
43
#include "syldap.h"
44
#include "utils.h"
45

    
46
/*
47
* Create new LDAP server interface object.
48
*/
49
SyldapServer *syldap_create() {
50
        SyldapServer *ldapServer;
51

    
52
        debug_print("Creating LDAP server interface object\n");
53

    
54
        ldapServer = g_new0( SyldapServer, 1 );
55
        ldapServer->name = NULL;
56
        ldapServer->hostName = NULL;
57
        ldapServer->port = SYLDAP_DFL_PORT;
58
        ldapServer->baseDN = NULL;
59
        ldapServer->bindDN = NULL;
60
        ldapServer->bindPass = NULL;
61
        ldapServer->searchCriteria = NULL;
62
        ldapServer->searchValue = NULL;
63
        ldapServer->entriesRead = 0;
64
        ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
65
        ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
66
        ldapServer->newSearch = TRUE;
67
        ldapServer->addressCache = addrcache_create();
68
        ldapServer->thread = NULL;
69
        ldapServer->busyFlag = FALSE;
70
        ldapServer->retVal = MGU_SUCCESS;
71
        ldapServer->callBack = NULL;
72
        ldapServer->accessFlag = FALSE;
73
        ldapServer->idleId = 0;
74
        return ldapServer;
75
}
76

    
77
/*
78
* Specify name to be used.
79
*/
80
void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
81
        ldapServer->name = mgu_replace_string( ldapServer->name, value );
82
        g_strstrip( ldapServer->name );
83
}
84

    
85
/*
86
* Specify hostname to be used.
87
*/
88
void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
89
        addrcache_refresh( ldapServer->addressCache );
90
        ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
91
        g_strstrip( ldapServer->hostName );
92
}
93

    
94
/*
95
* Specify port to be used.
96
*/
97
void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
98
        addrcache_refresh( ldapServer->addressCache );
99
        if( value > 0 ) {
100
                ldapServer->port = value;
101
        }
102
        else {
103
                ldapServer->port = SYLDAP_DFL_PORT;
104
        }
105
}
106

    
107
/*
108
* Specify base DN to be used.
109
*/
110
void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
111
        addrcache_refresh( ldapServer->addressCache );
112
        ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
113
        g_strstrip( ldapServer->baseDN );
114
}
115

    
116
/*
117
* Specify bind DN to be used.
118
*/
119
void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
120
        addrcache_refresh( ldapServer->addressCache );
121
        ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
122
        g_strstrip( ldapServer->bindDN );
123
}
124

    
125
/*
126
* Specify bind password to be used.
127
*/
128
void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
129
        addrcache_refresh( ldapServer->addressCache );
130
        ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
131
        g_strstrip( ldapServer->bindPass );
132
}
133

    
134
/*
135
* Specify search criteria to be used.
136
*/
137
void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
138
        addrcache_refresh( ldapServer->addressCache );
139
        ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
140
        g_strstrip( ldapServer->searchCriteria );
141
        ldapServer->newSearch = TRUE;
142
}
143

    
144
/*
145
* Specify search value to be searched for.
146
*/
147
void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
148
        addrcache_refresh( ldapServer->addressCache );
149
        ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
150
        g_strstrip( ldapServer->searchValue );
151
        ldapServer->newSearch = TRUE;
152
}
153

    
154
/*
155
* Specify maximum number of entries to retrieve.
156
*/
157
void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
158
        addrcache_refresh( ldapServer->addressCache );
159
        if( value > 0 ) {
160
                ldapServer->maxEntries = value;
161
        }
162
        else {
163
                ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
164
        }
165
}
166

    
167
/*
168
* Specify timeout value for LDAP operation (in seconds).
169
*/
170
void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
171
        addrcache_refresh( ldapServer->addressCache );
172
        if( value > 0 ) {
173
                ldapServer->timeOut = value;
174
        }
175
        else {
176
                ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
177
        }
178
}
179

    
180
/*
181
* Register a callback function. When called, the function will be passed
182
* this object as an argument.
183
*/
184
void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
185
        ldapServer->callBack = func;
186
}
187

    
188
void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
189
        g_return_if_fail( ldapServer != NULL );
190
        ldapServer->accessFlag = value;
191
}
192

    
193
/*
194
* Refresh internal variables to force a file read.
195
*/
196
void syldap_force_refresh( SyldapServer *ldapServer ) {
197
        addrcache_refresh( ldapServer->addressCache );
198
        ldapServer->newSearch = TRUE;
199
}
200

    
201
gint syldap_get_status( SyldapServer *ldapServer ) {
202
        g_return_val_if_fail( ldapServer != NULL, -1 );
203
        return ldapServer->retVal;
204
}
205

    
206
ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
207
        g_return_val_if_fail( ldapServer != NULL, NULL );
208
        return addrcache_get_root_folder( ldapServer->addressCache );
209
}
210

    
211
gchar *syldap_get_name( SyldapServer *ldapServer ) {
212
        g_return_val_if_fail( ldapServer != NULL, NULL );
213
        return ldapServer->name;
214
}
215

    
216
gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
217
        g_return_val_if_fail( ldapServer != NULL, FALSE );
218
        return ldapServer->accessFlag;
219
}
220

    
221
/*
222
* Free up LDAP server interface object by releasing internal memory.
223
*/
224
void syldap_free( SyldapServer *ldapServer ) {
225
        g_return_if_fail( ldapServer != NULL );
226

    
227
        debug_print("Freeing LDAP server interface object\n");
228

    
229
        ldapServer->callBack = NULL;
230

    
231
        /* Free internal stuff */
232
        g_free( ldapServer->name );
233
        g_free( ldapServer->hostName );
234
        g_free( ldapServer->baseDN );
235
        g_free( ldapServer->bindDN );
236
        g_free( ldapServer->bindPass );
237
        g_free( ldapServer->searchCriteria );
238
        g_free( ldapServer->searchValue );
239
        g_free( ldapServer->thread );
240

    
241
        ldapServer->port = 0;
242
        ldapServer->entriesRead = 0;
243
        ldapServer->maxEntries = 0;
244
        ldapServer->newSearch = FALSE;
245

    
246
        /* Clear cache */
247
        addrcache_clear( ldapServer->addressCache );
248
        addrcache_free( ldapServer->addressCache );
249

    
250
        /* Clear pointers */
251
        ldapServer->name = NULL;
252
        ldapServer->hostName = NULL;
253
        ldapServer->baseDN = NULL;
254
        ldapServer->bindDN = NULL;
255
        ldapServer->bindPass = NULL;
256
        ldapServer->searchCriteria = NULL;
257
        ldapServer->searchValue = NULL;
258
        ldapServer->addressCache = NULL;
259
        ldapServer->thread = NULL;
260
        ldapServer->busyFlag = FALSE;
261
        ldapServer->retVal = MGU_SUCCESS;
262
        ldapServer->accessFlag = FALSE;
263

    
264
        /* Now release LDAP object */
265
        g_free( ldapServer );
266

    
267
}
268

    
269
/*
270
* Display object to specified stream.
271
*/
272
void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
273
        g_return_if_fail( ldapServer != NULL );
274

    
275
        fprintf( stream, "SyldapServer:\n" );
276
        fprintf( stream, "     name: '%s'\n", ldapServer->name );
277
        fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
278
        fprintf( stream, "     port: %d\n",   ldapServer->port );
279
        fprintf( stream, "  base dn: '%s'\n", ldapServer->baseDN );
280
        fprintf( stream, "  bind dn: '%s'\n", ldapServer->bindDN );
281
        fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
282
        fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
283
        fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
284
        fprintf( stream, "max entry: %d\n",   ldapServer->maxEntries );
285
        fprintf( stream, " num read: %d\n",   ldapServer->entriesRead );
286
        fprintf( stream, "  ret val: %d\n",   ldapServer->retVal );
287
        addrcache_print( ldapServer->addressCache, stream );
288
        addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
289
}
290

    
291
/*
292
* Display object to specified stream.
293
*/
294
void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
295
        g_return_if_fail( ldapServer != NULL );
296

    
297
        fprintf( stream, "SyldapServer:\n" );
298
        fprintf( stream, "     name: '%s'\n", ldapServer->name );
299
        fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
300
        fprintf( stream, "     port: %d\n",   ldapServer->port );
301
        fprintf( stream, "  base dn: '%s'\n", ldapServer->baseDN );
302
        fprintf( stream, "  bind dn: '%s'\n", ldapServer->bindDN );
303
        fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
304
        fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
305
        fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
306
        fprintf( stream, "max entry: %d\n",   ldapServer->maxEntries );
307
        fprintf( stream, " num read: %d\n",   ldapServer->entriesRead );
308
        fprintf( stream, "  ret val: %d\n",   ldapServer->retVal );
309
}
310

    
311
#if 0
312
/*
313
* Build an address list entry and append to list of address items. Name is formatted
314
* as it appears in the common name (cn) attribute.
315
*/
316
static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
317
        ItemPerson *person;
318
        ItemEMail *email;
319
        GSList *nodeName = listName;
320

321
        while( nodeName ) {
322
                GSList *nodeAddress = listAddr;
323
                person = addritem_create_item_person();
324
                addritem_person_set_common_name( person, nodeName->data );
325
                addrcache_id_person( ldapServer->addressCache, person );
326
                addrcache_add_person( ldapServer->addressCache, person );
327

328
                while( nodeAddress ) {
329
                        email = addritem_create_item_email();
330
                        addritem_email_set_address( email, nodeAddress->data );
331
                        addrcache_id_email( ldapServer->addressCache, email );
332
                        addrcache_person_add_email( ldapServer->addressCache, person, email );
333
                        nodeAddress = g_slist_next( nodeAddress );
334
                        ldapServer->entriesRead++;
335
                }
336
                nodeName = g_slist_next( nodeName );
337
        }
338
}
339
#endif
340

    
341
/*
342
* Build an address list entry and append to list of address items. Name is formatted
343
* as "<first-name> <last-name>".
344
*/
345
static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast  ) {
346
        GSList *nodeFirst = listFirst;
347
        GSList *nodeAddress = listAddr;
348
        gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
349
        gint iLen = 0, iLenT = 0;
350
        ItemPerson *person;
351
        ItemEMail *email;
352

    
353
        /* Find longest first name in list */
354
        while( nodeFirst ) {
355
                if( firstName == NULL ) {
356
                        firstName = nodeFirst->data;
357
                        iLen = strlen( firstName );
358
                }
359
                else {
360
                        if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
361
                                firstName = nodeFirst->data;
362
                                iLen = iLenT;
363
                        }
364
                }
365
                nodeFirst = g_slist_next( nodeFirst );
366
        }
367

    
368
        /* Format name */
369
        if( listLast ) {
370
                lastName = listLast->data;
371
        }
372

    
373
        if( firstName ) {
374
                if( lastName ) {
375
                        fullName = g_strdup_printf( "%s %s", firstName, lastName );
376
                }
377
                else {
378
                        fullName = g_strdup_printf( "%s", firstName );
379
                }
380
        }
381
        else {
382
                if( lastName ) {
383
                        fullName = g_strdup_printf( "%s", lastName );
384
                }
385
        }
386
        if( fullName ) {
387
                g_strchug( fullName ); g_strchomp( fullName );
388
        }
389

    
390
        if( nodeAddress ) {
391
                person = addritem_create_item_person();
392
                addritem_person_set_common_name( person, fullName );
393
                addritem_person_set_first_name( person, firstName );
394
                addritem_person_set_last_name( person, lastName );
395
                addrcache_id_person( ldapServer->addressCache, person );
396
                addrcache_add_person( ldapServer->addressCache, person );
397
        }
398

    
399
        /* Add address item */
400
        while( nodeAddress ) {
401
                email = addritem_create_item_email();
402
                addritem_email_set_address( email, nodeAddress->data );
403
                addrcache_id_email( ldapServer->addressCache, email );
404
                addrcache_person_add_email( ldapServer->addressCache, person, email );
405
                nodeAddress = g_slist_next( nodeAddress );
406
                ldapServer->entriesRead++;
407
        }
408
        g_free( fullName );
409
        fullName = firstName = lastName = NULL;
410

    
411
}
412

    
413
/*
414
* Add all attribute values to a list.
415
*/
416
static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
417
        GSList *list = NULL;
418
        gint i;
419
        gchar **vals;
420

    
421
        if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
422
                for( i = 0; vals[i] != NULL; i++ ) {
423
                        /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
424
                        list = g_slist_append( list, g_strdup( vals[i] ) );
425
                }
426
        }
427
        ldap_value_free( vals );
428
        return list;
429
}
430

    
431
/*
432
* Add a single attribute value to a list.
433
*/
434
static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
435
        GSList *list = NULL;
436
        gchar **vals;
437

    
438
        if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
439
                if( vals[0] != NULL ) {
440
                        /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
441
                        list = g_slist_append( list, g_strdup( vals[0] ) );
442
                }
443
        }
444
        ldap_value_free( vals );
445
        return list;
446
}
447

    
448
/*
449
* Free linked lists of character strings.
450
*/
451
static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
452
        mgu_free_list( listName );
453
        mgu_free_list( listAddr );
454
        mgu_free_list( listID );
455
        mgu_free_list( listDN );
456
        mgu_free_list( listFirst );
457
        mgu_free_list( listLast );
458
}
459

    
460
/*
461
* Check parameters that are required for a search. This should
462
* be called before performing a search.
463
* Return: TRUE if search criteria appear OK.
464
*/
465
gboolean syldap_check_search( SyldapServer *ldapServer ) {
466
        g_return_val_if_fail( ldapServer != NULL, FALSE );
467

    
468
        ldapServer->retVal = MGU_LDAP_CRITERIA;
469

    
470
        /* Test search criteria */
471
        if( ldapServer->searchCriteria == NULL ) {
472
                return FALSE;
473
        }
474
        if( strlen( ldapServer->searchCriteria ) < 1 ) {
475
                return FALSE;
476
        }
477

    
478
        if( ldapServer->searchValue == NULL ) {
479
                return FALSE;
480
        }
481
        if( strlen( ldapServer->searchValue ) < 1 ) {
482
                return FALSE;
483
        }
484

    
485
        ldapServer->retVal = MGU_SUCCESS;
486
        return TRUE;
487
}
488

    
489
/*
490
* Perform the LDAP search, reading LDAP entries into cache.
491
* Note that one LDAP entry can have multiple values for many of its
492
* attributes. If these attributes are E-Mail addresses; these are
493
* broken out into separate address items. For any other attribute,
494
* only the first occurrence is read.
495
*/
496
gint syldap_search( SyldapServer *ldapServer ) {
497
        LDAP *ld;
498
        LDAPMessage *result, *e;
499
        char *attribs[10];
500
        char *attribute;
501
        gchar *criteria;
502
        BerElement *ber;
503
        gint rc;
504
        GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
505
        GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
506
        struct timeval timeout;
507
        gboolean entriesFound = FALSE;
508

    
509
        g_return_val_if_fail( ldapServer != NULL, -1 );
510

    
511
        ldapServer->retVal = MGU_SUCCESS;
512
        if( ! syldap_check_search( ldapServer ) ) {
513
                return ldapServer->retVal;
514
        }
515

    
516
        /* Set timeout */
517
        timeout.tv_sec = ldapServer->timeOut;
518
        timeout.tv_usec = 0L;
519

    
520
        ldapServer->entriesRead = 0;
521
        if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
522
                ldapServer->retVal = MGU_LDAP_INIT;
523
                return ldapServer->retVal;
524
        }
525

    
526
        /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
527

    
528
        /* Bind to the server, if required */
529
        if( ldapServer->bindDN ) {
530
                if( * ldapServer->bindDN != '\0' ) {
531
                        /* printf( "binding...\n" ); */
532
                        rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
533
                        /* printf( "rc=%d\n", rc ); */
534
                        if( rc != LDAP_SUCCESS ) {
535
                                /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
536
                                ldap_unbind( ld );
537
                                ldapServer->retVal = MGU_LDAP_BIND;
538
                                return ldapServer->retVal;
539
                        }
540
                }
541
        }
542

    
543
        /* Define all attributes we are interested in. */
544
        attribs[0] = SYLDAP_ATTR_DN;
545
        attribs[1] = SYLDAP_ATTR_COMMONNAME;
546
        attribs[2] = SYLDAP_ATTR_GIVENNAME;
547
        attribs[3] = SYLDAP_ATTR_SURNAME;
548
        attribs[4] = SYLDAP_ATTR_EMAIL;
549
        attribs[5] = SYLDAP_ATTR_UID;
550
        attribs[6] = NULL;
551

    
552
        /* Create LDAP search string and apply search criteria */
553
        criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
554
        rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
555
                       &timeout, 0, &result );
556
        g_free( criteria );
557
        criteria = NULL;
558
        if( rc == LDAP_TIMEOUT ) {
559
                ldap_unbind( ld );
560
                ldapServer->retVal = MGU_LDAP_TIMEOUT;
561
                return ldapServer->retVal;
562
        }
563
        if( rc != LDAP_SUCCESS ) {
564
                /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
565
                ldap_unbind( ld );
566
                ldapServer->retVal = MGU_LDAP_SEARCH;
567
                return ldapServer->retVal;
568
        }
569

    
570
        /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
571

    
572
        /* Clear the cache if we have new entries, otherwise leave untouched. */
573
        if( ldap_count_entries( ld, result ) > 0 ) {
574
                addrcache_clear( ldapServer->addressCache );
575
        }
576

    
577
        /* Process results */
578
        ldapServer->entriesRead = 0;
579
        for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
580
                entriesFound = TRUE;
581
                if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;                
582
                /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
583

    
584
                /* Process all attributes */
585
                for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
586
                               attribute = ldap_next_attribute( ld, e, ber ) ) {
587
                        if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
588
                                listName = syldap_add_list_values( ld, e, attribute );
589
                        }
590
                        if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
591
                                listAddress = syldap_add_list_values( ld, e, attribute );
592
                        }
593
                        if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
594
                                listID = syldap_add_single_value( ld, e, attribute );
595
                        }
596
                        if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
597
                                listFirst = syldap_add_list_values( ld, e, attribute );
598
                        }
599
                        if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
600
                                listLast = syldap_add_single_value( ld, e, attribute );
601
                        }
602
                        if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
603
                                listDN = syldap_add_single_value( ld, e, attribute );
604
                        }
605
                }
606

    
607
                /* Free memory used to store attribute */
608
                ldap_memfree( attribute );
609

    
610
                /* Format and add items to cache */
611
                syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
612

    
613
                /* Free up */
614
                syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
615
                listName = listAddress = listID = listFirst = listLast = listDN = NULL;
616

    
617
                if( ber != NULL ) {
618
                        ber_free( ber, 0 );
619
                }
620
        }
621

    
622
        syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
623
        listName = listAddress = listID = listFirst = listLast = listDN = NULL;
624
        
625
        /* Free up and disconnect */
626
        ldap_msgfree( result );
627
        ldap_unbind( ld );
628
        ldapServer->newSearch = FALSE;
629
        if( entriesFound ) {
630
                ldapServer->retVal = MGU_SUCCESS;
631
        }
632
        else {
633
                ldapServer->retVal = MGU_LDAP_NOENTRIES;
634
        }
635
        return ldapServer->retVal;
636
}
637

    
638
/* syldap_display_search_results() - updates the ui. this function is called from the
639
 * main thread (the thread running the GTK event loop). */
640
static gint syldap_display_search_results(SyldapServer *ldapServer)
641
{
642
        /* NOTE: when this function is called the accompanying thread should
643
         * already be terminated. */
644
        gtk_idle_remove(ldapServer->idleId);
645
        ldapServer->callBack(ldapServer);
646
        /* FIXME:  match should know whether to free this SyldapServer stuff. */
647
        g_free(ldapServer->thread);
648
        ldapServer->thread = NULL;
649
        return TRUE;
650
}
651

    
652
/* ============================================================================================ */
653
/*
654
* Read data into list. Main entry point
655
* Return: TRUE if file read successfully.
656
*/
657
/* ============================================================================================ */
658
gint syldap_read_data( SyldapServer *ldapServer ) {
659
        g_return_val_if_fail( ldapServer != NULL, -1 );
660

    
661
        ldapServer->accessFlag = FALSE;
662
        pthread_detach( pthread_self() );
663
        if( ldapServer->newSearch ) {
664
                /* Read data into the list */
665
                syldap_search( ldapServer );
666

    
667
                /* Mark cache */
668
                ldapServer->addressCache->modified = FALSE;
669
                ldapServer->addressCache->dataRead = TRUE;
670
                ldapServer->accessFlag = FALSE;
671
        }
672

    
673
        /* Callback */
674
        ldapServer->busyFlag = FALSE;
675
        if( ldapServer->callBack ) {
676
                /* make the ui thread update the search results */
677
                /* TODO: really necessary to call gdk_threads_XXX()??? gtk_idle_add()
678
                 * should do this - could someone check the GTK sources please? */
679
                gdk_threads_enter();
680
                ldapServer->idleId = gtk_idle_add((GtkFunction)syldap_display_search_results, ldapServer);
681
                gdk_threads_leave();
682
        }
683

    
684
        return ldapServer->retVal;
685
}
686

    
687
/* ============================================================================================ */
688
/*
689
* Cancel read with thread.
690
*/
691
/* ============================================================================================ */
692
void syldap_cancel_read( SyldapServer *ldapServer ) {
693
        g_return_if_fail( ldapServer != NULL );
694

    
695
        /* DELETEME: this is called from inside UI thread so it's OK, Christoph! */
696
        if( ldapServer->thread ) {
697
                /* printf( "thread cancelled\n" ); */
698
                pthread_cancel( *ldapServer->thread );
699
        }
700
        g_free(ldapServer->thread);
701
        ldapServer->thread = NULL;
702
        ldapServer->busyFlag = FALSE;
703
}
704

    
705
/* ============================================================================================ */
706
/*
707
* Read data into list using a background thread.
708
* Return: TRUE if file read successfully. Callback function will be
709
* notified when search is complete.
710
*/
711
/* ============================================================================================ */
712
gint syldap_read_data_th( SyldapServer *ldapServer ) {
713
        g_return_val_if_fail( ldapServer != NULL, -1 );
714

    
715
        ldapServer->busyFlag = FALSE;
716
        syldap_check_search( ldapServer );
717
        if( ldapServer->retVal == MGU_SUCCESS ) {
718
                /* debug_print("Staring LDAP read thread\n"); */
719

    
720
                ldapServer->busyFlag = TRUE;
721
                ldapServer->thread = g_new0(pthread_t, 1);
722
                pthread_create( ldapServer->thread, NULL, (void *) syldap_read_data, (void *) ldapServer );
723
        }
724
        return ldapServer->retVal;
725
}
726

    
727
/*
728
* Return link list of persons.
729
*/
730
GList *syldap_get_list_person( SyldapServer *ldapServer ) {
731
        g_return_val_if_fail( ldapServer != NULL, NULL );
732
        return addrcache_get_list_person( ldapServer->addressCache );
733
}
734

    
735
/*
736
* Return link list of folders. This is always NULL since there are
737
* no folders in GnomeCard.
738
* Return: NULL.
739
*/
740
GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
741
        g_return_val_if_fail( ldapServer != NULL, NULL );
742
        return NULL;
743
}
744

    
745
#define SYLDAP_TEST_FILTER   "(objectclass=*)"
746
#define SYLDAP_SEARCHBASE_V2 "cn=config"
747
#define SYLDAP_SEARCHBASE_V3 ""
748
#define SYLDAP_V2_TEST_ATTR  "database"
749
#define SYLDAP_V3_TEST_ATTR  "namingcontexts"
750

    
751
/*
752
* Attempt to discover the base DN for the server.
753
* Enter:
754
*        host        Host name
755
*        port        Port number
756
*        bindDN        Bind DN (optional).
757
*        bindPW        Bind PW (optional).
758
*        tov        Timeout value (seconds), or 0 for none, default 30 secs.
759
* Return: List of Base DN's, or NULL if could not read. Base DN should
760
* be g_free() when done.
761
*/
762
GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
763
        GList *baseDN = NULL;
764
        LDAP *ld;
765
        gint rc, i;
766
        LDAPMessage *result, *e;
767
        gchar *attribs[10];
768
        BerElement *ber;
769
        gchar *attribute;
770
        gchar **vals;
771
        struct timeval timeout;
772

    
773
        if( host == NULL ) return baseDN;
774
        if( port < 1 ) return baseDN;
775

    
776
        /* Set timeout */
777
        timeout.tv_usec = 0L;
778
        if( tov > 0 ) {
779
                timeout.tv_sec = tov;
780
        }
781
        else {
782
                timeout.tv_sec = 30L;
783
        }
784

    
785
        /* Connect to server. */
786
        if( ( ld = ldap_init( host, port ) ) == NULL ) {
787
                return baseDN;
788
        }
789

    
790
        /* Bind to the server, if required */
791
        if( bindDN ) {
792
                if( *bindDN != '\0' ) {
793
                        rc = ldap_simple_bind_s( ld, bindDN, bindPW );
794
                        if( rc != LDAP_SUCCESS ) {
795
                                /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
796
                                ldap_unbind( ld );
797
                                return baseDN;
798
                        }
799
                }
800
        }
801

    
802
        /* Test for LDAP version 3 */
803
        attribs[0] = SYLDAP_V3_TEST_ATTR;
804
        attribs[1] = NULL;
805
        rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
806
                       0, NULL, NULL, &timeout, 0, &result );
807
        if( rc == LDAP_SUCCESS ) {
808
                /* Process entries */
809
                for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
810
                        /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
811

    
812
                        /* Process attributes */
813
                        for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
814
                                        attribute = ldap_next_attribute( ld, e, ber ) ) {
815
                                if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
816
                                        if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
817
                                                for( i = 0; vals[i] != NULL; i++ ) {
818
                                                        /* printf( "\t%s: %s\n", attribute, vals[i] ); */
819
                                                        baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
820
                                                }
821
                                        }
822
                                        ldap_value_free( vals );
823
                                }
824
                        }
825
                        ldap_memfree( attribute );
826
                        if( ber != NULL ) {
827
                                ber_free( ber, 0 );
828
                        }
829
                }
830
                ldap_msgfree( result );
831
        }
832
        else {
833
        }
834

    
835
        if( baseDN == NULL ) {
836
                /* Test for LDAP version 2 */
837
                attribs[0] = NULL;
838
                rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
839
                               0, NULL, NULL, &timeout, 0, &result );
840
                if( rc == LDAP_SUCCESS ) {
841
                        /* Process entries */
842
                        for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
843
                                /* if( baseDN ) break;                         */
844
                                /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
845

    
846
                                /* Process attributes */
847
                                for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
848
                                               attribute = ldap_next_attribute( ld, e, ber ) ) {
849
                                        /* if( baseDN ) break;                         */
850
                                        if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
851
                                                if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
852
                                                        for( i = 0; vals[i] != NULL; i++ ) {
853
                                                                char *ch;
854
                                                                /* Strip the 'ldb:' from the front of the value */
855
                                                                ch = ( char * ) strchr( vals[i], ':' );
856
                                                                if( ch ) {
857
                                                                        gchar *bn = g_strdup( ++ch );
858
                                                                        g_strchomp( bn );
859
                                                                        g_strchug( bn );
860
                                                                        baseDN = g_list_append( baseDN, g_strdup( bn ) );
861
                                                                }
862
                                                        }
863
                                                }
864
                                                ldap_value_free( vals );
865
                                        }
866
                                }
867
                                ldap_memfree( attribute );
868
                                if( ber != NULL ) {
869
                                        ber_free( ber, 0 );
870
                                }
871
                        }
872
                        ldap_msgfree( result );
873
                }
874
        }
875
        ldap_unbind( ld );
876
        return baseDN;
877
}
878

    
879
/*
880
* Attempt to discover the base DN for the server.
881
* Enter:  ldapServer Server to test.
882
* Return: List of Base DN's, or NULL if could not read. Base DN should
883
* be g_free() when done. Return code set in ldapServer.
884
*/
885
GList *syldap_read_basedn( SyldapServer *ldapServer ) {
886
        GList *baseDN = NULL;
887
        LDAP *ld;
888
        gint rc, i;
889
        LDAPMessage *result, *e;
890
        gchar *attribs[10];
891
        BerElement *ber;
892
        gchar *attribute;
893
        gchar **vals;
894
        struct timeval timeout;
895

    
896
        ldapServer->retVal = MGU_BAD_ARGS;
897
        if( ldapServer == NULL ) return baseDN;
898
        if( ldapServer->hostName == NULL ) return baseDN;
899
        if( ldapServer->port < 1 ) return baseDN;
900

    
901
        /* Set timeout */
902
        timeout.tv_usec = 0L;
903
        if( ldapServer->timeOut > 0 ) {
904
                timeout.tv_sec = ldapServer->timeOut;
905
        }
906
        else {
907
                timeout.tv_sec = 30L;
908
        }
909

    
910
        /* Connect to server. */
911
        if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
912
                ldapServer->retVal = MGU_LDAP_INIT;
913
                return baseDN;
914
        }
915

    
916
        /* Bind to the server, if required */
917
        if( ldapServer->bindDN ) {
918
                if( *ldapServer->bindDN != '\0' ) {
919
                        rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
920
                        if( rc != LDAP_SUCCESS ) {
921
                                /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
922
                                ldap_unbind( ld );
923
                                ldapServer->retVal = MGU_LDAP_BIND;
924
                                return baseDN;
925
                        }
926
                }
927
        }
928

    
929
        ldapServer->retVal = MGU_LDAP_SEARCH;
930

    
931
        /* Test for LDAP version 3 */
932
        attribs[0] = SYLDAP_V3_TEST_ATTR;
933
        attribs[1] = NULL;
934
        rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
935
                       0, NULL, NULL, &timeout, 0, &result );
936
        if( rc == LDAP_SUCCESS ) {
937
                /* Process entries */
938
                for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
939
                        /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
940

    
941
                        /* Process attributes */
942
                        for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
943
                                        attribute = ldap_next_attribute( ld, e, ber ) ) {
944
                                if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
945
                                        if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
946
                                                for( i = 0; vals[i] != NULL; i++ ) {
947
                                                        /* printf( "\t%s: %s\n", attribute, vals[i] ); */
948
                                                        baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
949
                                                }
950
                                        }
951
                                        ldap_value_free( vals );
952
                                }
953
                        }
954
                        ldap_memfree( attribute );
955
                        if( ber != NULL ) {
956
                                ber_free( ber, 0 );
957
                        }
958
                }
959
                ldap_msgfree( result );
960
                ldapServer->retVal = MGU_SUCCESS;
961
        }
962
        else if( rc == LDAP_TIMEOUT ) {
963
                ldapServer->retVal = MGU_LDAP_TIMEOUT;
964
        }
965

    
966
        if( baseDN == NULL ) {
967
                /* Test for LDAP version 2 */
968
                attribs[0] = NULL;
969
                rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
970
                               0, NULL, NULL, &timeout, 0, &result );
971
                if( rc == LDAP_SUCCESS ) {
972
                        /* Process entries */
973
                        for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
974
                                /* if( baseDN ) break;                         */
975
                                /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
976

    
977
                                /* Process attributes */
978
                                for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
979
                                               attribute = ldap_next_attribute( ld, e, ber ) ) {
980
                                        /* if( baseDN ) break;                         */
981
                                        if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
982
                                                if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
983
                                                        for( i = 0; vals[i] != NULL; i++ ) {
984
                                                                char *ch;
985
                                                                /* Strip the 'ldb:' from the front of the value */
986
                                                                ch = ( char * ) strchr( vals[i], ':' );
987
                                                                if( ch ) {
988
                                                                        gchar *bn = g_strdup( ++ch );
989
                                                                        g_strchomp( bn );
990
                                                                        g_strchug( bn );
991
                                                                        baseDN = g_list_append( baseDN, g_strdup( bn ) );
992
                                                                }
993
                                                        }
994
                                                }
995
                                                ldap_value_free( vals );
996
                                        }
997
                                }
998
                                ldap_memfree( attribute );
999
                                if( ber != NULL ) {
1000
                                        ber_free( ber, 0 );
1001
                                }
1002
                        }
1003
                        ldap_msgfree( result );
1004
                        ldapServer->retVal = MGU_SUCCESS;
1005
                }
1006
                else if( rc == LDAP_TIMEOUT ) {
1007
                        ldapServer->retVal = MGU_LDAP_TIMEOUT;
1008
                }
1009
        }
1010
        ldap_unbind( ld );
1011

    
1012
        return baseDN;
1013
}
1014

    
1015
/*
1016
* Attempt to connect to the server.
1017
* Enter:
1018
*        host        Host name
1019
*        port        Port number
1020
* Return: TRUE if connected successfully.
1021
*/
1022
gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
1023
        gboolean retVal = FALSE;
1024
        LDAP *ld;
1025

    
1026
        if( host == NULL ) return retVal;
1027
        if( port < 1 ) return retVal;
1028
        if( ( ld = ldap_open( host, port ) ) != NULL ) {
1029
                retVal = TRUE;
1030
        }
1031
        if( ld != NULL ) {
1032
                ldap_unbind( ld );
1033
        }
1034
        return retVal;
1035
}
1036

    
1037
/*
1038
* Attempt to connect to the server.
1039
* Enter:  ldapServer Server to test.
1040
* Return: TRUE if connected successfully. Return code set in ldapServer.
1041
*/
1042
gboolean syldap_test_connect( SyldapServer *ldapServer ) {
1043
        gboolean retVal = FALSE;
1044
        LDAP *ld;
1045

    
1046
        ldapServer->retVal = MGU_BAD_ARGS;
1047
        if( ldapServer == NULL ) return retVal;
1048
        if( ldapServer->hostName == NULL ) return retVal;
1049
        if( ldapServer->port < 1 ) return retVal;
1050
        ldapServer->retVal = MGU_LDAP_INIT;
1051
        if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1052
                ldapServer->retVal = MGU_SUCCESS;
1053
                retVal = TRUE;
1054
        }
1055
        if( ld != NULL ) {
1056
                ldap_unbind( ld );
1057
        }
1058
        return retVal;
1059
}
1060

    
1061
#define LDAP_LINK_LIB_NAME_1 "libldap.so"
1062
#define LDAP_LINK_LIB_NAME_2 "liblber.so"
1063
#define LDAP_LINK_LIB_NAME_3 "libresolv.so"
1064
#define LDAP_LINK_LIB_NAME_4 "libpthread.so"
1065

    
1066
/*
1067
* Test whether LDAP libraries installed.
1068
* Return: TRUE if library available.
1069
*/
1070
#if 0
1071
gboolean syldap_test_ldap_lib() {
1072
        void *handle, *fun;
1073
        
1074
        /* Get library */
1075
        handle = dlopen( LDAP_LINK_LIB_NAME_1, RTLD_LAZY );
1076
        if( ! handle ) {
1077
                return FALSE;
1078
        }
1079

1080
        /* Test for symbols we need */
1081
        fun = dlsym( handle, "ldap_init" );
1082
        if( ! fun ) {
1083
                dlclose( handle );
1084
                return FALSE;
1085
        }
1086
        dlclose( handle ); handle = NULL; fun = NULL;
1087

1088
        handle = dlopen( LDAP_LINK_LIB_NAME_2, RTLD_LAZY );
1089
        if( ! handle ) {
1090
                return FALSE;
1091
        }
1092
        fun = dlsym( handle, "ber_init" );
1093
        if( ! fun ) {
1094
                dlclose( handle );
1095
                return FALSE;
1096
        }
1097
        dlclose( handle ); handle = NULL; fun = NULL;
1098

1099
        handle = dlopen( LDAP_LINK_LIB_NAME_3, RTLD_LAZY );
1100
        if( ! handle ) {
1101
                return FALSE;
1102
        }
1103
        fun = dlsym( handle, "res_query" );
1104
        if( ! fun ) {
1105
                dlclose( handle );
1106
                return FALSE;
1107
        }
1108
        dlclose( handle ); handle = NULL; fun = NULL;
1109

1110
        handle = dlopen( LDAP_LINK_LIB_NAME_4, RTLD_LAZY );
1111
        if( ! handle ) {
1112
                return FALSE;
1113
        }
1114
        fun = dlsym( handle, "pthread_create" );
1115
        if( ! fun ) {
1116
                dlclose( handle );
1117
                return FALSE;
1118
        }
1119
        dlclose( handle ); handle = NULL; fun = NULL;
1120

1121
        return TRUE;
1122
}
1123
#endif /* 0 */
1124

    
1125
#endif        /* USE_LDAP */
1126

    
1127
/*
1128
* End of Source.
1129
*/