Fri Aug 17 00:17:47 2018

Asterisk developer's documentation


res_config_ldap.c File Reference

ldap plugin for portable configuration engine (ARA) More...

#include "asterisk.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <ldap.h>
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"

Go to the source code of this file.

Data Structures

struct  category_and_metric
struct  ldap_table_config
 Table configuration. More...
struct  table_configs
 Should be locked before using it. More...

Defines

#define MAXRESULT   2048
#define RES_CONFIG_LDAP_CONF   "res_ldap.conf"
#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void append_var_and_value_to_filter (struct ast_str **filter, struct ldap_table_config *table_config, const char *name, const char *value)
 Append a name=value filter string. The filter string can grow.
static char * cleaned_basedn (struct ast_channel *channel, const char *basedn)
static int compare_categories (const void *a, const void *b)
 Sorting alogrithm for qsort to find the order of the variables a and b.
static struct ast_configconfig_ldap (const char *basedn, const char *table_name, const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *sugg_incl, const char *who_asked)
 See Asterisk doc.
static const char * convert_attribute_name_from_ldap (struct ldap_table_config *table_config, const char *attribute_name)
 Convert ldap attribute name to variable name.
static const char * convert_attribute_name_to_ldap (struct ldap_table_config *table_config, const char *attribute_name)
 Convert variable name to ldap attribute name - Should be locked before using it.
static int is_ldap_connect_error (int err)
 Check if we have a connection error.
static struct ast_variableldap_loadentry (struct ldap_table_config *table_config, const char *dn)
 Get LDAP entry by dn and return attributes as variables - Should be locked before using it This is used for setting the default values of an object(i.e., with accountBaseDN).
static int ldap_reconnect (void)
static void ldap_table_config_add_attribute (struct ldap_table_config *table_config, const char *attribute_name, const char *attribute_value)
 add attribute to table config - Should be locked before using it
static int load_module (void)
static int parse_config (void)
 parse the configuration file
static struct ast_variablerealtime_ldap (const char *basedn, const char *table_name, va_list ap)
 See Asterisk doc.
static struct ast_variable ** realtime_ldap_base (unsigned int *entries_count_ptr, const char *basedn, const char *table_name,...)
 same as realtime_ldap_base_ap but take variable arguments count list
static struct ast_variable ** realtime_ldap_base_ap (unsigned int *entries_count_ptr, const char *basedn, const char *table_name, va_list ap)
 LDAP base function.
static struct ast_variablerealtime_ldap_entry_to_var (struct ldap_table_config *table_config, LDAPMessage *ldap_entry)
 Get variables from ldap entry attributes.
static struct ast_variable ** realtime_ldap_result_to_vars (struct ldap_table_config *table_config, LDAPMessage *ldap_result_msg, unsigned int *entries_count_ptr)
 Get variables from ldap entry attributes - Should be locked before using it.
static char * realtime_ldap_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_configrealtime_multi_ldap (const char *basedn, const char *table_name, va_list ap)
 See Asterisk doc.
static int reload (void)
static int replace_string_in_string (char *string, const char *search, const char *by)
 Replace <search> by <by> in string.
static int semicolon_count_str (const char *somestr)
 for the semicolon delimiter
static int semicolon_count_var (struct ast_variable *var)
static char * substituted (struct ast_channel *channel, const char *string)
static struct ldap_table_configtable_config_for_table_name (const char *table_name)
 Find a table_config - Should be locked before using it.
static struct ldap_table_configtable_config_new (const char *table_name)
 Create a new table_config.
static void table_configs_free (void)
 Free table_config.
static int unload_module (void)
static int update2_ldap (const char *basedn, const char *table_name, va_list ap)
static int update_ldap (const char *basedn, const char *table_name, const char *attribute, const char *lookup, va_list ap)
static struct ast_variablevariable_named (struct ast_variable *var, const char *name)
 Find variable by name.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "LDAP realtime interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static char base_distinguished_name [512]
static struct ldap_table_configbase_table_config
static time_t connect_time
static struct ast_cli_entry ldap_cli []
static struct ast_config_engine ldap_engine
static ast_mutex_t ldap_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static LDAP * ldapConn
static char pass [512]
static struct ldap_table_configstatic_table_config
static char url [512]
static char user [512]
static int version

Detailed Description

ldap plugin for portable configuration engine (ARA)

Author:
Mark Spencer <markster@digium.com>
Manuel Guesdon
Carl-Einar Thorner <cthorner@voicerd.com>
Russell Bryant <russell@digium.com>
ExtRef:
OpenLDAP http://www.openldap.org

Definition in file res_config_ldap.c.


Define Documentation

#define MAXRESULT   2048
#define RES_CONFIG_LDAP_CONF   "res_ldap.conf"

Definition at line 61 of file res_config_ldap.c.

Referenced by config_ldap(), and parse_config().

#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Definition at line 62 of file res_config_ldap.c.

Referenced by parse_config().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1810 of file res_config_ldap.c.

static void __unreg_module ( void   )  [static]

Definition at line 1810 of file res_config_ldap.c.

static void append_var_and_value_to_filter ( struct ast_str **  filter,
struct ldap_table_config table_config,
const char *  name,
const char *  value 
) [static]

Append a name=value filter string. The filter string can grow.

Definition at line 694 of file res_config_ldap.c.

References ast_debug, ast_str_append(), ast_strdupa, convert_attribute_name_to_ldap(), len(), and replace_string_in_string().

Referenced by realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

00697 {
00698    char *new_name = NULL;
00699    char *new_value = NULL;
00700    char *like_pos = strstr(name, " LIKE");
00701 
00702    ast_debug(2, "name='%s' value='%s'\n", name, value);
00703 
00704    if (like_pos) {
00705       int len = like_pos - name;
00706 
00707       name = new_name = ast_strdupa(name);
00708       new_name[len] = '\0';
00709       value = new_value = ast_strdupa(value);
00710       replace_string_in_string(new_value, "\\_", "_");
00711       replace_string_in_string(new_value, "%", "*");
00712    }
00713 
00714    name = convert_attribute_name_to_ldap(table_config, name);
00715 
00716    ast_str_append(filter, 0, "(%s=%s)", name, value);
00717 }

static char* cleaned_basedn ( struct ast_channel channel,
const char *  basedn 
) [static]
Note:
caller should free returned pointer

Definition at line 643 of file res_config_ldap.c.

References ast_debug, ast_strlen_zero(), len(), and substituted().

Referenced by realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

00644 {
00645    char *cbasedn = NULL;
00646    if (basedn) {
00647       char *p = NULL;
00648       cbasedn = substituted(channel, basedn);
00649       if (*cbasedn == '"') {
00650          cbasedn++;
00651          if (!ast_strlen_zero(cbasedn)) {
00652             int len = strlen(cbasedn);
00653             if (cbasedn[len - 1] == '"')
00654                cbasedn[len - 1] = '\0';
00655 
00656          }
00657       }
00658       p = cbasedn;
00659       while (*p) {
00660          if (*p == '|')
00661             *p = ',';
00662          p++;
00663       }
00664    }
00665    ast_debug(2, "basedn: '%s' => '%s' \n", basedn, cbasedn);
00666    return cbasedn;
00667 }

static int compare_categories ( const void *  a,
const void *  b 
) [static]

Sorting alogrithm for qsort to find the order of the variables a and b.

Parameters:
a pointer to category_and_metric struct
b pointer to category_and_metric struct
Return values:
-1 for if b is greater
0 zero for equal
1 if a is greater

Definition at line 1019 of file res_config_ldap.c.

References category_and_metric::metric, category_and_metric::name, and category_and_metric::var_metric.

Referenced by config_ldap().

01020 {
01021    const struct category_and_metric *as = a;
01022    const struct category_and_metric *bs = b;
01023 
01024    if (as->metric < bs->metric) {
01025       return -1;
01026    } else if (as->metric > bs->metric) {
01027       return 1;
01028    } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
01029       return strcmp(as->name, bs->name);
01030    } 
01031    /* if the metric and the category name is the same, we check the variable metric */
01032    if (as->var_metric < bs->var_metric) {
01033       return -1;
01034    } else if (as->var_metric > bs->var_metric) {
01035       return 1;
01036    }
01037 
01038    return 0;
01039 }

