2006-12-12 [paul] 2.6.1cvs21
[claws.git] / src / syldap.c
blob31ee41c98ab078fcf828f53e2ad50d5b57f9f031
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2006 Match Grun and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * Functions necessary to access LDAP servers.
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #ifdef USE_LDAP
30 #include <glib.h>
31 #include <sys/time.h>
32 #include <string.h>
33 #include <ldap.h>
34 #include <lber.h>
35 #include <pthread.h>
37 #include "mgutils.h"
38 #include "addritem.h"
39 #include "addrcache.h"
40 #include "syldap.h"
41 #include "utils.h"
42 #include "adbookbase.h"
45 * Create new LDAP server interface object.
47 SyldapServer *syldap_create() {
48 SyldapServer *ldapServer;
50 debug_print("Creating LDAP server interface object\n");
52 ldapServer = g_new0( SyldapServer, 1 );
53 ldapServer->type = ADBOOKTYPE_LDAP;
54 ldapServer->addressCache = addrcache_create();
55 ldapServer->retVal = MGU_SUCCESS;
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->thread = NULL;
68 ldapServer->busyFlag = FALSE;
69 ldapServer->callBack = NULL;
70 ldapServer->idleId = 0;
71 return ldapServer;
75 * Specify name to be used.
77 void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
78 g_return_if_fail( ldapServer != NULL );
79 addrcache_set_name( ldapServer->addressCache, value );
83 * Specify hostname to be used.
85 void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
86 addrcache_refresh( ldapServer->addressCache );
87 ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
88 g_strstrip( ldapServer->hostName );
92 * Specify port to be used.
94 void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
95 addrcache_refresh( ldapServer->addressCache );
96 if( value > 0 ) {
97 ldapServer->port = value;
99 else {
100 ldapServer->port = SYLDAP_DFL_PORT;
105 * Specify base DN to be used.
107 void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
108 addrcache_refresh( ldapServer->addressCache );
109 ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
110 g_strstrip( ldapServer->baseDN );
114 * Specify bind DN to be used.
116 void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
117 addrcache_refresh( ldapServer->addressCache );
118 ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
119 g_strstrip( ldapServer->bindDN );
123 * Specify bind password to be used.
125 void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
126 addrcache_refresh( ldapServer->addressCache );
127 ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
128 g_strstrip( ldapServer->bindPass );
132 * Specify search criteria to be used.
134 void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
135 addrcache_refresh( ldapServer->addressCache );
136 ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
137 g_strstrip( ldapServer->searchCriteria );
138 ldapServer->newSearch = TRUE;
142 * Specify search value to be searched for.
144 void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
145 addrcache_refresh( ldapServer->addressCache );
146 ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
147 g_strstrip( ldapServer->searchValue );
148 ldapServer->newSearch = TRUE;
152 * Specify maximum number of entries to retrieve.
154 void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
155 addrcache_refresh( ldapServer->addressCache );
156 if( value > 0 ) {
157 ldapServer->maxEntries = value;
159 else {
160 ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
165 * Specify timeout value for LDAP operation (in seconds).
167 void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
168 addrcache_refresh( ldapServer->addressCache );
169 if( value > 0 ) {
170 ldapServer->timeOut = value;
172 else {
173 ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
178 * Register a callback function. When called, the function will be passed
179 * this object as an argument.
181 void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
182 ldapServer->callBack = func;
186 * Refresh internal variables to force a file read.
188 void syldap_force_refresh( SyldapServer *ldapServer ) {
189 addrcache_refresh( ldapServer->addressCache );
190 ldapServer->newSearch = TRUE;
193 gint syldap_get_status( SyldapServer *ldapServer ) {
194 g_return_val_if_fail( ldapServer != NULL, -1 );
195 return ldapServer->retVal;
198 ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
199 g_return_val_if_fail( ldapServer != NULL, NULL );
200 return addrcache_get_root_folder( ldapServer->addressCache );
203 gchar *syldap_get_name( SyldapServer *ldapServer ) {
204 g_return_val_if_fail( ldapServer != NULL, NULL );
205 return addrcache_get_name( ldapServer->addressCache );
208 gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
209 g_return_val_if_fail( ldapServer != NULL, FALSE );
210 return ldapServer->addressCache->accessFlag;
213 void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
214 g_return_if_fail( ldapServer != NULL );
215 ldapServer->addressCache->accessFlag = value;
218 gboolean syldap_get_modified( SyldapServer *ldapServer ) {
219 g_return_val_if_fail( ldapServer != NULL, FALSE );
220 return ldapServer->addressCache->modified;
223 void syldap_set_modified( SyldapServer *ldapServer, const gboolean value ) {
224 g_return_if_fail( ldapServer != NULL );
225 ldapServer->addressCache->modified = value;
229 * Free up LDAP server interface object by releasing internal memory.
231 void syldap_free( SyldapServer *ldapServer ) {
232 g_return_if_fail( ldapServer != NULL );
234 debug_print("Freeing LDAP server interface object\n");
236 ldapServer->callBack = NULL;
238 /* Clear cache */
239 addrcache_clear( ldapServer->addressCache );
240 addrcache_free( ldapServer->addressCache );
242 /* Free internal stuff */
243 g_free( ldapServer->hostName );
244 g_free( ldapServer->baseDN );
245 g_free( ldapServer->bindDN );
246 g_free( ldapServer->bindPass );
247 g_free( ldapServer->searchCriteria );
248 g_free( ldapServer->searchValue );
249 g_free( ldapServer->thread );
252 /* Clear pointers */
253 ldapServer->hostName = NULL;
254 ldapServer->port = 0;
255 ldapServer->baseDN = NULL;
256 ldapServer->bindDN = NULL;
257 ldapServer->bindPass = NULL;
258 ldapServer->searchCriteria = NULL;
259 ldapServer->searchValue = NULL;
260 ldapServer->entriesRead = 0;
261 ldapServer->maxEntries = 0;
262 ldapServer->timeOut = 0;
263 ldapServer->newSearch = FALSE;
264 ldapServer->thread = NULL;
265 ldapServer->busyFlag = FALSE;
266 ldapServer->callBack = NULL;
267 ldapServer->idleId = 0;
269 ldapServer->type = ADBOOKTYPE_NONE;
270 ldapServer->addressCache = NULL;
271 ldapServer->retVal = MGU_SUCCESS;
273 /* Now release LDAP object */
274 g_free( ldapServer );
278 * Display object to specified stream.
280 void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
281 g_return_if_fail( ldapServer != NULL );
283 fprintf( stream, "SyldapServer:\n" );
284 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
285 fprintf( stream, " port: %d\n", ldapServer->port );
286 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
287 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
288 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
289 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
290 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
291 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
292 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
293 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
294 addrcache_print( ldapServer->addressCache, stream );
295 addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
299 * Display object to specified stream.
301 void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
302 g_return_if_fail( ldapServer != NULL );
304 fprintf( stream, "SyldapServer:\n" );
305 fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
306 fprintf( stream, " port: %d\n", ldapServer->port );
307 fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
308 fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
309 fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
310 fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
311 fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
312 fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
313 fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
314 fprintf( stream, " ret val: %d\n", ldapServer->retVal );
318 * Build an address list entry and append to list of address items. Name is formatted
319 * as "<first-name> <last-name>".
321 static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
322 GSList *nodeFirst = listFirst;
323 GSList *nodeAddress = listAddr;
324 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
325 gint iLen = 0, iLenT = 0;
326 ItemPerson *person;
327 ItemEMail *email;
329 /* Find longest first name in list */
330 while( nodeFirst ) {
331 if( firstName == NULL ) {
332 firstName = nodeFirst->data;
333 iLen = strlen( firstName );
335 else {
336 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
337 firstName = nodeFirst->data;
338 iLen = iLenT;
341 nodeFirst = g_slist_next( nodeFirst );
344 /* Format name */
345 if( listLast ) {
346 lastName = listLast->data;
349 if( firstName ) {
350 if( lastName ) {
351 fullName = g_strdup_printf( "%s %s", firstName, lastName );
353 else {
354 fullName = g_strdup_printf( "%s", firstName );
357 else {
358 if( lastName ) {
359 fullName = g_strdup_printf( "%s", lastName );
362 if( fullName ) {
363 g_strchug( fullName ); g_strchomp( fullName );
366 if( nodeAddress ) {
367 person = addritem_create_item_person();
368 addritem_person_set_common_name( person, fullName );
369 addritem_person_set_first_name( person, firstName );
370 addritem_person_set_last_name( person, lastName );
371 addrcache_id_person( ldapServer->addressCache, person );
372 addrcache_add_person( ldapServer->addressCache, person );
375 /* Add address item */
376 while( nodeAddress ) {
377 email = addritem_create_item_email();
378 addritem_email_set_address( email, nodeAddress->data );
379 addrcache_id_email( ldapServer->addressCache, email );
380 addrcache_person_add_email( ldapServer->addressCache, person, email );
381 nodeAddress = g_slist_next( nodeAddress );
382 ldapServer->entriesRead++;
384 g_free( fullName );
385 fullName = firstName = lastName = NULL;
390 * Add all attribute values to a list.
392 static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
393 GSList *list = NULL;
394 gint i;
395 gchar **vals;
397 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
398 for( i = 0; vals[i] != NULL; i++ ) {
399 /* printf( "lv\t%s: %s\n", attr, vals[i] ); */
400 list = g_slist_append( list, g_strdup( vals[i] ) );
403 ldap_value_free( vals );
404 return list;
408 * Add a single attribute value to a list.
410 static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
411 GSList *list = NULL;
412 gchar **vals;
414 if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
415 if( vals[0] != NULL ) {
416 /* printf( "sv\t%s: %s\n", attr, vals[0] ); */
417 list = g_slist_append( list, g_strdup( vals[0] ) );
420 ldap_value_free( vals );
421 return list;
425 * Free linked lists of character strings.
427 static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
428 mgu_free_list( listName );
429 mgu_free_list( listAddr );
430 mgu_free_list( listID );
431 mgu_free_list( listDN );
432 mgu_free_list( listFirst );
433 mgu_free_list( listLast );
437 * Check parameters that are required for a search. This should
438 * be called before performing a search.
439 * Return: TRUE if search criteria appear OK.
441 gboolean syldap_check_search( SyldapServer *ldapServer ) {
442 g_return_val_if_fail( ldapServer != NULL, FALSE );
444 ldapServer->retVal = MGU_LDAP_CRITERIA;
446 /* Test search criteria */
447 if( ldapServer->searchCriteria == NULL ) {
448 return FALSE;
450 if( strlen( ldapServer->searchCriteria ) < 1 ) {
451 return FALSE;
454 if( ldapServer->searchValue == NULL ) {
455 return FALSE;
457 if( strlen( ldapServer->searchValue ) < 1 ) {
458 return FALSE;
461 ldapServer->retVal = MGU_SUCCESS;
462 return TRUE;
466 * Perform the LDAP search, reading LDAP entries into cache.
467 * Note that one LDAP entry can have multiple values for many of its
468 * attributes. If these attributes are E-Mail addresses; these are
469 * broken out into separate address items. For any other attribute,
470 * only the first occurrence is read.
472 gint syldap_search( SyldapServer *ldapServer ) {
473 LDAP *ld;
474 LDAPMessage *result, *e;
475 char *attribs[10];
476 char *attribute;
477 gchar *criteria;
478 BerElement *ber;
479 gint rc;
480 GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
481 GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
482 struct timeval timeout;
483 gboolean entriesFound = FALSE;
485 g_return_val_if_fail( ldapServer != NULL, -1 );
487 ldapServer->retVal = MGU_SUCCESS;
488 if( ! syldap_check_search( ldapServer ) ) {
489 return ldapServer->retVal;
492 /* Set timeout */
493 timeout.tv_sec = ldapServer->timeOut;
494 timeout.tv_usec = 0L;
496 ldapServer->entriesRead = 0;
497 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
498 ldapServer->retVal = MGU_LDAP_INIT;
499 return ldapServer->retVal;
502 /* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
504 /* Bind to the server, if required */
505 if( ldapServer->bindDN ) {
506 if( * ldapServer->bindDN != '\0' ) {
507 /* printf( "binding...\n" ); */
508 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
509 /* printf( "rc=%d\n", rc ); */
510 if( rc != LDAP_SUCCESS ) {
511 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
512 ldap_unbind( ld );
513 ldapServer->retVal = MGU_LDAP_BIND;
514 return ldapServer->retVal;
519 /* Define all attributes we are interested in. */
520 attribs[0] = SYLDAP_ATTR_DN;
521 attribs[1] = SYLDAP_ATTR_COMMONNAME;
522 attribs[2] = SYLDAP_ATTR_GIVENNAME;
523 attribs[3] = SYLDAP_ATTR_SURNAME;
524 attribs[4] = SYLDAP_ATTR_EMAIL;
525 attribs[5] = SYLDAP_ATTR_UID;
526 attribs[6] = NULL;
528 /* Create LDAP search string and apply search criteria */
529 criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
530 rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
531 &timeout, 0, &result );
532 g_free( criteria );
533 criteria = NULL;
534 if( rc == LDAP_TIMEOUT ) {
535 ldap_unbind( ld );
536 ldapServer->retVal = MGU_LDAP_TIMEOUT;
537 return ldapServer->retVal;
539 if( rc != LDAP_SUCCESS ) {
540 /* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
541 ldap_unbind( ld );
542 ldapServer->retVal = MGU_LDAP_SEARCH;
543 return ldapServer->retVal;
546 /* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
548 /* Clear the cache if we have new entries, otherwise leave untouched. */
549 if( ldap_count_entries( ld, result ) > 0 ) {
550 addrcache_clear( ldapServer->addressCache );
553 /* Process results */
554 ldapServer->entriesRead = 0;
555 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
556 entriesFound = TRUE;
557 if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
558 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
560 /* Process all attributes */
561 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
562 attribute = ldap_next_attribute( ld, e, ber ) ) {
563 if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
564 listName = syldap_add_list_values( ld, e, attribute );
566 if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
567 listAddress = syldap_add_list_values( ld, e, attribute );
569 if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
570 listID = syldap_add_single_value( ld, e, attribute );
572 if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
573 listFirst = syldap_add_list_values( ld, e, attribute );
575 if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
576 listLast = syldap_add_single_value( ld, e, attribute );
578 if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
579 listDN = syldap_add_single_value( ld, e, attribute );
582 /* Free memory used to store attribute */
583 ldap_memfree( attribute );
586 /* Format and add items to cache */
587 syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
589 /* Free up */
590 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
591 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
593 if( ber != NULL ) {
594 ber_free( ber, 0 );
598 syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
599 listName = listAddress = listID = listFirst = listLast = listDN = NULL;
601 /* Free up and disconnect */
602 ldap_msgfree( result );
603 ldap_unbind( ld );
604 ldapServer->newSearch = FALSE;
605 if( entriesFound ) {
606 ldapServer->retVal = MGU_SUCCESS;
608 else {
609 ldapServer->retVal = MGU_LDAP_NOENTRIES;
611 return ldapServer->retVal;
614 /* ============================================================================================ */
616 * Read data into list. Main entry point
617 * Return: TRUE if file read successfully.
619 /* ============================================================================================ */
620 gint syldap_read_data( SyldapServer *ldapServer ) {
621 g_return_val_if_fail( ldapServer != NULL, -1 );
623 ldapServer->addressCache->accessFlag = FALSE;
624 pthread_detach( pthread_self() );
625 if( ldapServer->newSearch ) {
626 /* Read data into the list */
627 syldap_search( ldapServer );
629 /* Mark cache */
630 ldapServer->addressCache->modified = FALSE;
631 ldapServer->addressCache->dataRead = TRUE;
632 ldapServer->addressCache->accessFlag = FALSE;
634 ldapServer->busyFlag = FALSE;
636 return ldapServer->retVal;
639 /* ============================================================================================ */
641 * Cancel read with thread.
643 /* ============================================================================================ */
644 void syldap_cancel_read( SyldapServer *ldapServer ) {
645 g_return_if_fail( ldapServer != NULL );
647 if( ldapServer->thread ) {
648 /* printf( "thread cancelled\n" ); */
649 pthread_cancel( *ldapServer->thread );
650 g_free(ldapServer->thread);
652 ldapServer->thread = NULL;
653 ldapServer->busyFlag = FALSE;
656 /* ============================================================================================ */
658 * Read data into list using a background thread.
659 * Return: TRUE if file read successfully. Callback function will be
660 * notified when search is complete.
662 /* ============================================================================================ */
663 gint syldap_read_data_th( SyldapServer *ldapServer ) {
664 g_return_val_if_fail( ldapServer != NULL, -1 );
666 ldapServer->busyFlag = FALSE;
667 syldap_check_search( ldapServer );
668 if( ldapServer->retVal == MGU_SUCCESS ) {
669 /* debug_print("Starting LDAP read thread\n"); */
671 ldapServer->busyFlag = TRUE;
672 ldapServer->thread = g_new0(pthread_t, 1);
673 pthread_create(
674 ldapServer->thread, NULL, (void *) syldap_read_data,
675 (void *) ldapServer );
677 return ldapServer->retVal;
681 * Return link list of persons.
683 GList *syldap_get_list_person( SyldapServer *ldapServer ) {
684 g_return_val_if_fail( ldapServer != NULL, NULL );
685 return addrcache_get_list_person( ldapServer->addressCache );
689 * Return link list of folders. This is always NULL since there are
690 * no folders in GnomeCard.
691 * Return: NULL.
693 GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
694 g_return_val_if_fail( ldapServer != NULL, NULL );
695 return NULL;
698 #define SYLDAP_TEST_FILTER "(objectclass=*)"
699 #define SYLDAP_SEARCHBASE_V2 "cn=config"
700 #define SYLDAP_SEARCHBASE_V3 ""
701 #define SYLDAP_V2_TEST_ATTR "database"
702 #define SYLDAP_V3_TEST_ATTR "namingcontexts"
705 * Attempt to discover the base DN for the server.
706 * Enter:
707 * host Host name
708 * port Port number
709 * bindDN Bind DN (optional).
710 * bindPW Bind PW (optional).
711 * tov Timeout value (seconds), or 0 for none, default 30 secs.
712 * Return: List of Base DN's, or NULL if could not read. Base DN should
713 * be g_free() when done.
715 GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
716 GList *baseDN = NULL;
717 LDAP *ld;
718 gint rc, i;
719 LDAPMessage *result, *e;
720 gchar *attribs[10];
721 BerElement *ber;
722 gchar *attribute;
723 gchar **vals;
724 struct timeval timeout;
726 if( host == NULL ) return baseDN;
727 if( port < 1 ) return baseDN;
729 /* Set timeout */
730 timeout.tv_usec = 0L;
731 if( tov > 0 ) {
732 timeout.tv_sec = tov;
734 else {
735 timeout.tv_sec = 30L;
738 /* Connect to server. */
739 if( ( ld = ldap_init( host, port ) ) == NULL ) {
740 return baseDN;
743 /* Bind to the server, if required */
744 if( bindDN ) {
745 if( *bindDN != '\0' ) {
746 rc = ldap_simple_bind_s( ld, bindDN, bindPW );
747 if( rc != LDAP_SUCCESS ) {
748 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
749 ldap_unbind( ld );
750 return baseDN;
755 /* Test for LDAP version 3 */
756 attribs[0] = SYLDAP_V3_TEST_ATTR;
757 attribs[1] = NULL;
758 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
759 0, NULL, NULL, &timeout, 0, &result );
760 if( rc == LDAP_SUCCESS ) {
761 /* Process entries */
762 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
763 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
765 /* Process attributes */
766 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
767 attribute = ldap_next_attribute( ld, e, ber ) ) {
768 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
769 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
770 for( i = 0; vals[i] != NULL; i++ ) {
771 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
772 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
775 ldap_value_free( vals );
777 ldap_memfree( attribute );
779 if( ber != NULL ) {
780 ber_free( ber, 0 );
783 ldap_msgfree( result );
785 else {
788 if( baseDN == NULL ) {
789 /* Test for LDAP version 2 */
790 attribs[0] = NULL;
791 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
792 0, NULL, NULL, &timeout, 0, &result );
793 if( rc == LDAP_SUCCESS ) {
794 /* Process entries */
795 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
796 /* if( baseDN ) break; */
797 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
799 /* Process attributes */
800 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
801 attribute = ldap_next_attribute( ld, e, ber ) ) {
802 /* if( baseDN ) break; */
803 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
804 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
805 for( i = 0; vals[i] != NULL; i++ ) {
806 char *ch;
807 /* Strip the 'ldb:' from the front of the value */
808 ch = ( char * ) strchr( vals[i], ':' );
809 if( ch ) {
810 gchar *bn = g_strdup( ++ch );
811 g_strchomp( bn );
812 g_strchug( bn );
813 baseDN = g_list_append( baseDN, g_strdup( bn ) );
817 ldap_value_free( vals );
819 ldap_memfree( attribute );
821 if( ber != NULL ) {
822 ber_free( ber, 0 );
825 ldap_msgfree( result );
828 ldap_unbind( ld );
829 return baseDN;
833 * Attempt to discover the base DN for the server.
834 * Enter: ldapServer Server to test.
835 * Return: List of Base DN's, or NULL if could not read. Base DN should
836 * be g_free() when done. Return code set in ldapServer.
838 GList *syldap_read_basedn( SyldapServer *ldapServer ) {
839 GList *baseDN = NULL;
840 LDAP *ld;
841 gint rc, i;
842 LDAPMessage *result, *e;
843 gchar *attribs[10];
844 BerElement *ber;
845 gchar *attribute;
846 gchar **vals;
847 struct timeval timeout;
849 ldapServer->retVal = MGU_BAD_ARGS;
850 if( ldapServer == NULL ) return baseDN;
851 if( ldapServer->hostName == NULL ) return baseDN;
852 if( ldapServer->port < 1 ) return baseDN;
854 /* Set timeout */
855 timeout.tv_usec = 0L;
856 if( ldapServer->timeOut > 0 ) {
857 timeout.tv_sec = ldapServer->timeOut;
859 else {
860 timeout.tv_sec = 30L;
863 /* Connect to server. */
864 if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
865 ldapServer->retVal = MGU_LDAP_INIT;
866 return baseDN;
869 /* Bind to the server, if required */
870 if( ldapServer->bindDN ) {
871 if( *ldapServer->bindDN != '\0' ) {
872 rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
873 if( rc != LDAP_SUCCESS ) {
874 /* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
875 ldap_unbind( ld );
876 ldapServer->retVal = MGU_LDAP_BIND;
877 return baseDN;
882 ldapServer->retVal = MGU_LDAP_SEARCH;
884 /* Test for LDAP version 3 */
885 attribs[0] = SYLDAP_V3_TEST_ATTR;
886 attribs[1] = NULL;
887 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
888 0, NULL, NULL, &timeout, 0, &result );
889 if( rc == LDAP_SUCCESS ) {
890 /* Process entries */
891 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
892 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
894 /* Process attributes */
895 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
896 attribute = ldap_next_attribute( ld, e, ber ) ) {
897 if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
898 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
899 for( i = 0; vals[i] != NULL; i++ ) {
900 /* printf( "\t%s: %s\n", attribute, vals[i] ); */
901 baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
904 ldap_value_free( vals );
906 ldap_memfree( attribute );
908 if( ber != NULL ) {
909 ber_free( ber, 0 );
912 ldap_msgfree( result );
913 ldapServer->retVal = MGU_SUCCESS;
915 else if( rc == LDAP_TIMEOUT ) {
916 ldapServer->retVal = MGU_LDAP_TIMEOUT;
919 if( baseDN == NULL ) {
920 /* Test for LDAP version 2 */
921 attribs[0] = NULL;
922 rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
923 0, NULL, NULL, &timeout, 0, &result );
924 if( rc == LDAP_SUCCESS ) {
925 /* Process entries */
926 for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
927 /* if( baseDN ) break; */
928 /* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
930 /* Process attributes */
931 for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
932 attribute = ldap_next_attribute( ld, e, ber ) ) {
933 /* if( baseDN ) break; */
934 if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
935 if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
936 for( i = 0; vals[i] != NULL; i++ ) {
937 char *ch;
938 /* Strip the 'ldb:' from the front of the value */
939 ch = ( char * ) strchr( vals[i], ':' );
940 if( ch ) {
941 gchar *bn = g_strdup( ++ch );
942 g_strchomp( bn );
943 g_strchug( bn );
944 baseDN = g_list_append( baseDN, g_strdup( bn ) );
948 ldap_value_free( vals );
950 ldap_memfree( attribute );
952 if( ber != NULL ) {
953 ber_free( ber, 0 );
956 ldap_msgfree( result );
957 ldapServer->retVal = MGU_SUCCESS;
959 else if( rc == LDAP_TIMEOUT ) {
960 ldapServer->retVal = MGU_LDAP_TIMEOUT;
963 ldap_unbind( ld );
965 return baseDN;
969 * Attempt to connect to the server.
970 * Enter:
971 * host Host name
972 * port Port number
973 * Return: TRUE if connected successfully.
975 gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
976 gboolean retVal = FALSE;
977 LDAP *ld;
979 if( host == NULL ) return retVal;
980 if( port < 1 ) return retVal;
981 if( ( ld = ldap_open( host, port ) ) != NULL ) {
982 retVal = TRUE;
984 if( ld != NULL ) {
985 ldap_unbind( ld );
987 return retVal;
991 * Attempt to connect to the server.
992 * Enter: ldapServer Server to test.
993 * Return: TRUE if connected successfully. Return code set in ldapServer.
995 gboolean syldap_test_connect( SyldapServer *ldapServer ) {
996 gboolean retVal = FALSE;
997 LDAP *ld;
999 ldapServer->retVal = MGU_BAD_ARGS;
1000 if( ldapServer == NULL ) return retVal;
1001 if( ldapServer->hostName == NULL ) return retVal;
1002 if( ldapServer->port < 1 ) return retVal;
1003 ldapServer->retVal = MGU_LDAP_INIT;
1004 if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
1005 ldapServer->retVal = MGU_SUCCESS;
1006 retVal = TRUE;
1008 if( ld != NULL ) {
1009 ldap_unbind( ld );
1011 return retVal;
1015 * Test whether LDAP libraries installed.
1016 * Return: TRUE if library available.
1018 gboolean syldap_test_ldap_lib() {
1019 return TRUE;
1022 #endif /* USE_LDAP */
1025 * End of Source.