Progress commit...

This commit is contained in:
Guillaume BIENKOWSKI 2013-11-28 16:58:15 +01:00
parent 006ba8be2e
commit f5c9d60d88

View file

@ -19,12 +19,6 @@
#include "lpconfig.h"
#include <ldap.h>
struct _LinphoneLDAPContactSearch
{
LDAP *ld;
int msgid;
char* filter;
};
#define MAX_RUNNING_REQUESTS 10
#define FILTER_MAX_SIZE 512
@ -33,18 +27,27 @@ typedef struct {
LinphoneLDAPContactSearch* request;
} LDAPRequestEntry;
typedef enum {
ANONYMOUS,
PLAIN,
SASL
} LDAPAuthMethod;
struct _LinphoneLDAPContactProvider
{
LDAP* ld;
//LDAPRequestEntry requests[MAX_RUNNING_REQUESTS];
LDAP* ld;
MSList* requests;
int req_count;
uint req_count;
// bind transaction
uint bind_msgid;
// config
int use_tls;
char* auth_method;
LDAPAuthMethod auth_method;
char* username;
char* password;
char* server;
char* base_object;
char** attributes;
@ -54,6 +57,14 @@ struct _LinphoneLDAPContactProvider
int max_results;
};
struct _LinphoneLDAPContactSearch
{
LDAP *ld;
int msgid;
char* filter;
};
/* *************************
* LinphoneLDAPContactSearch
* *************************/
@ -62,20 +73,38 @@ LinphoneLDAPContactSearch*linphone_ldap_contact_search_create(LinphoneLDAPContac
{
LinphoneLDAPContactSearch* search = belle_sip_object_new(LinphoneLDAPContactSearch);
LinphoneContactSearch* base = LINPHONE_CONTACT_SEARCH(search);
struct timeval timeout = { cp->timeout, 0 };
linphone_contact_search_init(base, predicate, cb, cb_data);
search->ld = cp->ld;
search->ld = cp->ld;
search->filter = ms_malloc(FILTER_MAX_SIZE);
snprintf(search->filter, FILTER_MAX_SIZE-1, cp->filter, predicate);
search->filter[FILTER_MAX_SIZE-1] = 0;
struct timeval timeout = { cp->timeout, 0 };
ldap_search_ext(search->ld, cp->base_object, LDAP_SCOPE_SUBTREE, search->filter,
cp->attributes, 0, NULL, NULL, &timeout, cp->max_results, &search->msgid );
int ret = ldap_search_ext(search->ld,
cp->base_object, // base from which to start
LDAP_SCOPE_SUBTREE,
search->filter, // search predicate
cp->attributes, // which attributes to get
0, // 0 = get attrs AND value, 1 = get attrs only
NULL,
NULL,
&timeout, // server timeout for the search
cp->max_results,// max result number
&search->msgid );
if( ret != LDAP_SUCCESS ){
ms_error("Error ldap_search_ext returned %d (%s)", ret, ldap_err2string(ret));
belle_sip_object_unref(search);
return NULL;
}
return search;
}
static void linphone_ldap_contact_destroy( LinphoneLDAPContactSearch* obj )
{
(void)obj;
if( obj->filter ) ms_free(obj->filter);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneLDAPContactSearch);
@ -90,13 +119,35 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneLDAPContactSearch,LinphoneContactSearch,
/* ***************************
* LinphoneLDAPContactProvider
* ***************************/
struct AuthMethodDescription{
LDAPAuthMethod method;
const char* description;
};
static struct AuthMethodDescription ldap_auth_method_description[] = {
{ANONYMOUS, "anonymous"},
{PLAIN, "plain"},
{SASL, "sasl"},
{0, NULL}
};
static LDAPAuthMethod linphone_ldap_contact_provider_auth_method( const char* description )
{
struct AuthMethodDescription* desc = ldap_auth_method_description;
while( desc && desc->description ){
if( strcmp(description, desc->description) == 0)
return desc->method;
desc++;
}
return ANONYMOUS;
}
static void linphone_ldap_contact_provider_conf_destroy(LinphoneLDAPContactProvider* obj )
{
if(obj->auth_method) ms_free(obj->auth_method);
if(obj->username) ms_free(obj->username);
if(obj->password) ms_free(obj->password);
if(obj->username) ms_free(obj->username);
if(obj->password) ms_free(obj->password);
if(obj->base_object) ms_free(obj->base_object);
if(obj->attributes){
int i=0;
for( ; obj->attributes[i]; i++){
@ -113,17 +164,20 @@ static void linphone_ldap_contact_provider_destroy( LinphoneLDAPContactProvider*
linphone_ldap_contact_provider_conf_destroy(obj);
}
static LinphoneLDAPContactSearch* linphone_ldap_begin_search(LinphoneLDAPContactProvider* obj,
const char* predicate,
ContactSearchCallback cb,
void* cb_data)
static LinphoneLDAPContactSearch*
linphone_ldap_begin_search(LinphoneLDAPContactProvider* obj,
const char* predicate,
ContactSearchCallback cb,
void* cb_data)
{
LDAPRequestEntry* entry = ms_new0(LDAPRequestEntry,1);
if( entry){
LinphoneLDAPContactSearch* request = linphone_ldap_contact_search_create(obj, predicate, cb, cb_data);
entry->msgid = request->msgid;
entry->request = request;
obj->requests = ms_list_append(obj->requests, entry);
obj->requests = ms_list_append(obj->requests, entry);
obj->req_count++;
return request;
} else {
@ -158,33 +212,16 @@ static unsigned int linphone_ldap_cancel_search(LinphoneContactProvider* obj, Li
return ret;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneLDAPContactProvider);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(LinphoneLDAPContactProvider)=
{
{
{
BELLE_SIP_VPTR_INIT(LinphoneLDAPContactProvider,LinphoneContactProvider,TRUE),
(belle_sip_object_destroy_t)linphone_ldap_contact_provider_destroy,
NULL,
NULL
},
"LDAP",
(LinphoneContactProviderStartSearchMethod)linphone_ldap_begin_search,
(LinphoneContactProviderCancelSearchMethod)linphone_ldap_cancel_search
}
};
static bool_t linphone_ldap_contact_provider_iterate(void *data)
{
LinphoneLDAPContactProvider* obj = LINPHONE_LDAP_CONTACT_PROVIDER(data);
if( obj->ld && (obj->req_count >= 0) ){
int wait_for_all_results = 1;
if( obj->ld && ((obj->req_count >= 0) || (obj->bind_msgid != 0) )){
// never block
struct timeval timeout = {0,0};
LDAPMessage* results = NULL;
int res = ldap_result(obj->ld, LDAP_RES_ANY, wait_for_all_results, &timeout, &results);
int res = ldap_result(obj->ld, LDAP_RES_ANY, LDAP_MSG_ALL, &timeout, &results);
switch( res ){
case -1:
@ -193,7 +230,14 @@ static bool_t linphone_ldap_contact_provider_iterate(void *data)
break;
}
case 0: break; // nothing to do
case LDAP_RES_BIND:
case LDAP_RES_BIND:
{
ms_message("iterate: LDAP_RES_BIND");
if( ldap_msgid( results ) != obj->bind_msgid ) {
ms_error("Bad msgid");
}
break;
}
case LDAP_RES_SEARCH_ENTRY:
case LDAP_RES_SEARCH_REFERENCE:
case LDAP_RES_SEARCH_RESULT:
@ -226,13 +270,19 @@ static void linphone_ldap_contact_provider_loadconfig(LinphoneLDAPContactProvide
obj->timeout = lp_config_get_int(config, section, "timeout", 10);
obj->deref_aliases = lp_config_get_int(config, section, "deref_aliases", 0);
obj->max_results = lp_config_get_int(config, section, "max_results", 50);
obj->auth_method = linphone_ldap_contact_provider_auth_method( lp_config_get_string(config, section, "auth_method", "anonymous"));
// free any pre-existing char* conf values
linphone_ldap_contact_provider_conf_destroy(obj);
// parse the attributes list
attributes_list = ms_strdup(lp_config_get_string(config, section, "attributes", "telephoneNumber,givenName,sn"));
/*
* parse the attributes list
*/
attributes_list = ms_strdup(lp_config_get_string(config, section,
"attributes",
"telephoneNumber,givenName,sn"));
// count attributes:
for( i=0; attributes_list[i]; i++)
@ -240,6 +290,7 @@ static void linphone_ldap_contact_provider_loadconfig(LinphoneLDAPContactProvide
if( attributes_list[i] == ',') attr_count++;
}
obj->attributes = ms_malloc0((attr_count+2) * sizeof(char*));
// 1 more for the first attr without ',', the other for the null-finished list
attr = strtok_r( attributes_list, ",", &saveptr );
while( attr != NULL ){
@ -247,17 +298,45 @@ static void linphone_ldap_contact_provider_loadconfig(LinphoneLDAPContactProvide
attr_idx++;
attr = strtok_r(NULL, ",", &saveptr);
}
if( attr_idx == attr_count)
if( attr_idx != attr_count+1) ms_error("Invalid attribute number!!! %d expected, got %d", attr_count+1, attr_idx);
ms_free(attributes_list);
obj->auth_method = ms_strdup(lp_config_get_string(config, section, "auth_method", "anonymous"));
obj->username = ms_strdup(lp_config_get_string(config, section, "username", ""));
obj->password = ms_strdup(lp_config_get_string(config, section, "password", ""));
obj->base_object = ms_strdup(lp_config_get_string(config, section, "base_object", ""));
obj->server = ms_strdup(lp_config_get_string(config, section, "server", "ldap://localhost:10389"));
}
static int linphone_ldap_contact_provider_bind( LinphoneLDAPContactProvider* obj )
{
struct berval password = { strlen( obj->password), obj->password };
int ret;
int bind_msgid = 0;
switch( obj->auth_method ){
case ANONYMOUS:
default:
{
ret = ldap_sasl_bind( obj->ld, obj->base_object, NULL, &password, NULL, NULL, &bind_msgid);
if( ret == LDAP_SUCCESS ) {
obj->bind_msgid = bind_msgid;
} else {
int err;
ldap_get_option(obj->ld, LDAP_OPT_RESULT_CODE, &err);
ms_error("ldap_sasl_bind error %d (%s)", err, ldap_err2string(err) );
}
break;
}
case SASL:
{
break;
}
}
return 0;
}
LinphoneLDAPContactProvider*linphone_ldap_contact_provider_create(LinphoneCore* lc)
{
@ -266,25 +345,42 @@ LinphoneLDAPContactProvider*linphone_ldap_contact_provider_create(LinphoneCore*
memset(obj->requests, MAX_RUNNING_REQUESTS, sizeof(LDAPRequestEntry));
int proto_version = LDAP_VERSION3;
const char* url = "localhost";
ms_message( "Constructed Contact provider '%s'", BELLE_SIP_OBJECT_VPTR(obj,LinphoneContactProvider)->name);
linphone_ldap_contact_provider_loadconfig(obj, linphone_core_get_config(lc));
int ret = ldap_initialize(&(obj->ld),url);
int ret = ldap_initialize(&(obj->ld),obj->server);
if( ret != LDAP_SUCCESS ){
ms_error( "Problem initializing ldap on url '%s': %s", url, ldap_err2string(ret));
linphone_ldap_contact_provider_destroy(obj);
ms_error( "Problem initializing ldap on url '%s': %s", obj->server, ldap_err2string(ret));
belle_sip_object_unref(obj);
return NULL;
} else if( (ret = ldap_set_option(obj->ld, LDAP_OPT_PROTOCOL_VERSION, &proto_version)) != LDAP_SUCCESS ){
ms_error( "Problem setting protocol version %d: %s", proto_version, ldap_err2string(ret));
linphone_ldap_contact_provider_destroy(obj);
belle_sip_object_unref(obj);
return NULL;
} else {
// register our hook into iterate so that LDAP can do its magic asynchronously
linphone_ldap_contact_provider_bind(obj);
linphone_core_add_iterate_hook(lc, linphone_ldap_contact_provider_iterate, obj);
}
return obj;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneLDAPContactProvider);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(LinphoneLDAPContactProvider)=
{
{
{
BELLE_SIP_VPTR_INIT(LinphoneLDAPContactProvider,LinphoneContactProvider,TRUE),
(belle_sip_object_destroy_t)linphone_ldap_contact_provider_destroy,
NULL,
NULL
},
"LDAP",
(LinphoneContactProviderStartSearchMethod)linphone_ldap_begin_search,
(LinphoneContactProviderCancelSearchMethod)linphone_ldap_cancel_search
}
};