static struct ast_config* config_ldap ( const char *  basedn,
const char *  table_name,
const char *  file,
struct ast_config cfg,
struct ast_flags  config_flags,
const char *  sugg_incl,
const char *  who_asked 
) [static, read]

See Asterisk doc.

This is for Static Realtime (again: I think...)

load the configuration stuff for the .conf files called on a reload

Note:
Since the items come back in random order, they need to be sorted first, and since the data could easily exceed stack size, this is allocated from the heap.

Definition at line 1048 of file res_config_ldap.c.

References ast_calloc, ast_category_append(), ast_category_new(), ast_config_internal_load(), ast_debug, ast_free, ast_log(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), compare_categories(), LOG_ERROR, LOG_WARNING, category_and_metric::metric, name, category_and_metric::name, realtime_ldap_base(), RES_CONFIG_LDAP_CONF, ast_variable::value, category_and_metric::var_metric, category_and_metric::variable_name, variable_named(), and category_and_metric::variable_value.

01050 {
01051    unsigned int vars_count = 0;
01052    struct ast_variable **vars;
01053    int i = 0;
01054    struct ast_variable *new_v = NULL;
01055    struct ast_category *cur_cat = NULL;
01056    const char *last_category = NULL;
01057    int last_category_metric = 0;
01058    struct category_and_metric *categories;
01059    struct ast_variable **p;
01060 
01061    if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
01062       ast_log(LOG_ERROR, "Missing configuration file: %s. Can't configure myself.\n", RES_CONFIG_LDAP_CONF);
01063       return NULL;
01064    }
01065 
01066    vars = realtime_ldap_base(&vars_count, basedn, table_name, "filename", file, "commented", "FALSE", NULL);
01067 
01068    if (!vars) {
01069       ast_log(LOG_WARNING, "Could not find config '%s' in directory.\n", file);
01070       return NULL;
01071    }
01072 
01073    /*!\note Since the items come back in random order, they need to be sorted
01074     * first, and since the data could easily exceed stack size, this is
01075     * allocated from the heap.
01076     */
01077    if (!(categories = ast_calloc(sizeof(*categories), vars_count))) {
01078       return NULL;
01079    }
01080 
01081    for (vars_count = 0, p = vars; *p; p++) {
01082       struct ast_variable *category = variable_named(*p, "category");
01083       struct ast_variable *cat_metric = variable_named(*p, "cat_metric");
01084       struct ast_variable *var_name = variable_named(*p, "variable_name");
01085       struct ast_variable *var_val = variable_named(*p, "variable_value");
01086       struct ast_variable *var_metric = variable_named(*p, "var_metric");
01087       struct ast_variable *dn = variable_named(*p, "dn");
01088          
01089       ast_debug(3, "category: %s\n", category->value);
01090       ast_debug(3, "var_name: %s\n", var_name->value);
01091       ast_debug(3, "var_val: %s\n", var_val->value);
01092       ast_debug(3, "cat_metric: %s\n", cat_metric->value);
01093 
01094       if (!category) {
01095          ast_log(LOG_ERROR, "No category name in entry '%s'  for file '%s'.\n",
01096                (dn ? dn->value : "?"), file);
01097       } else if (!cat_metric) {
01098          ast_log(LOG_ERROR, "No category metric in entry '%s'(category: %s) for file '%s'.\n",
01099                (dn ? dn->value : "?"), category->value, file);
01100       } else if (!var_metric) {
01101          ast_log(LOG_ERROR, "No variable metric in entry '%s'(category: %s) for file '%s'.\n",
01102                (dn ? dn->value : "?"), category->value, file);
01103       } else if (!var_name) {
01104          ast_log(LOG_ERROR, "No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
01105                (dn ? dn->value : "?"), category->value,
01106                cat_metric->value, file);
01107       } else if (!var_val) {
01108          ast_log(LOG_ERROR, "No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
01109                (dn ? dn->value : "?"), category->value,
01110                cat_metric->value, var_name->value, file);
01111       } else {
01112          categories[vars_count].name = category->value;
01113          categories[vars_count].metric = atoi(cat_metric->value);
01114          categories[vars_count].variable_name = var_name->value;
01115          categories[vars_count].variable_value = var_val->value;
01116          categories[vars_count].var_metric = atoi(var_metric->value);
01117          vars_count++;
01118       }
01119    }
01120 
01121    qsort(categories, vars_count, sizeof(*categories), compare_categories);
01122 
01123    for (i = 0; i < vars_count; i++) {
01124       if (!strcmp(categories[i].variable_name, "#include")) {
01125          struct ast_flags flags = { 0 };
01126          if (!ast_config_internal_load(categories[i].variable_value, cfg, flags, "", who_asked)) {
01127             break;
01128          }
01129          continue;
01130       }
01131 
01132       if (!last_category || strcmp(last_category, categories[i].name) ||
01133          last_category_metric != categories[i].metric) {
01134 
01135          cur_cat = ast_category_new(categories[i].name, table_name, -1);
01136          if (!cur_cat) {
01137             break;
01138          }
01139          last_category = categories[i].name;
01140          last_category_metric = categories[i].metric;
01141          ast_category_append(cfg, cur_cat);
01142       }
01143 
01144       if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name))) {
01145          break;
01146       }
01147 
01148       ast_variable_append(cur_cat, new_v);
01149    }
01150 
01151    ast_free(vars);
01152    ast_free(categories);
01153 
01154    return cfg;
01155 }

static const char* convert_attribute_name_from_ldap ( struct ldap_table_config table_config,
const char *  attribute_name 
) [static]

Convert ldap attribute name to variable name.

Note:
Should be locked before using it

Definition at line 251 of file res_config_ldap.c.

References ARRAY_LEN, ldap_table_config::attributes, base_table_config, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by realtime_ldap_entry_to_var(), and realtime_ldap_result_to_vars().

00253 {
00254    int i = 0;
00255    struct ldap_table_config *configs[] = { table_config, base_table_config };
00256 
00257    for (i = 0; i < ARRAY_LEN(configs); i++) {
00258       struct ast_variable *attribute;
00259 
00260       if (!configs[i]) {
00261          continue;
00262       }
00263 
00264       attribute = configs[i]->attributes;
00265       for (; attribute; attribute = attribute->next) {
00266          if (strcasecmp(attribute_name, attribute->value) == 0) {
00267             return attribute->name;
00268          }
00269       }
00270    }
00271 
00272    return attribute_name;
00273 }

static const char* convert_attribute_name_to_ldap ( struct ldap_table_config table_config,
const char *  attribute_name 
) [static]

Convert variable name to ldap attribute name - Should be locked before using it.

Definition at line 225 of file res_config_ldap.c.

References ARRAY_LEN, ldap_table_config::attributes, base_table_config, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by append_var_and_value_to_filter(), update2_ldap(), and update_ldap().

00227 {
00228    int i = 0;
00229    struct ldap_table_config *configs[] = { table_config, base_table_config };
00230 
00231    for (i = 0; i < ARRAY_LEN(configs); i++) {
00232       struct ast_variable *attribute;
00233 
00234       if (!configs[i]) {
00235          continue;
00236       }
00237 
00238       attribute = configs[i]->attributes;
00239       for (; attribute; attribute = attribute->next) {
00240          if (!strcasecmp(attribute_name, attribute->name)) {
00241             return attribute->value;
00242          }
00243       }
00244    }
00245 
00246    return attribute_name;
00247 }

static int is_ldap_connect_error ( int  err  )  [static]

Check if we have a connection error.

Definition at line 546 of file res_config_ldap.c.

Referenced by ldap_loadentry(), realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

00547 {
00548    return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
00549 }

static struct ast_variable* ldap_loadentry ( struct ldap_table_config table_config,
const char *  dn 
) [static, read]

Get LDAP entry by dn and return attributes as variables - Should be locked before using it This is used for setting the default values of an object(i.e., with accountBaseDN).

< not using this

Definition at line 554 of file res_config_ldap.c.

