1054 lines
30 KiB
C
1054 lines
30 KiB
C
/*
|
|
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
|
* Copyright (C) 2001-2002 Match Grun
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* Functions necessary to access LDAP servers.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#ifdef USE_LDAP
|
|
|
|
#include <glib.h>
|
|
#include <sys/time.h>
|
|
#include <string.h>
|
|
#include <ldap.h>
|
|
#include <lber.h>
|
|
#include <pthread.h>
|
|
|
|
#include "mgutils.h"
|
|
#include "addritem.h"
|
|
#include "addrcache.h"
|
|
#include "syldap.h"
|
|
#include "utils.h"
|
|
#include "adbookbase.h"
|
|
|
|
/*
|
|
* Create new LDAP server interface object.
|
|
*/
|
|
SyldapServer *syldap_create() {
|
|
SyldapServer *ldapServer;
|
|
|
|
debug_print("Creating LDAP server interface object\n");
|
|
|
|
ldapServer = g_new0( SyldapServer, 1 );
|
|
ldapServer->type = ADBOOKTYPE_LDAP;
|
|
ldapServer->addressCache = addrcache_create();
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
ldapServer->hostName = NULL;
|
|
ldapServer->port = SYLDAP_DFL_PORT;
|
|
ldapServer->baseDN = NULL;
|
|
ldapServer->bindDN = NULL;
|
|
ldapServer->bindPass = NULL;
|
|
ldapServer->searchCriteria = NULL;
|
|
ldapServer->searchValue = NULL;
|
|
ldapServer->entriesRead = 0;
|
|
ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
|
|
ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
|
|
ldapServer->newSearch = TRUE;
|
|
ldapServer->thread = NULL;
|
|
ldapServer->busyFlag = FALSE;
|
|
ldapServer->callBack = NULL;
|
|
ldapServer->idleId = 0;
|
|
return ldapServer;
|
|
}
|
|
|
|
/*
|
|
* Specify name to be used.
|
|
*/
|
|
void syldap_set_name( SyldapServer* ldapServer, const gchar *value ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
addrcache_set_name( ldapServer->addressCache, value );
|
|
}
|
|
|
|
/*
|
|
* Specify hostname to be used.
|
|
*/
|
|
void syldap_set_host( SyldapServer* ldapServer, const gchar *value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->hostName = mgu_replace_string( ldapServer->hostName, value );
|
|
g_strstrip( ldapServer->hostName );
|
|
}
|
|
|
|
/*
|
|
* Specify port to be used.
|
|
*/
|
|
void syldap_set_port( SyldapServer* ldapServer, const gint value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
if( value > 0 ) {
|
|
ldapServer->port = value;
|
|
}
|
|
else {
|
|
ldapServer->port = SYLDAP_DFL_PORT;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Specify base DN to be used.
|
|
*/
|
|
void syldap_set_base_dn( SyldapServer* ldapServer, const gchar *value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->baseDN = mgu_replace_string( ldapServer->baseDN, value );
|
|
g_strstrip( ldapServer->baseDN );
|
|
}
|
|
|
|
/*
|
|
* Specify bind DN to be used.
|
|
*/
|
|
void syldap_set_bind_dn( SyldapServer* ldapServer, const gchar *value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->bindDN = mgu_replace_string( ldapServer->bindDN, value );
|
|
g_strstrip( ldapServer->bindDN );
|
|
}
|
|
|
|
/*
|
|
* Specify bind password to be used.
|
|
*/
|
|
void syldap_set_bind_password( SyldapServer* ldapServer, const gchar *value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->bindPass = mgu_replace_string( ldapServer->bindPass, value );
|
|
g_strstrip( ldapServer->bindPass );
|
|
}
|
|
|
|
/*
|
|
* Specify search criteria to be used.
|
|
*/
|
|
void syldap_set_search_criteria( SyldapServer* ldapServer, const gchar *value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->searchCriteria = mgu_replace_string( ldapServer->searchCriteria, value );
|
|
g_strstrip( ldapServer->searchCriteria );
|
|
ldapServer->newSearch = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Specify search value to be searched for.
|
|
*/
|
|
void syldap_set_search_value( SyldapServer* ldapServer, const gchar *value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->searchValue = mgu_replace_string( ldapServer->searchValue, value );
|
|
g_strstrip( ldapServer->searchValue );
|
|
ldapServer->newSearch = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Specify maximum number of entries to retrieve.
|
|
*/
|
|
void syldap_set_max_entries( SyldapServer* ldapServer, const gint value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
if( value > 0 ) {
|
|
ldapServer->maxEntries = value;
|
|
}
|
|
else {
|
|
ldapServer->maxEntries = SYLDAP_MAX_ENTRIES;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Specify timeout value for LDAP operation (in seconds).
|
|
*/
|
|
void syldap_set_timeout( SyldapServer* ldapServer, const gint value ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
if( value > 0 ) {
|
|
ldapServer->timeOut = value;
|
|
}
|
|
else {
|
|
ldapServer->timeOut = SYLDAP_DFL_TIMEOUT;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Register a callback function. When called, the function will be passed
|
|
* this object as an argument.
|
|
*/
|
|
void syldap_set_callback( SyldapServer *ldapServer, void *func ) {
|
|
ldapServer->callBack = func;
|
|
}
|
|
|
|
/*
|
|
* Refresh internal variables to force a file read.
|
|
*/
|
|
void syldap_force_refresh( SyldapServer *ldapServer ) {
|
|
addrcache_refresh( ldapServer->addressCache );
|
|
ldapServer->newSearch = TRUE;
|
|
}
|
|
|
|
gint syldap_get_status( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, -1 );
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
ItemFolder *syldap_get_root_folder( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, NULL );
|
|
return addrcache_get_root_folder( ldapServer->addressCache );
|
|
}
|
|
|
|
gchar *syldap_get_name( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, NULL );
|
|
return addrcache_get_name( ldapServer->addressCache );
|
|
}
|
|
|
|
gboolean syldap_get_accessed( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, FALSE );
|
|
return ldapServer->addressCache->accessFlag;
|
|
}
|
|
|
|
void syldap_set_accessed( SyldapServer *ldapServer, const gboolean value ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
ldapServer->addressCache->accessFlag = value;
|
|
}
|
|
|
|
gboolean syldap_get_modified( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, FALSE );
|
|
return ldapServer->addressCache->modified;
|
|
}
|
|
|
|
void syldap_set_modified( SyldapServer *ldapServer, const gboolean value ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
ldapServer->addressCache->modified = value;
|
|
}
|
|
|
|
/*
|
|
* Free up LDAP server interface object by releasing internal memory.
|
|
*/
|
|
void syldap_free( SyldapServer *ldapServer ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
|
|
debug_print("Freeing LDAP server interface object\n");
|
|
|
|
ldapServer->callBack = NULL;
|
|
|
|
/* Clear cache */
|
|
addrcache_clear( ldapServer->addressCache );
|
|
addrcache_free( ldapServer->addressCache );
|
|
|
|
/* Free internal stuff */
|
|
g_free( ldapServer->hostName );
|
|
g_free( ldapServer->baseDN );
|
|
g_free( ldapServer->bindDN );
|
|
g_free( ldapServer->bindPass );
|
|
g_free( ldapServer->searchCriteria );
|
|
g_free( ldapServer->searchValue );
|
|
g_free( ldapServer->thread );
|
|
|
|
|
|
/* Clear pointers */
|
|
ldapServer->hostName = NULL;
|
|
ldapServer->port = 0;
|
|
ldapServer->baseDN = NULL;
|
|
ldapServer->bindDN = NULL;
|
|
ldapServer->bindPass = NULL;
|
|
ldapServer->searchCriteria = NULL;
|
|
ldapServer->searchValue = NULL;
|
|
ldapServer->entriesRead = 0;
|
|
ldapServer->maxEntries = 0;
|
|
ldapServer->timeOut = 0;
|
|
ldapServer->newSearch = FALSE;
|
|
ldapServer->thread = NULL;
|
|
ldapServer->busyFlag = FALSE;
|
|
ldapServer->callBack = NULL;
|
|
ldapServer->idleId = 0;
|
|
|
|
ldapServer->type = ADBOOKTYPE_NONE;
|
|
ldapServer->addressCache = NULL;
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
|
|
/* Now release LDAP object */
|
|
g_free( ldapServer );
|
|
}
|
|
|
|
/*
|
|
* Display object to specified stream.
|
|
*/
|
|
void syldap_print_data( SyldapServer *ldapServer, FILE *stream ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
|
|
fprintf( stream, "SyldapServer:\n" );
|
|
fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
|
|
fprintf( stream, " port: %d\n", ldapServer->port );
|
|
fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
|
|
fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
|
|
fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
|
|
fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
|
|
fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
|
|
fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
|
|
fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
|
|
fprintf( stream, " ret val: %d\n", ldapServer->retVal );
|
|
addrcache_print( ldapServer->addressCache, stream );
|
|
addritem_print_item_folder( ldapServer->addressCache->rootFolder, stream );
|
|
}
|
|
|
|
/*
|
|
* Display object to specified stream.
|
|
*/
|
|
void syldap_print_short( SyldapServer *ldapServer, FILE *stream ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
|
|
fprintf( stream, "SyldapServer:\n" );
|
|
fprintf( stream, "host name: '%s'\n", ldapServer->hostName );
|
|
fprintf( stream, " port: %d\n", ldapServer->port );
|
|
fprintf( stream, " base dn: '%s'\n", ldapServer->baseDN );
|
|
fprintf( stream, " bind dn: '%s'\n", ldapServer->bindDN );
|
|
fprintf( stream, "bind pass: '%s'\n", ldapServer->bindPass );
|
|
fprintf( stream, " criteria: '%s'\n", ldapServer->searchCriteria );
|
|
fprintf( stream, "searchval: '%s'\n", ldapServer->searchValue );
|
|
fprintf( stream, "max entry: %d\n", ldapServer->maxEntries );
|
|
fprintf( stream, " num read: %d\n", ldapServer->entriesRead );
|
|
fprintf( stream, " ret val: %d\n", ldapServer->retVal );
|
|
}
|
|
|
|
/*
|
|
* Build an address list entry and append to list of address items. Name is formatted
|
|
* as it appears in the common name (cn) attribute.
|
|
*/
|
|
static void syldap_build_items_cn( SyldapServer *ldapServer, GSList *listName, GSList *listAddr ) {
|
|
ItemPerson *person;
|
|
ItemEMail *email;
|
|
GSList *nodeName = listName;
|
|
|
|
while( nodeName ) {
|
|
GSList *nodeAddress = listAddr;
|
|
person = addritem_create_item_person();
|
|
addritem_person_set_common_name( person, nodeName->data );
|
|
addrcache_id_person( ldapServer->addressCache, person );
|
|
addrcache_add_person( ldapServer->addressCache, person );
|
|
|
|
while( nodeAddress ) {
|
|
email = addritem_create_item_email();
|
|
addritem_email_set_address( email, nodeAddress->data );
|
|
addrcache_id_email( ldapServer->addressCache, email );
|
|
addrcache_person_add_email( ldapServer->addressCache, person, email );
|
|
nodeAddress = g_slist_next( nodeAddress );
|
|
ldapServer->entriesRead++;
|
|
}
|
|
nodeName = g_slist_next( nodeName );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Build an address list entry and append to list of address items. Name is formatted
|
|
* as "<first-name> <last-name>".
|
|
*/
|
|
static void syldap_build_items_fl( SyldapServer *ldapServer, GSList *listAddr, GSList *listFirst, GSList *listLast ) {
|
|
GSList *nodeFirst = listFirst;
|
|
GSList *nodeAddress = listAddr;
|
|
gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
|
|
gint iLen = 0, iLenT = 0;
|
|
ItemPerson *person;
|
|
ItemEMail *email;
|
|
|
|
/* Find longest first name in list */
|
|
while( nodeFirst ) {
|
|
if( firstName == NULL ) {
|
|
firstName = nodeFirst->data;
|
|
iLen = strlen( firstName );
|
|
}
|
|
else {
|
|
if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
|
|
firstName = nodeFirst->data;
|
|
iLen = iLenT;
|
|
}
|
|
}
|
|
nodeFirst = g_slist_next( nodeFirst );
|
|
}
|
|
|
|
/* Format name */
|
|
if( listLast ) {
|
|
lastName = listLast->data;
|
|
}
|
|
|
|
if( firstName ) {
|
|
if( lastName ) {
|
|
fullName = g_strdup_printf( "%s %s", firstName, lastName );
|
|
}
|
|
else {
|
|
fullName = g_strdup_printf( "%s", firstName );
|
|
}
|
|
}
|
|
else {
|
|
if( lastName ) {
|
|
fullName = g_strdup_printf( "%s", lastName );
|
|
}
|
|
}
|
|
if( fullName ) {
|
|
g_strchug( fullName ); g_strchomp( fullName );
|
|
}
|
|
|
|
if( nodeAddress ) {
|
|
person = addritem_create_item_person();
|
|
addritem_person_set_common_name( person, fullName );
|
|
addritem_person_set_first_name( person, firstName );
|
|
addritem_person_set_last_name( person, lastName );
|
|
addrcache_id_person( ldapServer->addressCache, person );
|
|
addrcache_add_person( ldapServer->addressCache, person );
|
|
}
|
|
|
|
/* Add address item */
|
|
while( nodeAddress ) {
|
|
email = addritem_create_item_email();
|
|
addritem_email_set_address( email, nodeAddress->data );
|
|
addrcache_id_email( ldapServer->addressCache, email );
|
|
addrcache_person_add_email( ldapServer->addressCache, person, email );
|
|
nodeAddress = g_slist_next( nodeAddress );
|
|
ldapServer->entriesRead++;
|
|
}
|
|
g_free( fullName );
|
|
fullName = firstName = lastName = NULL;
|
|
|
|
}
|
|
|
|
/*
|
|
* Add all attribute values to a list.
|
|
*/
|
|
static GSList *syldap_add_list_values( LDAP *ld, LDAPMessage *entry, char *attr ) {
|
|
GSList *list = NULL;
|
|
gint i;
|
|
gchar **vals;
|
|
|
|
if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
|
|
for( i = 0; vals[i] != NULL; i++ ) {
|
|
/* printf( "lv\t%s: %s\n", attr, vals[i] ); */
|
|
list = g_slist_append( list, g_strdup( vals[i] ) );
|
|
}
|
|
}
|
|
ldap_value_free( vals );
|
|
return list;
|
|
}
|
|
|
|
/*
|
|
* Add a single attribute value to a list.
|
|
*/
|
|
static GSList *syldap_add_single_value( LDAP *ld, LDAPMessage *entry, char *attr ) {
|
|
GSList *list = NULL;
|
|
gchar **vals;
|
|
|
|
if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
|
|
if( vals[0] != NULL ) {
|
|
/* printf( "sv\t%s: %s\n", attr, vals[0] ); */
|
|
list = g_slist_append( list, g_strdup( vals[0] ) );
|
|
}
|
|
}
|
|
ldap_value_free( vals );
|
|
return list;
|
|
}
|
|
|
|
/*
|
|
* Free linked lists of character strings.
|
|
*/
|
|
static void syldap_free_lists( GSList *listName, GSList *listAddr, GSList *listID, GSList *listDN, GSList *listFirst, GSList *listLast ) {
|
|
mgu_free_list( listName );
|
|
mgu_free_list( listAddr );
|
|
mgu_free_list( listID );
|
|
mgu_free_list( listDN );
|
|
mgu_free_list( listFirst );
|
|
mgu_free_list( listLast );
|
|
}
|
|
|
|
/*
|
|
* Check parameters that are required for a search. This should
|
|
* be called before performing a search.
|
|
* Return: TRUE if search criteria appear OK.
|
|
*/
|
|
gboolean syldap_check_search( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, FALSE );
|
|
|
|
ldapServer->retVal = MGU_LDAP_CRITERIA;
|
|
|
|
/* Test search criteria */
|
|
if( ldapServer->searchCriteria == NULL ) {
|
|
return FALSE;
|
|
}
|
|
if( strlen( ldapServer->searchCriteria ) < 1 ) {
|
|
return FALSE;
|
|
}
|
|
|
|
if( ldapServer->searchValue == NULL ) {
|
|
return FALSE;
|
|
}
|
|
if( strlen( ldapServer->searchValue ) < 1 ) {
|
|
return FALSE;
|
|
}
|
|
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Perform the LDAP search, reading LDAP entries into cache.
|
|
* Note that one LDAP entry can have multiple values for many of its
|
|
* attributes. If these attributes are E-Mail addresses; these are
|
|
* broken out into separate address items. For any other attribute,
|
|
* only the first occurrence is read.
|
|
*/
|
|
gint syldap_search( SyldapServer *ldapServer ) {
|
|
LDAP *ld;
|
|
LDAPMessage *result, *e;
|
|
char *attribs[10];
|
|
char *attribute;
|
|
gchar *criteria;
|
|
BerElement *ber;
|
|
gint rc;
|
|
GSList *listName = NULL, *listAddress = NULL, *listID = NULL;
|
|
GSList *listFirst = NULL, *listLast = NULL, *listDN = NULL;
|
|
struct timeval timeout;
|
|
gboolean entriesFound = FALSE;
|
|
|
|
g_return_val_if_fail( ldapServer != NULL, -1 );
|
|
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
if( ! syldap_check_search( ldapServer ) ) {
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
/* Set timeout */
|
|
timeout.tv_sec = ldapServer->timeOut;
|
|
timeout.tv_usec = 0L;
|
|
|
|
ldapServer->entriesRead = 0;
|
|
if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
|
|
ldapServer->retVal = MGU_LDAP_INIT;
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
/* printf( "connected to LDAP host %s on port %d\n", ldapServer->hostName, ldapServer->port ); */
|
|
|
|
/* Bind to the server, if required */
|
|
if( ldapServer->bindDN ) {
|
|
if( * ldapServer->bindDN != '\0' ) {
|
|
/* printf( "binding...\n" ); */
|
|
rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
|
|
/* printf( "rc=%d\n", rc ); */
|
|
if( rc != LDAP_SUCCESS ) {
|
|
/* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
|
|
ldap_unbind( ld );
|
|
ldapServer->retVal = MGU_LDAP_BIND;
|
|
return ldapServer->retVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Define all attributes we are interested in. */
|
|
attribs[0] = SYLDAP_ATTR_DN;
|
|
attribs[1] = SYLDAP_ATTR_COMMONNAME;
|
|
attribs[2] = SYLDAP_ATTR_GIVENNAME;
|
|
attribs[3] = SYLDAP_ATTR_SURNAME;
|
|
attribs[4] = SYLDAP_ATTR_EMAIL;
|
|
attribs[5] = SYLDAP_ATTR_UID;
|
|
attribs[6] = NULL;
|
|
|
|
/* Create LDAP search string and apply search criteria */
|
|
criteria = g_strdup_printf( ldapServer->searchCriteria, ldapServer->searchValue );
|
|
rc = ldap_search_ext_s( ld, ldapServer->baseDN, LDAP_SCOPE_SUBTREE, criteria, attribs, 0, NULL, NULL,
|
|
&timeout, 0, &result );
|
|
g_free( criteria );
|
|
criteria = NULL;
|
|
if( rc == LDAP_TIMEOUT ) {
|
|
ldap_unbind( ld );
|
|
ldapServer->retVal = MGU_LDAP_TIMEOUT;
|
|
return ldapServer->retVal;
|
|
}
|
|
if( rc != LDAP_SUCCESS ) {
|
|
/* printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) ); */
|
|
ldap_unbind( ld );
|
|
ldapServer->retVal = MGU_LDAP_SEARCH;
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
/* printf( "Total results are: %d\n", ldap_count_entries( ld, result ) ); */
|
|
|
|
/* Clear the cache if we have new entries, otherwise leave untouched. */
|
|
if( ldap_count_entries( ld, result ) > 0 ) {
|
|
addrcache_clear( ldapServer->addressCache );
|
|
}
|
|
|
|
/* Process results */
|
|
ldapServer->entriesRead = 0;
|
|
for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
|
|
entriesFound = TRUE;
|
|
if( ldapServer->entriesRead >= ldapServer->maxEntries ) break;
|
|
/* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
|
|
|
|
/* Process all attributes */
|
|
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
|
|
attribute = ldap_next_attribute( ld, e, ber ) ) {
|
|
if( strcasecmp( attribute, SYLDAP_ATTR_COMMONNAME ) == 0 ) {
|
|
listName = syldap_add_list_values( ld, e, attribute );
|
|
}
|
|
if( strcasecmp( attribute, SYLDAP_ATTR_EMAIL ) == 0 ) {
|
|
listAddress = syldap_add_list_values( ld, e, attribute );
|
|
}
|
|
if( strcasecmp( attribute, SYLDAP_ATTR_UID ) == 0 ) {
|
|
listID = syldap_add_single_value( ld, e, attribute );
|
|
}
|
|
if( strcasecmp( attribute, SYLDAP_ATTR_GIVENNAME ) == 0 ) {
|
|
listFirst = syldap_add_list_values( ld, e, attribute );
|
|
}
|
|
if( strcasecmp( attribute, SYLDAP_ATTR_SURNAME ) == 0 ) {
|
|
listLast = syldap_add_single_value( ld, e, attribute );
|
|
}
|
|
if( strcasecmp( attribute, SYLDAP_ATTR_DN ) == 0 ) {
|
|
listDN = syldap_add_single_value( ld, e, attribute );
|
|
}
|
|
|
|
/* Free memory used to store attribute */
|
|
ldap_memfree( attribute );
|
|
}
|
|
|
|
/* Format and add items to cache */
|
|
syldap_build_items_fl( ldapServer, listAddress, listFirst, listLast );
|
|
|
|
/* Free up */
|
|
syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
|
|
listName = listAddress = listID = listFirst = listLast = listDN = NULL;
|
|
|
|
if( ber != NULL ) {
|
|
ber_free( ber, 0 );
|
|
}
|
|
}
|
|
|
|
syldap_free_lists( listName, listAddress, listID, listDN, listFirst, listLast );
|
|
listName = listAddress = listID = listFirst = listLast = listDN = NULL;
|
|
|
|
/* Free up and disconnect */
|
|
ldap_msgfree( result );
|
|
ldap_unbind( ld );
|
|
ldapServer->newSearch = FALSE;
|
|
if( entriesFound ) {
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
}
|
|
else {
|
|
ldapServer->retVal = MGU_LDAP_NOENTRIES;
|
|
}
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
/* ============================================================================================ */
|
|
/*
|
|
* Read data into list. Main entry point
|
|
* Return: TRUE if file read successfully.
|
|
*/
|
|
/* ============================================================================================ */
|
|
gint syldap_read_data( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, -1 );
|
|
|
|
ldapServer->addressCache->accessFlag = FALSE;
|
|
pthread_detach( pthread_self() );
|
|
if( ldapServer->newSearch ) {
|
|
/* Read data into the list */
|
|
syldap_search( ldapServer );
|
|
|
|
/* Mark cache */
|
|
ldapServer->addressCache->modified = FALSE;
|
|
ldapServer->addressCache->dataRead = TRUE;
|
|
ldapServer->addressCache->accessFlag = FALSE;
|
|
}
|
|
ldapServer->busyFlag = FALSE;
|
|
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
/* ============================================================================================ */
|
|
/*
|
|
* Cancel read with thread.
|
|
*/
|
|
/* ============================================================================================ */
|
|
void syldap_cancel_read( SyldapServer *ldapServer ) {
|
|
g_return_if_fail( ldapServer != NULL );
|
|
|
|
if( ldapServer->thread ) {
|
|
/* printf( "thread cancelled\n" ); */
|
|
pthread_cancel( *ldapServer->thread );
|
|
g_free(ldapServer->thread);
|
|
}
|
|
ldapServer->thread = NULL;
|
|
ldapServer->busyFlag = FALSE;
|
|
}
|
|
|
|
/* ============================================================================================ */
|
|
/*
|
|
* Read data into list using a background thread.
|
|
* Return: TRUE if file read successfully. Callback function will be
|
|
* notified when search is complete.
|
|
*/
|
|
/* ============================================================================================ */
|
|
gint syldap_read_data_th( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, -1 );
|
|
|
|
ldapServer->busyFlag = FALSE;
|
|
syldap_check_search( ldapServer );
|
|
if( ldapServer->retVal == MGU_SUCCESS ) {
|
|
/* debug_print("Starting LDAP read thread\n"); */
|
|
|
|
ldapServer->busyFlag = TRUE;
|
|
ldapServer->thread = g_new0(pthread_t, 1);
|
|
pthread_create(
|
|
ldapServer->thread, NULL, (void *) syldap_read_data,
|
|
(void *) ldapServer );
|
|
}
|
|
return ldapServer->retVal;
|
|
}
|
|
|
|
/*
|
|
* Return link list of persons.
|
|
*/
|
|
GList *syldap_get_list_person( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, NULL );
|
|
return addrcache_get_list_person( ldapServer->addressCache );
|
|
}
|
|
|
|
/*
|
|
* Return link list of folders. This is always NULL since there are
|
|
* no folders in GnomeCard.
|
|
* Return: NULL.
|
|
*/
|
|
GList *syldap_get_list_folder( SyldapServer *ldapServer ) {
|
|
g_return_val_if_fail( ldapServer != NULL, NULL );
|
|
return NULL;
|
|
}
|
|
|
|
#define SYLDAP_TEST_FILTER "(objectclass=*)"
|
|
#define SYLDAP_SEARCHBASE_V2 "cn=config"
|
|
#define SYLDAP_SEARCHBASE_V3 ""
|
|
#define SYLDAP_V2_TEST_ATTR "database"
|
|
#define SYLDAP_V3_TEST_ATTR "namingcontexts"
|
|
|
|
/*
|
|
* Attempt to discover the base DN for the server.
|
|
* Enter:
|
|
* host Host name
|
|
* port Port number
|
|
* bindDN Bind DN (optional).
|
|
* bindPW Bind PW (optional).
|
|
* tov Timeout value (seconds), or 0 for none, default 30 secs.
|
|
* Return: List of Base DN's, or NULL if could not read. Base DN should
|
|
* be g_free() when done.
|
|
*/
|
|
GList *syldap_read_basedn_s( const gchar *host, const gint port, const gchar *bindDN, const gchar *bindPW, const gint tov ) {
|
|
GList *baseDN = NULL;
|
|
LDAP *ld;
|
|
gint rc, i;
|
|
LDAPMessage *result, *e;
|
|
gchar *attribs[10];
|
|
BerElement *ber;
|
|
gchar *attribute;
|
|
gchar **vals;
|
|
struct timeval timeout;
|
|
|
|
if( host == NULL ) return baseDN;
|
|
if( port < 1 ) return baseDN;
|
|
|
|
/* Set timeout */
|
|
timeout.tv_usec = 0L;
|
|
if( tov > 0 ) {
|
|
timeout.tv_sec = tov;
|
|
}
|
|
else {
|
|
timeout.tv_sec = 30L;
|
|
}
|
|
|
|
/* Connect to server. */
|
|
if( ( ld = ldap_init( host, port ) ) == NULL ) {
|
|
return baseDN;
|
|
}
|
|
|
|
/* Bind to the server, if required */
|
|
if( bindDN ) {
|
|
if( *bindDN != '\0' ) {
|
|
rc = ldap_simple_bind_s( ld, bindDN, bindPW );
|
|
if( rc != LDAP_SUCCESS ) {
|
|
/* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
|
|
ldap_unbind( ld );
|
|
return baseDN;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Test for LDAP version 3 */
|
|
attribs[0] = SYLDAP_V3_TEST_ATTR;
|
|
attribs[1] = NULL;
|
|
rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
|
|
0, NULL, NULL, &timeout, 0, &result );
|
|
if( rc == LDAP_SUCCESS ) {
|
|
/* Process entries */
|
|
for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
|
|
/* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
|
|
|
|
/* Process attributes */
|
|
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
|
|
attribute = ldap_next_attribute( ld, e, ber ) ) {
|
|
if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
|
|
if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
|
|
for( i = 0; vals[i] != NULL; i++ ) {
|
|
/* printf( "\t%s: %s\n", attribute, vals[i] ); */
|
|
baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
|
|
}
|
|
}
|
|
ldap_value_free( vals );
|
|
}
|
|
ldap_memfree( attribute );
|
|
}
|
|
if( ber != NULL ) {
|
|
ber_free( ber, 0 );
|
|
}
|
|
}
|
|
ldap_msgfree( result );
|
|
}
|
|
else {
|
|
}
|
|
|
|
if( baseDN == NULL ) {
|
|
/* Test for LDAP version 2 */
|
|
attribs[0] = NULL;
|
|
rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
|
|
0, NULL, NULL, &timeout, 0, &result );
|
|
if( rc == LDAP_SUCCESS ) {
|
|
/* Process entries */
|
|
for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
|
|
/* if( baseDN ) break; */
|
|
/* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
|
|
|
|
/* Process attributes */
|
|
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
|
|
attribute = ldap_next_attribute( ld, e, ber ) ) {
|
|
/* if( baseDN ) break; */
|
|
if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
|
|
if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
|
|
for( i = 0; vals[i] != NULL; i++ ) {
|
|
char *ch;
|
|
/* Strip the 'ldb:' from the front of the value */
|
|
ch = ( char * ) strchr( vals[i], ':' );
|
|
if( ch ) {
|
|
gchar *bn = g_strdup( ++ch );
|
|
g_strchomp( bn );
|
|
g_strchug( bn );
|
|
baseDN = g_list_append( baseDN, g_strdup( bn ) );
|
|
}
|
|
}
|
|
}
|
|
ldap_value_free( vals );
|
|
}
|
|
ldap_memfree( attribute );
|
|
}
|
|
if( ber != NULL ) {
|
|
ber_free( ber, 0 );
|
|
}
|
|
}
|
|
ldap_msgfree( result );
|
|
}
|
|
}
|
|
ldap_unbind( ld );
|
|
return baseDN;
|
|
}
|
|
|
|
/*
|
|
* Attempt to discover the base DN for the server.
|
|
* Enter: ldapServer Server to test.
|
|
* Return: List of Base DN's, or NULL if could not read. Base DN should
|
|
* be g_free() when done. Return code set in ldapServer.
|
|
*/
|
|
GList *syldap_read_basedn( SyldapServer *ldapServer ) {
|
|
GList *baseDN = NULL;
|
|
LDAP *ld;
|
|
gint rc, i;
|
|
LDAPMessage *result, *e;
|
|
gchar *attribs[10];
|
|
BerElement *ber;
|
|
gchar *attribute;
|
|
gchar **vals;
|
|
struct timeval timeout;
|
|
|
|
ldapServer->retVal = MGU_BAD_ARGS;
|
|
if( ldapServer == NULL ) return baseDN;
|
|
if( ldapServer->hostName == NULL ) return baseDN;
|
|
if( ldapServer->port < 1 ) return baseDN;
|
|
|
|
/* Set timeout */
|
|
timeout.tv_usec = 0L;
|
|
if( ldapServer->timeOut > 0 ) {
|
|
timeout.tv_sec = ldapServer->timeOut;
|
|
}
|
|
else {
|
|
timeout.tv_sec = 30L;
|
|
}
|
|
|
|
/* Connect to server. */
|
|
if( ( ld = ldap_init( ldapServer->hostName, ldapServer->port ) ) == NULL ) {
|
|
ldapServer->retVal = MGU_LDAP_INIT;
|
|
return baseDN;
|
|
}
|
|
|
|
/* Bind to the server, if required */
|
|
if( ldapServer->bindDN ) {
|
|
if( *ldapServer->bindDN != '\0' ) {
|
|
rc = ldap_simple_bind_s( ld, ldapServer->bindDN, ldapServer->bindPass );
|
|
if( rc != LDAP_SUCCESS ) {
|
|
/* printf( "LDAP Error: ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); */
|
|
ldap_unbind( ld );
|
|
ldapServer->retVal = MGU_LDAP_BIND;
|
|
return baseDN;
|
|
}
|
|
}
|
|
}
|
|
|
|
ldapServer->retVal = MGU_LDAP_SEARCH;
|
|
|
|
/* Test for LDAP version 3 */
|
|
attribs[0] = SYLDAP_V3_TEST_ATTR;
|
|
attribs[1] = NULL;
|
|
rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V3, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
|
|
0, NULL, NULL, &timeout, 0, &result );
|
|
if( rc == LDAP_SUCCESS ) {
|
|
/* Process entries */
|
|
for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
|
|
/* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
|
|
|
|
/* Process attributes */
|
|
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
|
|
attribute = ldap_next_attribute( ld, e, ber ) ) {
|
|
if( strcasecmp( attribute, SYLDAP_V3_TEST_ATTR ) == 0 ) {
|
|
if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
|
|
for( i = 0; vals[i] != NULL; i++ ) {
|
|
/* printf( "\t%s: %s\n", attribute, vals[i] ); */
|
|
baseDN = g_list_append( baseDN, g_strdup( vals[i] ) );
|
|
}
|
|
}
|
|
ldap_value_free( vals );
|
|
}
|
|
ldap_memfree( attribute );
|
|
}
|
|
if( ber != NULL ) {
|
|
ber_free( ber, 0 );
|
|
}
|
|
}
|
|
ldap_msgfree( result );
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
}
|
|
else if( rc == LDAP_TIMEOUT ) {
|
|
ldapServer->retVal = MGU_LDAP_TIMEOUT;
|
|
}
|
|
|
|
if( baseDN == NULL ) {
|
|
/* Test for LDAP version 2 */
|
|
attribs[0] = NULL;
|
|
rc = ldap_search_ext_s( ld, SYLDAP_SEARCHBASE_V2, LDAP_SCOPE_BASE, SYLDAP_TEST_FILTER, attribs,
|
|
0, NULL, NULL, &timeout, 0, &result );
|
|
if( rc == LDAP_SUCCESS ) {
|
|
/* Process entries */
|
|
for( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) {
|
|
/* if( baseDN ) break; */
|
|
/* printf( "DN: %s\n", ldap_get_dn( ld, e ) ); */
|
|
|
|
/* Process attributes */
|
|
for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
|
|
attribute = ldap_next_attribute( ld, e, ber ) ) {
|
|
/* if( baseDN ) break; */
|
|
if( strcasecmp( attribute, SYLDAP_V2_TEST_ATTR ) == 0 ) {
|
|
if( ( vals = ldap_get_values( ld, e, attribute ) ) != NULL ) {
|
|
for( i = 0; vals[i] != NULL; i++ ) {
|
|
char *ch;
|
|
/* Strip the 'ldb:' from the front of the value */
|
|
ch = ( char * ) strchr( vals[i], ':' );
|
|
if( ch ) {
|
|
gchar *bn = g_strdup( ++ch );
|
|
g_strchomp( bn );
|
|
g_strchug( bn );
|
|
baseDN = g_list_append( baseDN, g_strdup( bn ) );
|
|
}
|
|
}
|
|
}
|
|
ldap_value_free( vals );
|
|
}
|
|
ldap_memfree( attribute );
|
|
}
|
|
if( ber != NULL ) {
|
|
ber_free( ber, 0 );
|
|
}
|
|
}
|
|
ldap_msgfree( result );
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
}
|
|
else if( rc == LDAP_TIMEOUT ) {
|
|
ldapServer->retVal = MGU_LDAP_TIMEOUT;
|
|
}
|
|
}
|
|
ldap_unbind( ld );
|
|
|
|
return baseDN;
|
|
}
|
|
|
|
/*
|
|
* Attempt to connect to the server.
|
|
* Enter:
|
|
* host Host name
|
|
* port Port number
|
|
* Return: TRUE if connected successfully.
|
|
*/
|
|
gboolean syldap_test_connect_s( const gchar *host, const gint port ) {
|
|
gboolean retVal = FALSE;
|
|
LDAP *ld;
|
|
|
|
if( host == NULL ) return retVal;
|
|
if( port < 1 ) return retVal;
|
|
if( ( ld = ldap_open( host, port ) ) != NULL ) {
|
|
retVal = TRUE;
|
|
}
|
|
if( ld != NULL ) {
|
|
ldap_unbind( ld );
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
/*
|
|
* Attempt to connect to the server.
|
|
* Enter: ldapServer Server to test.
|
|
* Return: TRUE if connected successfully. Return code set in ldapServer.
|
|
*/
|
|
gboolean syldap_test_connect( SyldapServer *ldapServer ) {
|
|
gboolean retVal = FALSE;
|
|
LDAP *ld;
|
|
|
|
ldapServer->retVal = MGU_BAD_ARGS;
|
|
if( ldapServer == NULL ) return retVal;
|
|
if( ldapServer->hostName == NULL ) return retVal;
|
|
if( ldapServer->port < 1 ) return retVal;
|
|
ldapServer->retVal = MGU_LDAP_INIT;
|
|
if( ( ld = ldap_open( ldapServer->hostName, ldapServer->port ) ) != NULL ) {
|
|
ldapServer->retVal = MGU_SUCCESS;
|
|
retVal = TRUE;
|
|
}
|
|
if( ld != NULL ) {
|
|
ldap_unbind( ld );
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
/*
|
|
* Test whether LDAP libraries installed.
|
|
* Return: TRUE if library available.
|
|
*/
|
|
gboolean syldap_test_ldap_lib() {
|
|
return TRUE;
|
|
}
|
|
|
|
#endif /* USE_LDAP */
|
|
|
|
/*
|
|
* End of Source.
|
|
*/
|