From f5c9d60d8823085b1a5a3f823c5d3c39eabe0b93 Mon Sep 17 00:00:00 2001 From: Guillaume BIENKOWSKI Date: Thu, 28 Nov 2013 16:58:15 +0100 Subject: [PATCH] Progress commit... --- coreapi/ldap/ldapprovider.c | 204 ++++++++++++++++++++++++++---------- 1 file changed, 150 insertions(+), 54 deletions(-) diff --git a/coreapi/ldap/ldapprovider.c b/coreapi/ldap/ldapprovider.c index 843cea918..79cb66b03 100644 --- a/coreapi/ldap/ldapprovider.c +++ b/coreapi/ldap/ldapprovider.c @@ -19,12 +19,6 @@ #include "lpconfig.h" #include -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 + } +};