References ast_debug, ast_log(), ast_mutex_unlock, ast_realloc, ast_variables_destroy(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, realtime_ldap_result_to_vars(), and var.

Referenced by realtime_ldap_base_ap().

00556 {
00557    if (!table_config) {
00558       ast_log(LOG_ERROR, "No table config\n");
00559       return NULL;
00560    } else {
00561       struct ast_variable **vars = NULL;
00562       struct ast_variable *var = NULL;
00563       int result = -1;
00564       LDAPMessage *ldap_result_msg = NULL;
00565       int tries = 0;
00566 
00567       ast_debug(2, "ldap_loadentry dn=%s\n", dn);
00568 
00569       do {
00570          result = ldap_search_ext_s(ldapConn, dn, LDAP_SCOPE_BASE,
00571                   "(objectclass=*)", NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg);
00572          if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
00573             ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
00574             tries++;
00575             if (tries < 3) {
00576                usleep(500000L * tries);
00577                if (ldapConn) {
00578                   ldap_unbind_ext_s(ldapConn, NULL, NULL);
00579                   ldapConn = NULL;
00580                }
00581                if (!ldap_reconnect()) {
00582                   break;
00583                }
00584             }
00585          }
00586       } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
00587 
00588       if (result != LDAP_SUCCESS) {
00589          ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
00590          ast_debug(2, "dn=%s\n", dn);
00591          ast_mutex_unlock(&ldap_lock);
00592          return NULL;
00593       } else {
00594          int num_entry = 0;
00595          unsigned int *entries_count_ptr = NULL; /*!< not using this */
00596 
00597          if ((num_entry = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
00598             ast_debug(3, "num_entry: %d\n", num_entry);
00599 
00600             vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
00601             if (num_entry > 1) {
00602                ast_log(LOG_NOTICE, "More than one entry for dn=%s. Take only 1st one\n", dn);
00603             }
00604          } else {
00605             ast_debug(2, "Could not find any entry dn=%s.\n", dn);
00606          }
00607       }
00608       ldap_msgfree(ldap_result_msg);
00609 
00610       /* Chopping \a vars down to one variable */
00611       if (vars != NULL) {
00612          struct ast_variable **p = vars;
00613          p++;
00614          var = *p;
00615          while (var) {
00616             ast_variables_destroy(var);
00617             p++;
00618          }
00619          vars = ast_realloc(vars, sizeof(struct ast_variable *));
00620       }
00621 
00622       var = *vars;
00623 
00624       return var;
00625    }
00626 }

static int ldap_reconnect ( void   )  [static]
Note:
ldap_lock should have been locked before calling this function.

Definition at line 1710 of file res_config_ldap.c.

References ast_debug, ast_log(), ast_strlen_zero(), LOG_ERROR, and LOG_WARNING.

Referenced by ldap_loadentry(), load_module(), realtime_ldap_base_ap(), reload(), update2_ldap(), and update_ldap().

01711 {
01712    int bind_result = 0;
01713    struct berval cred;
01714 
01715    if (ldapConn) {
01716       ast_debug(2, "Everything seems fine.\n");
01717       return 1;
01718    }
01719 
01720    if (ast_strlen_zero(url)) {
01721       ast_log(LOG_ERROR, "Not enough parameters to connect to ldap directory\n");
01722       return 0;
01723    }
01724 
01725    if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
01726       ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
01727       return 0;
01728    }
01729 
01730    if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
01731       ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
01732    }
01733 
01734    if (!ast_strlen_zero(user)) {
01735       ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
01736       cred.bv_val = (char *) pass;
01737       cred.bv_len = strlen(pass);
01738       bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01739    } else {
01740       ast_debug(2, "bind %s anonymously\n", url);
01741       cred.bv_val = NULL;
01742       cred.bv_len = 0;
01743       bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01744    }
01745    if (bind_result == LDAP_SUCCESS) {
01746       ast_debug(2, "Successfully connected to directory.\n");
01747       connect_time = time(NULL);
01748       return 1;
01749    } else {
01750       ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
01751       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01752       ldapConn = NULL;
01753       return 0;
01754    }
01755 }

static void ldap_table_config_add_attribute ( struct ldap_table_config table_config,
const char *  attribute_name,
const char *  attribute_value 
) [static]

add attribute to table config - Should be locked before using it

Definition at line 182 of file res_config_ldap.c.

References ast_strlen_zero(), ast_variable_new(), ldap_table_config::attributes, ast_variable::next, ldap_table_config::table_name, and var.

Referenced by parse_config().

00184 {
00185    struct ast_variable *var;
00186 
00187    if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value)) {
00188       return;
00189    }
00190 
00191    if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->table_name))) {
00192       return;
00193    }
00194 
00195    if (table_config->attributes) {
00196       var->next = table_config->attributes;
00197    }
00198    table_config->attributes = var;
00199 }

static int load_module ( void   )  [static]

Definition at line 1538 of file res_config_ldap.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_config_engine_register(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, ldap_cli, ldap_engine, ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, and parse_config().

01539 {
01540    if (parse_config() < 0) {
01541       ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
01542       return 0;
01543    }
01544 
01545    ast_mutex_lock(&ldap_lock);
01546 
01547    if (!ldap_reconnect())  {
01548       ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
01549    }
01550 
01551    ast_config_engine_register(&ldap_engine);
01552    ast_verb(1, "LDAP RealTime driver loaded.\n");
01553    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01554 
01555    ast_mutex_unlock(&ldap_lock);
01556 
01557    return 0;
01558 }

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1610 of file res_config_ldap.c.

References ldap_table_config::additional_filter, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_INSERT_HEAD, ast_log(), ast_strdup, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), base_table_config, config, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ldap_table_config::entry, ldap_table_config_add_attribute(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, RES_CONFIG_LDAP_CONF, RES_CONFIG_LDAP_DEFAULT_BASEDN, static_table_config, table_config_for_table_name(), table_config_new(), table_configs_free(), ast_variable::value, and var.

Referenced by load_module(), and reload().

01611 {
01612    struct ast_config *config;
01613    struct ast_flags config_flags = {0};
01614    const char *s, *host;
01615    int port;
01616    char *category_name = NULL;
01617 
01618    /* Make sure that global variables are reset */
01619    url[0] = '\0';
01620    user[0] = '\0';
01621    pass[0] = '\0';
01622    base_distinguished_name[0] = '\0';
01623    version = 3;
01624 
01625    config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
01626    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01627       ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
01628       return -1;
01629    }
01630 
01631    if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
01632       ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
01633       user[0] = '\0';
01634    } else {
01635       ast_copy_string(user, s, sizeof(user));
01636    }
01637 
01638    if (!ast_strlen_zero(user)) {
01639       if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
01640          ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
01641          ast_copy_string(pass, "asterisk", sizeof(pass));
01642       } else {
01643          ast_copy_string(pass, s, sizeof(pass));
01644       }
01645    }
01646 
01647    /* URL is preferred, use host and port if not found */
01648    if ((s = ast_variable_retrieve(config, "_general", "url"))) {
01649       ast_copy_string(url, s, sizeof(url));
01650    } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
01651       if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
01652          ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
01653          port = 389;
01654       }
01655 
01656       snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
01657    } else {
01658       ast_log(LOG_ERROR, "No directory URL or host found.\n");
01659       ast_config_destroy(config);
01660       return -1;
01661    }
01662 
01663    if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
01664       ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
01665       ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
01666    } else 
01667       ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));
01668 
01669    if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
01670       ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
01671    } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
01672       ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
01673       version = 3;
01674    }
01675 
01676    table_configs_free();
01677 
01678    while ((category_name = ast_category_browse(config, category_name))) {
01679       int is_general = (strcasecmp(category_name, "_general") == 0);
01680       int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
01681       struct ast_variable *var = ast_variable_browse(config, category_name);
01682       
01683       if (var) {
01684          struct ldap_table_config *table_config =
01685             table_config_for_table_name(category_name);
01686          if (!table_config) {
01687             table_config = table_config_new(category_name);
01688             AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
01689             if (is_general)
01690                base_table_config = table_config;
01691             if (is_config)
01692                static_table_config = table_config;
01693          }
01694          for (; var; var = var->next) {
01695             if (!strcasecmp(var->name, "additionalFilter")) {
01696                table_config->additional_filter = ast_strdup(var->value);
01697             } else {
01698                ldap_table_config_add_attribute(table_config, var->name, var->value);
01699             }
01700          }
01701       }
01702    }
01703 
01704    ast_config_destroy(config);
01705 
01706    return 1;
01707 }

