Statistics
| Revision:

root / src / syldap.c @ 3309

History | View | Annotate | Download (31.8 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
#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
*/
50
SyldapServer *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
*/
81
void 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
*/
89
void 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
*/
98
void 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
*/
111
void 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
*/
120
void 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
*/
129
void 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
*/
138
void 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
*/
148
void 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
*/
158
void 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
*/
171
void 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
*/
185
void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
186
        ldapServer->callBack = func;
187
}
188

    
189
void 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
*/
197
void syldap_force_refresh( SyldapServer *ldapServer ) {
198
        addrcache_refresh( ldapServer->addressCache );
199
        ldapServer->newSearch = TRUE;
200
}
201

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

    
207
ItemFolder *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

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

    
217
gboolean 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
*/
225
void 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
*/
273
void 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
*/
295
void 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
*/
317
static 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
*/
346
static 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
*/
417
static 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
*/
435
static 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
*/
452
static 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
*/
466
gboolean 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
*/
497
gint 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). */
641
static 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
/* ============================================================================================ */
660
gint 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
/* ============================================================================================ */
690
void 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
/* ============================================================================================ */
710
gint 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
*/
728
GList *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
*/
738
GList *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
*/
760
GList *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
*/
883
GList *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
*/
1020
gboolean 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
*/
1040
gboolean 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
1069
gboolean 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
*/