static struct ast_variable* realtime_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static, read]

See Asterisk doc.

For Realtime Dynamic(i.e., switch, queues, and directory) -- I think

Definition at line 921 of file res_config_ldap.c.

References free, ast_variable::next, realtime_ldap_base_ap(), and var.

00923 {
00924    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00925    struct ast_variable *var = NULL;
00926 
00927    if (vars) {
00928       struct ast_variable *last_var = NULL;
00929       struct ast_variable **p = vars;
00930       while (*p) {
00931          if (last_var) {
00932             while (last_var->next) {
00933                last_var = last_var->next;
00934             }
00935             last_var->next = *p;
00936          } else {
00937             var = *p;
00938             last_var = var;
00939          }
00940          p++;
00941       }
00942       free(vars);
00943    }
00944    return var;
00945 }

static struct ast_variable** realtime_ldap_base ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
  ... 
) [static, read]

same as realtime_ldap_base_ap but take variable arguments count list

Definition at line 904 of file res_config_ldap.c.

References realtime_ldap_base_ap().

Referenced by config_ldap().

00906 {
00907    struct ast_variable **vars = NULL;
00908    va_list ap;
00909 
00910    va_start(ap, table_name);
00911    vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, ap);
00912    va_end(ap);
00913 
00914    return vars;
00915 }

static struct ast_variable** realtime_ldap_base_ap ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
va_list  ap 
) [static, read]

LDAP base function.

Returns:
a null terminated array of ast_variable (one per entry) or NULL if no entry is found or if an error occured caller should free the returned array and ast_variables
Parameters:
entries_count_ptr is a pointer to found entries count (can be NULL)
basedn is the base DN
table_name is the table_name (used dor attribute convertion and additional filter)
ap contains null terminated list of pairs name/value

Definition at line 727 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_variables_destroy(), base_table_config, cleaned_basedn(), filter(), is_ldap_connect_error(), ldap_loadentry(), ldap_lock, ldap_reconnect(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, ldap_table_config::next, realtime_ldap_result_to_vars(), table_config_for_table_name(), and ast_variable::value.

Referenced by realtime_ldap(), realtime_ldap_base(), and realtime_multi_ldap().

00729 {
00730    struct ast_variable **vars = NULL;
00731    const char *newparam = NULL;
00732    const char *newval = NULL;
00733    struct ldap_table_config *table_config = NULL;
00734    char *clean_basedn = cleaned_basedn(NULL, basedn);
00735    struct ast_str *filter = NULL;
00736    int tries = 0;
00737    int result = 0;
00738    LDAPMessage *ldap_result_msg = NULL;
00739 
00740    if (!table_name) {
00741       ast_log(LOG_ERROR, "No table_name specified.\n");
00742       ast_free(clean_basedn);
00743       return NULL;
00744    } 
00745 
00746    if (!(filter = ast_str_create(80))) {
00747       ast_log(LOG_ERROR, "Can't initialize data structures.n");
00748       ast_free(clean_basedn);
00749       return NULL;
00750    }
00751 
00752    /* Get the first parameter and first value in our list of passed paramater/value pairs  */
00753    newparam = va_arg(ap, const char *);
00754    newval = va_arg(ap, const char *);
00755 
00756    if (!newparam || !newval) {
00757       ast_log(LOG_ERROR, "Realtime retrieval requires at least 1 parameter"
00758          " and 1 value to search on.\n");
00759       ast_free(filter);
00760       ast_free(clean_basedn);
00761       return NULL;
00762    }
00763 
00764    ast_mutex_lock(&ldap_lock);
00765 
00766    /* We now have our complete statement; Lets connect to the server and execute it.  */
00767    if (!ldap_reconnect()) {
00768       ast_mutex_unlock(&ldap_lock);
00769       ast_free(filter);
00770       ast_free(clean_basedn);
00771       return NULL;
00772    }
00773 
00774    table_config = table_config_for_table_name(table_name);
00775    if (!table_config) {
00776       ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
00777       ast_mutex_unlock(&ldap_lock);
00778       ast_free(filter);
00779       ast_free(clean_basedn);
00780       return NULL;
00781    }
00782 
00783    ast_str_append(&filter, 0, "(&");
00784 
00785    if (table_config && table_config->additional_filter) {
00786       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
00787    }
00788    if (table_config != base_table_config && base_table_config && 
00789       base_table_config->additional_filter) {
00790       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
00791    }
00792 
00793    /* Create the first part of the query using the first parameter/value pairs we just extracted */
00794    /*   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
00795 
00796    append_var_and_value_to_filter(&filter, table_config, newparam, newval);
00797    while ((newparam = va_arg(ap, const char *))) {
00798       newval = va_arg(ap, const char *);
00799       append_var_and_value_to_filter(&filter, table_config, newparam, newval);
00800    }
00801    ast_str_append(&filter, 0, ")");
00802 
00803    do {
00804       /* freeing ldap_result further down */
00805       result = ldap_search_ext_s(ldapConn, clean_basedn,
00806               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
00807               &ldap_result_msg);
00808       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
00809          ast_log(LOG_DEBUG, "Failed to query directory. Try %d/10\n", tries + 1);
00810          if (++tries < 10) {
00811             usleep(1);
00812             if (ldapConn) {
00813                ldap_unbind_ext_s(ldapConn, NULL, NULL);
00814                ldapConn = NULL;
00815             }
00816             if (!ldap_reconnect()) {
00817                break;
00818             }
00819          }
00820       }
00821    } while (result != LDAP_SUCCESS && tries < 10 && is_ldap_connect_error(result));
00822 
00823    if (result != LDAP_SUCCESS) {
00824       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
00825       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
00826    } else {
00827       /* this is where we create the variables from the search result 
00828        * freeing this \a vars outside this function */
00829       if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
00830          /* is this a static var or some other? they are handled different for delimited values */
00831          vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
00832       } else {
00833          ast_debug(1, "Could not find any entry matching %s in base dn %s.\n", ast_str_buffer(filter), clean_basedn);
00834       }
00835 
00836       ldap_msgfree(ldap_result_msg);
00837 
00838       /* TODO: get the default variables from the accountBaseDN, not implemented with delimited values */
00839       if (vars) {
00840          struct ast_variable **p = vars;
00841          while (*p) {
00842             struct ast_variable *append_var = NULL;
00843             struct ast_variable *tmp = *p;
00844             while (tmp) {
00845                if (strcasecmp(tmp->name, "accountBaseDN") == 0) {
00846                   /* Get the variable to compare with for the defaults */
00847                   struct ast_variable *base_var = ldap_loadentry(table_config, tmp->value);
00848                   
00849                   while (base_var) {
00850                      struct ast_variable *next = base_var->next;
00851                      struct ast_variable *test_var = *p;
00852                      int base_var_found = 0;
00853 
00854                      /* run throught the default values and fill it inn if it is missing */
00855                      while (test_var) {
00856                         if (strcasecmp(test_var->name, base_var->name) == 0) {
00857                            base_var_found = 1;
00858                            break;
00859                         } else {
00860                            test_var = test_var->next;
00861                         }
00862                      }
00863                      if (base_var_found) {
00864                         base_var->next = NULL;
00865                         ast_variables_destroy(base_var);
00866                         base_var = next;
00867                      } else {
00868                         if (append_var) {
00869                            base_var->next = append_var;
00870                         } else {
00871                            base_var->next = NULL;
00872                         }
00873                         append_var = base_var;
00874                         base_var = next;
00875                      }
00876                   }
00877                }
00878                if (!tmp->next && append_var) {
00879                   tmp->next = append_var;
00880                   tmp = NULL;
00881                } else {
00882                   tmp = tmp->next;
00883                }
00884             }
00885             p++;
00886          }
00887       }
00888    }
00889 
00890    if (filter) {
00891       ast_free(filter);
00892    }
00893 
00894    if (clean_basedn) {
00895       ast_free(clean_basedn);
00896    }
00897 
00898    ast_mutex_unlock(&ldap_lock);
00899 
00900    return vars;
00901 }

static struct ast_variable* realtime_ldap_entry_to_var ( struct ldap_table_config table_config,
LDAPMessage *  ldap_entry 
) [static, read]

Get variables from ldap entry attributes.

Note:
Should be locked before using it
Returns:
a linked list of ast_variable variables.

Definition at line 279 of file res_config_ldap.c.

References ast_debug, ast_strlen_zero(), ast_variable_new(), convert_attribute_name_from_ldap(), ast_variable::next, ldap_table_config::table_name, value, and var.

Referenced by realtime_ldap_result_to_vars().

00281 {
00282    BerElement *ber = NULL;
00283    struct ast_variable *var = NULL;
00284    struct ast_variable *prev = NULL;
00285    int is_delimited = 0;
00286    int i = 0;
00287    char *ldap_attribute_name;
00288    struct berval *value;
00289    int pos = 0;
00290 
00291    ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00292 
00293    while (ldap_attribute_name) {
00294       struct berval **values = NULL;
00295       const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00296       int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00297 
00298       values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name); /* these are freed at the end */
00299       if (values) {
00300          struct berval **v;
00301          char *valptr;
00302 
00303          for (v = values; *v; v++) {
00304             value = *v;
00305             valptr = value->bv_val;
00306             ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr);
00307             if (is_realmed_password_attribute) {
00308                if (!strncasecmp(valptr, "{md5}", 5)) {
00309                   valptr += 5;
00310                }
00311                ast_debug(2, "md5: %s\n", valptr);
00312             }
00313             if (valptr) {
00314                /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
00315                if (is_delimited) {
00316                   i = 0;
00317                   pos = 0;
00318                   while (!ast_strlen_zero(valptr + i)) {
00319                      if (valptr[i] == ';') {
00320                         valptr[i] = '\0';
00321                         if (prev) {
00322                            prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00323                            if (prev->next) {
00324                               prev = prev->next;
00325                            }
00326                         } else {
00327                            prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00328                         }
00329                         pos = i + 1;
00330                      }
00331                      i++;
00332                   }
00333                }
00334                /* for the last delimited value or if the value is not delimited: */
00335                if (prev) {
00336                   prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00337                   if (prev->next) {
00338                      prev = prev->next;
00339                   }
00340                } else {
00341                   prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00342                }
00343             }
00344          }
00345          ldap_value_free_len(values);
00346       }
00347       ldap_memfree(ldap_attribute_name);
00348       ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00349    }
00350    ber_free(ber, 0);
00351 
00352    return var;
00353 }

static struct ast_variable** realtime_ldap_result_to_vars ( struct ldap_table_config table_config,
LDAPMessage *  ldap_result_msg,
unsigned int *  entries_count_ptr 
) [static, read]

Get variables from ldap entry attributes - Should be locked before using it.

The results are freed outside this function so is the vars array.

Returns:
vars - an array of ast_variable variables terminated with a null.

Definition at line 361 of file res_config_ldap.c.

References ast_calloc, ast_debug, ast_strdup, ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), convert_attribute_name_from_ldap(), free, ast_variable::next, option_debug, realtime_ldap_entry_to_var(), semicolon_count_str(), semicolon_count_var(), static_table_config, ldap_table_config::table_name, ast_variable::value, value, var, and variable_named().

Referenced by ldap_loadentry(), and realtime_ldap_base_ap().

00363 {
00364    struct ast_variable **vars;
00365    int i = 0;
00366    int tot_count = 0;
00367    int entry_index = 0;
00368    LDAPMessage *ldap_entry = NULL;
00369    BerElement *ber = NULL;
00370    struct ast_variable *var = NULL;
00371    struct ast_variable *prev = NULL;
00372    int is_delimited = 0;
00373    char *delim_value = NULL;
00374    int delim_tot_count = 0;
00375    int delim_count = 0;
00376 
00377    /* First find the total count */
00378    ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
00379 
00380    for (tot_count = 0; ldap_entry; tot_count++) { 
00381       struct ast_variable *tmp = realtime_ldap_entry_to_var(table_config, ldap_entry);
00382       tot_count += semicolon_count_var(tmp);
00383       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00384       ast_variables_destroy(tmp);
00385    }
00386 
00387    if (entries_count_ptr) {
00388       *entries_count_ptr = tot_count;
00389    }
00390 
00391    /* Now that we have the total count we allocate space and create the variables
00392     * Remember that each element in vars is a linked list that points to realtime variable.
00393     * If the we are dealing with a static realtime variable we create a new element in the \a vars array for each delimited
00394     * value in \a variable_value; otherwise, we keep \a vars static and increase the length of the linked list of variables in the array element.
00395     * This memory must be freed outside of this function. */
00396    vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1);
00397 
00398    ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
00399 
00400    i = 0;
00401 
00402    /* For each static realtime variable we may create several entries in the \a vars array if it's delimited */
00403    for (entry_index = 0; ldap_entry; ) { 
00404       int pos = 0;
00405       delim_value = NULL;
00406       delim_tot_count = 0;
00407       delim_count = 0;
00408       
00409       do { /* while delim_count */
00410 
00411          /* Starting new static var */
00412          char *ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00413          struct berval *value;
00414          while (ldap_attribute_name) {
00415          
00416             const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00417             int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00418             struct berval **values = NULL;
00419 
00420             values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
00421             if (values) {
00422                struct berval **v;
00423                char *valptr;
00424 
00425                for (v = values; *v; v++) {
00426                   value = *v;
00427                   valptr = value->bv_val;
00428                   if (is_realmed_password_attribute) {
00429                      if (strncasecmp(valptr, "{md5}", 5) == 0) {
00430                         valptr += 5;
00431                      }
00432                      ast_debug(2, "md5: %s\n", valptr);
00433                   }
00434                   if (valptr) {
00435                      if (delim_value == NULL && !is_realmed_password_attribute 
00436                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0)) {
00437 
00438                         delim_value = ast_strdup(valptr);
00439 
00440                         if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
00441                            ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value);
00442                            is_delimited = 1;
00443                         }
00444                      }
00445 
00446                      if (is_delimited != 0 && !is_realmed_password_attribute 
00447                         && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0) ) {
00448                         /* for non-Static RealTime, first */
00449 
00450                         for (i = pos; !ast_strlen_zero(valptr + i); i++) {
00451                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00452                            if (delim_value[i] == ';') {
00453                               delim_value[i] = '\0';
00454 
00455                               ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00456                      
00457                               if (prev) {
00458                                  prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00459                                  if (prev->next) {
00460                                     prev = prev->next;
00461                                  }
00462                               } else {
00463                                  prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00464                               }
00465                               pos = i + 1;
00466 
00467                               if (static_table_config == table_config) {
00468                                  break;
00469                               }
00470                            }
00471                         }
00472                         if (ast_strlen_zero(valptr + i)) {
00473                            ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count);
00474                            /* Last delimited value */
00475                            ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
00476                            if (prev) {
00477                               prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00478                               if (prev->next) {
00479                                  prev = prev->next;
00480                               }
00481                            } else {
00482                               prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
00483                            }
00484                            /* Remembering to free memory */
00485                            is_delimited = 0;
00486                            pos = 0;
00487                         }
00488                         free(delim_value);
00489                         delim_value = NULL;
00490                         
00491                         ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
00492                      } else {
00493                         /* not delimited */
00494                         if (delim_value) {
00495                            free(delim_value);
00496                            delim_value = NULL;
00497                         }
00498                         ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr);
00499 
00500                         if (prev) {
00501                            prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
00502                            if (prev->next) {
00503                               prev = prev->next;
00504                            }
00505                         } else {
00506                            prev = var = ast_variable_new(attribute_name, valptr, table_config->table_name);
00507                         }
00508                      }
00509                   }
00510                } /*!< for (v = values; *v; v++) */
00511                ldap_value_free_len(values);
00512             }/*!< if (values) */
00513             ldap_memfree(ldap_attribute_name);
00514             ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00515          } /*!< while (ldap_attribute_name) */
00516          ber_free(ber, 0);
00517          if (static_table_config == table_config) {
00518             if (option_debug > 2) {
00519                const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
00520                const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
00521                if (tmpdebug && tmpdebug2) {
00522                   ast_debug(3, "LINE(%d) Added to vars - %s = %s\n", __LINE__, tmpdebug->value, tmpdebug2->value);
00523                }
00524             }
00525             vars[entry_index++] = var;
00526             prev = NULL;
00527          }
00528 
00529          delim_count++;
00530       } while (delim_count <= delim_tot_count && static_table_config == table_config);
00531 
00532       if (static_table_config != table_config) {
00533          ast_debug(3, "LINE(%d) Added to vars - non static\n", __LINE__);
00534             
00535          vars[entry_index++] = var;
00536          prev = NULL;
00537       }
00538       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
00539    } /*!< end for loop over ldap_entry */
00540 
00541    return vars;
00542 }

static char * realtime_ldap_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1757 of file res_config_ldap.c.

References ast_cli(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.

01758 {
01759    char status[256], credentials[100] = "";
01760    int ctimesec = time(NULL) - connect_time;
01761 
01762    switch (cmd) {
01763    case CLI_INIT:
01764       e->command = "realtime show ldap status";
01765       e->usage =
01766          "Usage: realtime show ldap status\n"
01767          "         Shows connection information for the LDAP RealTime driver\n";
01768       return NULL;
01769    case CLI_GENERATE:
01770       return NULL;
01771    }
01772 
01773    if (!ldapConn)
01774       return CLI_FAILURE;
01775 
01776    if (!ast_strlen_zero(url)) 
01777       snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
01778 
01779    if (!ast_strlen_zero(user))
01780       snprintf(credentials, sizeof(credentials), " with username %s", user);
01781 
01782    if (ctimesec > 31536000) {
01783       ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
01784             status, credentials, ctimesec / 31536000,
01785             (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
01786             (ctimesec % 3600) / 60, ctimesec % 60);
01787    } else if (ctimesec > 86400) {
01788       ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
01789             status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
01790             (ctimesec % 3600) / 60, ctimesec % 60);
01791    } else if (ctimesec > 3600) {
01792       ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
01793             status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
01794             ctimesec % 60);
01795    } else if (ctimesec > 60) {
01796       ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
01797                ctimesec / 60, ctimesec % 60);
01798    } else {
01799       ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
01800    }
01801 
01802    return CLI_SUCCESS;
01803 }

static struct ast_config* realtime_multi_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static, read]

See Asterisk doc.

this function will be called for the switch statment if no match is found with the realtime_ldap function(i.e. it is a failover); however, the ast_load_realtime wil match on wildcharacters also depending on what the mode is set to this is an area of asterisk that could do with a lot of modification I think this function returns Realtime dynamic objects

Definition at line 954 of file res_config_ldap.c.

References ast_category_append(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_log(), ast_strdupa, ast_variable_append(), free, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, ldap_table_config::next, realtime_ldap_base_ap(), ast_variable::value, and var.

00956 {
00957    char *op;
00958    const char *initfield = NULL;
00959    const char *newparam, *newval;
00960    struct ast_variable **vars =
00961       realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00962    struct ast_config *cfg = NULL;
00963 
00964    newparam = va_arg(ap, const char *);
00965    newval = va_arg(ap, const char *);
00966    if (!newparam || !newval) {
00967        ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00968        return NULL;
00969    }
00970    initfield = ast_strdupa(newparam);
00971    if ((op = strchr(initfield, ' '))) {
00972       *op = '\0';
00973    }
00974 
00975    if (vars) {
00976       cfg = ast_config_new();
00977       if (!cfg) {
00978          ast_log(LOG_ERROR, "Unable to create a config!\n");
00979       } else {
00980          struct ast_variable **p = vars;
00981 
00982          while (*p) {
00983             struct ast_category *cat = NULL;
00984             cat = ast_category_new("", table_name, -1);
00985             if (!cat) {
00986                ast_log(LOG_ERROR, "Unable to create a new category!\n");
00987                break;
00988             } else {
00989                struct ast_variable *var = *p;
00990                while (var) {
00991                   struct ast_variable *next = var->next;
00992                   if (initfield && !strcmp(initfield, var->name)) {
00993                      ast_category_rename(cat, var->value);
00994                   }
00995                   var->next = NULL;
00996                   ast_variable_append(cat, var);
00997                   var = next;
00998                }
00999             }
01000             ast_category_append(cfg, cat);
01001             p++;
01002          }
01003       }
01004       free(vars);
01005    }
01006    return cfg;
01007 
01008 }

static int reload ( void   )  [static]

Definition at line 1581 of file res_config_ldap.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, ldap_lock, ldap_reconnect(), LOG_NOTICE, LOG_WARNING, and parse_config().

01582 {
01583    /* Aquire control before doing anything to the module itself. */
01584    ast_mutex_lock(&ldap_lock);
01585 
01586    if (ldapConn) {
01587       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01588       ldapConn = NULL;
01589    }
01590 
01591    if (parse_config() < 0) {
01592       ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
01593       ast_mutex_unlock(&ldap_lock);
01594       return 0;
01595    }     
01596 
01597    if (!ldap_reconnect())  {
01598       ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
01599    }
01600 
01601    ast_verb(2, "LDAP RealTime driver reloaded.\n");
01602 
01603    /* Done reloading. Release lock so others can now use driver. */
01604    ast_mutex_unlock(&ldap_lock);
01605 
01606    return 0;
01607 }

static int replace_string_in_string ( char *  string,
const char *  search,
const char *  by 
) [static]

Replace <search> by <by> in string.

Note:
No check is done on string allocated size !

Definition at line 671 of file res_config_ldap.c.

Referenced by append_var_and_value_to_filter().

00672 {
00673    int search_len = strlen(search);
00674    int by_len = strlen(by);
00675    int replaced = 0;
00676    char *p = strstr(string, search);
00677 
00678    if (p) {
00679       replaced = 1;
00680       while (p) {
00681          if (by_len == search_len) {
00682             memcpy(p, by, by_len);
00683          } else {
00684             memmove(p + by_len, p + search_len, strlen(p + search_len) + 1);
00685             memcpy(p, by, by_len);
00686          }
00687          p = strstr(p + by_len, search);
00688       }
00689    }
00690    return replaced;
00691 }

static int semicolon_count_str ( const char *  somestr  )  [static]

for the semicolon delimiter

Parameters:
somestr - pointer to a string
Returns:
number of occurances of the delimiter(semicolon)

Definition at line 153 of file res_config_ldap.c.

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

00154 {
00155    int count = 0;
00156 
00157    for (; *somestr; somestr++) {
00158       if (*somestr == ';')
00159          count++;
00160    }
00161 
00162    return count;
00163 } 

static int semicolon_count_var ( struct ast_variable var  )  [static]

Definition at line 168 of file res_config_ldap.c.

References ast_debug, semicolon_count_str(), ast_variable::value, and variable_named().

Referenced by realtime_ldap_result_to_vars().

00169 {
00170    struct ast_variable *var_value = variable_named(var, "variable_value");
00171 
00172    if (!var_value) {
00173       return 0;
00174    }
00175 
00176    ast_debug(2, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value);
00177 
00178    return semicolon_count_str(var_value->value);
00179 }

static char* substituted ( struct ast_channel channel,
const char *  string 
) [static]
Note:
caller should free returned pointer

Definition at line 629 of file res_config_ldap.c.

References ast_calloc, ast_debug, ast_strlen_zero(), MAXRESULT, and pbx_substitute_variables_helper().

Referenced by cleaned_basedn().

00630 {
00631 #define MAXRESULT 2048
00632    char *ret_string = NULL;
00633 
00634    if (!ast_strlen_zero(string)) {
00635       ret_string = ast_calloc(1, MAXRESULT);
00636       pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
00637    }
00638    ast_debug(2, "substituted: string: '%s' => '%s' \n", string, ret_string);
00639    return ret_string;
00640 }

static struct ldap_table_config* table_config_for_table_name ( const char *  table_name  )  [static, read]

Find a table_config - Should be locked before using it.

Note:
This function assumes ldap_lock to be locked.

Definition at line 125 of file res_config_ldap.c.

References AST_LIST_TRAVERSE, ldap_table_config::entry, and ldap_table_config::table_name.

Referenced by parse_config(), realtime_ldap_base_ap(), update2_ldap(), and update_ldap().

00126 {
00127    struct ldap_table_config *c = NULL;
00128 
00129    AST_LIST_TRAVERSE(&table_configs, c, entry) {
00130       if (!strcmp(c->table_name, table_name))
00131          break;
00132    }
00133 
00134    return c;
00135 }

static struct ldap_table_config* table_config_new ( const char *  table_name  )  [static, read]

Create a new table_config.

Definition at line 106 of file res_config_ldap.c.

References ast_calloc, ast_strdup, free, and ldap_table_config::table_name.

Referenced by parse_config().

00107 {
00108    struct ldap_table_config *p;
00109 
00110    if (!(p = ast_calloc(1, sizeof(*p))))
00111       return NULL;
00112 
00113    if (table_name) {
00114       if (!(p->table_name = ast_strdup(table_name))) {
00115          free(p);
00116          return NULL;
00117       }
00118    }
00119 
00120    return p;
00121 }

static void table_configs_free ( void   )  [static]

Free table_config.

Note:
assumes ldap_lock to be locked

Definition at line 203 of file res_config_ldap.c.

References ldap_table_config::additional_filter, ast_free, AST_LIST_REMOVE_HEAD, ast_variables_destroy(), ldap_table_config::attributes, base_table_config, ldap_table_config::entry, free, static_table_config, and ldap_table_config::table_name.

Referenced by parse_config(), and unload_module().

00204 {
00205    struct ldap_table_config *c;
00206 
00207    while ((c = AST_LIST_REMOVE_HEAD(&table_configs, entry))) {
00208       if (c->table_name) {
00209          ast_free(c->table_name);
00210       }
00211       if (c->additional_filter) {
00212          ast_free(c->additional_filter);
00213       }
00214       if (c->attributes) {
00215          ast_variables_destroy(c->attributes);
00216       }
00217       free(c);
00218    }
00219 
00220    base_table_config = NULL;
00221    static_table_config = NULL;
00222 }

static int unload_module ( void   )  [static]

Definition at line 1560 of file res_config_ldap.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_config_engine_deregister(), ast_mutex_lock, ast_mutex_unlock, ast_verb, ldap_cli, ldap_engine, ldap_lock, and table_configs_free().

01561 {
01562    /* Aquire control before doing anything to the module itself. */
01563    ast_mutex_lock(&ldap_lock);
01564 
01565    table_configs_free();
01566 
01567    if (ldapConn) {
01568       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01569       ldapConn = NULL;
01570    }
01571    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01572    ast_config_engine_deregister(&ldap_engine);
01573    ast_verb(1, "LDAP RealTime driver unloaded.\n");
01574 
01575    /* Unlock so something else can destroy the lock. */
01576    ast_mutex_unlock(&ldap_lock);
01577 
01578    return 0;
01579 }

static int update2_ldap ( const char *  basedn,
const char *  table_name,
va_list  ap 
) [static]

Definition at line 1343 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_realloc, ast_str_append(), ast_str_buffer(), ast_str_create(), base_table_config, cleaned_basedn(), convert_attribute_name_to_ldap(), filter(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

01344 {
01345    int error = 0;
01346    LDAPMessage *ldap_entry = NULL;
01347    LDAPMod **ldap_mods;
01348    const char *newparam = NULL;
01349    const char *newval = NULL;
01350    char *dn;
01351    int num_entries = 0;
01352    int i = 0;
01353    int mods_size = 0;
01354    int mod_exists = 0;
01355    struct ldap_table_config *table_config = NULL;
01356    char *clean_basedn = NULL;
01357    struct ast_str *filter = NULL;
01358    int tries = 0;
01359    int result = 0;
01360    LDAPMessage *ldap_result_msg = NULL;
01361 
01362    if (!table_name) {
01363       ast_log(LOG_ERROR, "No table_name specified.\n");
01364       return -1;
01365    } 
01366 
01367    if (!(filter = ast_str_create(80))) {
01368       return -1;
01369    }
01370 
01371    ast_mutex_lock(&ldap_lock);
01372 
01373    /* We now have our complete statement; Lets connect to the server and execute it.  */
01374    if (!ldap_reconnect()) {
01375       ast_mutex_unlock(&ldap_lock);
01376       ast_free(filter);
01377       return -1;
01378    }
01379 
01380    table_config = table_config_for_table_name(table_name);
01381    if (!table_config) {
01382       ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
01383       ast_mutex_unlock(&ldap_lock);
01384       ast_free(filter);
01385       return -1;
01386    }
01387 
01388    clean_basedn = cleaned_basedn(NULL, basedn);
01389 
01390    /* Create the filter with the table additional filter and the parameter/value pairs we were given */
01391    ast_str_append(&filter, 0, "(&");
01392    if (table_config && table_config->additional_filter) {
01393       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
01394    }
01395    if (table_config != base_table_config && base_table_config
01396       && base_table_config->additional_filter) {
01397       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
01398    }
01399 
01400    /* Get multiple lookup keyfields and values */
01401    while ((newparam = va_arg(ap, const char *))) {
01402       newval = va_arg(ap, const char *);
01403       append_var_and_value_to_filter(&filter, table_config, newparam, newval);
01404    }
01405    ast_str_append(&filter, 0, ")");
01406 
01407    /* Create the modification array with the parameter/value pairs we were given, 
01408     * if there are several parameters with the same name, we collect them into 
01409     * one parameter/value pair and delimit them with a semicolon */
01410    newparam = va_arg(ap, const char *);
01411    newparam = convert_attribute_name_to_ldap(table_config, newparam);
01412    newval = va_arg(ap, const char *);
01413    if (!newparam || !newval) {
01414       ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
01415       ast_free(filter);
01416       ast_free(clean_basedn);
01417       return -1;
01418    }
01419 
01420    mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
01421    ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
01422    ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
01423 
01424    ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
01425    ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01426    strcpy(ldap_mods[0]->mod_type, newparam);
01427 
01428    ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2);
01429    ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
01430    strcpy(ldap_mods[0]->mod_values[0], newval);
01431 
01432    while ((newparam = va_arg(ap, const char *))) {
01433       newparam = convert_attribute_name_to_ldap(table_config, newparam);
01434       newval = va_arg(ap, const char *);
01435       mod_exists = 0;
01436 
01437       for (i = 0; i < mods_size - 1; i++) {
01438          if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
01439             /* We have the parameter allready, adding the value as a semicolon delimited value */
01440             ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
01441             strcat(ldap_mods[i]->mod_values[0], ";");
01442             strcat(ldap_mods[i]->mod_values[0], newval);
01443             mod_exists = 1;   
01444             break;
01445          }
01446       }
01447 
01448       /* create new mod */
01449       if (!mod_exists) {
01450          mods_size++;
01451          ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
01452          ldap_mods[mods_size - 1] = NULL;
01453          ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
01454 
01455          ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
01456 
01457          ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01458          strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
01459 
01460          ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
01461          ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
01462          strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
01463       }
01464    }
01465    /* freeing ldap_mods further down */
01466 
01467    do {
01468       /* freeing ldap_result further down */
01469       result = ldap_search_ext_s(ldapConn, clean_basedn,
01470               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
01471               &ldap_result_msg);
01472       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
01473          ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
01474          tries++;
01475          if (tries < 3) {
01476             usleep(500000L * tries);
01477             if (ldapConn) {
01478                ldap_unbind_ext_s(ldapConn, NULL, NULL);
01479                ldapConn = NULL;
01480             }
01481             if (!ldap_reconnect()) {
01482                break;
01483             }
01484          }
01485       }
01486    } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
01487 
01488    if (result != LDAP_SUCCESS) {
01489       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
01490       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
01491 
01492       ast_mutex_unlock(&ldap_lock);
01493       ast_free(filter);
01494       ast_free(clean_basedn);
01495       ldap_msgfree(ldap_result_msg);
01496       ldap_mods_free(ldap_mods, 0);
01497       return -1;
01498    }
01499    /* Ready to update */
01500    if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
01501       for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
01502          ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
01503       }
01504 
01505       ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
01506 
01507       for (i = 0; ldap_entry; i++) { 
01508          dn = ldap_get_dn(ldapConn, ldap_entry);
01509          if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)  {
01510             ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
01511          }
01512          ldap_memfree(dn);
01513          ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
01514       }
01515    }
01516 
01517    ast_mutex_unlock(&ldap_lock);
01518    if (filter) {
01519       ast_free(filter);
01520    }
01521    if (clean_basedn) {
01522       ast_free(clean_basedn);
01523    }
01524    ldap_msgfree(ldap_result_msg);
01525    ldap_mods_free(ldap_mods, 0);
01526    return num_entries;
01527 }

static int update_ldap ( const char *  basedn,
const char *  table_name,
const char *  attribute,
const char *  lookup,
va_list  ap 
) [static]

Definition at line 1159 of file res_config_ldap.c.

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_create(), base_table_config, cleaned_basedn(), convert_attribute_name_to_ldap(), filter(), free, is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, option_debug, and table_config_for_table_name().

01161 {
01162    int error = 0;
01163    LDAPMessage *ldap_entry = NULL;
01164    LDAPMod **ldap_mods;
01165    const char *newparam = NULL;
01166    const char *newval = NULL;
01167    char *dn;
01168    int num_entries = 0;
01169    int i = 0;
01170    int mods_size = 0;
01171    int mod_exists = 0;
01172    struct ldap_table_config *table_config = NULL;
01173    char *clean_basedn = NULL;
01174    struct ast_str *filter = NULL;
01175    int tries = 0;
01176    int result = 0;
01177    LDAPMessage *ldap_result_msg = NULL;
01178 
01179    if (!table_name) {
01180       ast_log(LOG_ERROR, "No table_name specified.\n");
01181       return -1;
01182    } 
01183 
01184    if (!(filter = ast_str_create(80))) {
01185       return -1;
01186    }
01187 
01188    if (!attribute || !lookup) {
01189       ast_log(LOG_WARNING, "LINE(%d): search parameters are empty.\n", __LINE__);
01190       return -1;
01191    }
01192    ast_mutex_lock(&ldap_lock);
01193 
01194    /* We now have our complete statement; Lets connect to the server and execute it.  */
01195    if (!ldap_reconnect()) {
01196       ast_mutex_unlock(&ldap_lock);
01197       return -1;
01198    }
01199 
01200    table_config = table_config_for_table_name(table_name);
01201    if (!table_config) {
01202       ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
01203       ast_mutex_unlock(&ldap_lock);
01204       return -1;
01205    }
01206 
01207    clean_basedn = cleaned_basedn(NULL, basedn);
01208 
01209    /* Create the filter with the table additional filter and the parameter/value pairs we were given */
01210    ast_str_append(&filter, 0, "(&");
01211    if (table_config && table_config->additional_filter) {
01212       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
01213    }
01214    if (table_config != base_table_config && base_table_config && base_table_config->additional_filter) {
01215       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
01216    }
01217    append_var_and_value_to_filter(&filter, table_config, attribute, lookup);
01218    ast_str_append(&filter, 0, ")");
01219 
01220    /* Create the modification array with the parameter/value pairs we were given, 
01221     * if there are several parameters with the same name, we collect them into 
01222     * one parameter/value pair and delimit them with a semicolon */
01223    newparam = va_arg(ap, const char *);
01224    newparam = convert_attribute_name_to_ldap(table_config, newparam);
01225    newval = va_arg(ap, const char *);
01226    if (!newparam || !newval) {
01227       ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
01228       return -1;
01229    }
01230 
01231    mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
01232    ldap_mods = ldap_memcalloc(sizeof(LDAPMod *), mods_size);
01233    ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod));
01234 
01235    ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
01236    ldap_mods[0]->mod_type = ldap_strdup(newparam);
01237 
01238    ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2);
01239    ldap_mods[0]->mod_values[0] = ldap_strdup(newval);
01240 
01241    while ((newparam = va_arg(ap, const char *))) {
01242       newparam = convert_attribute_name_to_ldap(table_config, newparam);
01243       newval = va_arg(ap, const char *);
01244       mod_exists = 0;
01245 
01246       for (i = 0; i < mods_size - 1; i++) {
01247          if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
01248             /* We have the parameter allready, adding the value as a semicolon delimited value */
01249             ldap_mods[i]->mod_values[0] = ldap_memrealloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(newval) + 2));
01250             strcat(ldap_mods[i]->mod_values[0], ";");
01251             strcat(ldap_mods[i]->mod_values[0], newval);
01252             mod_exists = 1;   
01253             break;
01254          }
01255       }
01256 
01257       /* create new mod */
01258       if (!mod_exists) {
01259          mods_size++;
01260          ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
01261          ldap_mods[mods_size - 1] = NULL;
01262          
01263          ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod));
01264 
01265          ldap_mods[mods_size - 2]->mod_type = ldap_memcalloc(sizeof(char), strlen(newparam) + 1);
01266          strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
01267 
01268          if (strlen(newval) == 0) {
01269             ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE;
01270          } else {
01271             ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
01272 
01273             ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(sizeof(char *), 2);
01274             ldap_mods[mods_size - 2]->mod_values[0] = ldap_memcalloc(sizeof(char), strlen(newval) + 1);
01275             strcpy(ldap_mods[mods_size - 2]->mod_values[0], newval);
01276          }
01277       }
01278    }
01279    /* freeing ldap_mods further down */
01280 
01281    do {
01282       /* freeing ldap_result further down */
01283       result = ldap_search_ext_s(ldapConn, clean_basedn,
01284               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
01285               &ldap_result_msg);
01286       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
01287          ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
01288          tries++;
01289          if (tries < 3) {
01290             usleep(500000L * tries);
01291             if (ldapConn) {
01292                ldap_unbind_ext_s(ldapConn, NULL, NULL);
01293                ldapConn = NULL;
01294             }
01295             if (!ldap_reconnect())
01296                break;
01297          }
01298       }
01299    } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
01300 
01301    if (result != LDAP_SUCCESS) {
01302       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
01303       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
01304 
01305       ast_mutex_unlock(&ldap_lock);
01306       free(filter);
01307       free(clean_basedn);
01308       ldap_msgfree(ldap_result_msg);
01309       ldap_mods_free(ldap_mods, 0);
01310       return -1;
01311    }
01312    /* Ready to update */
01313    if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
01314       ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries);
01315       for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
01316          if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) {
01317             ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
01318          } else {
01319             ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type);
01320          }
01321       }
01322       ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
01323 
01324       for (i = 0; ldap_entry; i++) { 
01325          dn = ldap_get_dn(ldapConn, ldap_entry);
01326          if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)  {
01327             ast_log(LOG_ERROR, "Couldn't modify '%s'='%s', dn:%s because %s\n",
01328                   attribute, lookup, dn, ldap_err2string(error));
01329          }
01330          ldap_memfree(dn);
01331          ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
01332       }
01333    }
01334 
01335    ast_mutex_unlock(&ldap_lock);
01336    ast_free(filter);
01337    ast_free(clean_basedn);
01338    ldap_msgfree(ldap_result_msg);
01339    ldap_mods_free(ldap_mods, 0);
01340    return num_entries;
01341 }

static struct ast_variable* variable_named ( struct ast_variable var,
const char *  name 
) [static, read]

Find variable by name.

Definition at line 138 of file res_config_ldap.c.

References ast_variable::name, and ast_variable::next.

Referenced by config_ldap(), realtime_ldap_result_to_vars(), and semicolon_count_var().

00139 {
00140    for (; var; var = var->next) {
00141       if (!strcasecmp(name, var->name))
00142          break;
00143    }
00144 
00145    return var;
00146 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "LDAP realtime interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static]

Definition at line 1810 of file res_config_ldap.c.

Definition at line 1810 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 70 of file res_config_ldap.c.

time_t connect_time [static]

Definition at line 72 of file res_config_ldap.c.

struct ast_cli_entry ldap_cli[] [static]
Initial value:
 {
   AST_CLI_DEFINE(realtime_ldap_status, "Shows connection information for the LDAP RealTime driver"),
}

Definition at line 101 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

struct ast_config_engine ldap_engine [static]

Definition at line 1529 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]
LDAP* ldapConn [static]

Definition at line 66 of file res_config_ldap.c.

char pass[512] [static]
char url[512] [static]
char user[512] [static]

Definition at line 68 of file res_config_ldap.c.

int version [static]

Definition at line 71 of file res_config_ldap.c.


Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1