Thu Oct 11 06:37:01 2012

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"

Include dependency graph for res_config_ldap.c:

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)
 Load the module.
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 = AST_BUILDOPT_SUM, .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_MUTEX_INITIALIZER , 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>

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 71 of file res_config_ldap.c.

Referenced by config_ldap(), and parse_config().

#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Definition at line 72 of file res_config_ldap.c.

Referenced by parse_config().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1837 of file res_config_ldap.c.

static void __unreg_module ( void   )  [static]

Definition at line 1837 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 703 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().

00706 {
00707    char *new_name = NULL;
00708    char *new_value = NULL;
00709    char *like_pos = strstr(name, " LIKE");
00710 
00711    ast_debug(2, "name='%s' value='%s'\n", name, value);
00712 
00713    if (like_pos) {
00714       int len = like_pos - name;
00715 
00716       name = new_name = ast_strdupa(name);
00717       new_name[len] = '\0';
00718       value = new_value = ast_strdupa(value);
00719       replace_string_in_string(new_value, "\\_", "_");
00720       replace_string_in_string(new_value, "%", "*");
00721    }
00722 
00723    name = convert_attribute_name_to_ldap(table_config, name);
00724 
00725    ast_str_append(filter, 0, "(%s=%s)", name, value);
00726 }

static char* cleaned_basedn ( struct ast_channel channel,
const char *  basedn 
) [static]

Note:
caller should free returned pointer

Definition at line 652 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().

00653 {
00654    char *cbasedn = NULL;
00655    if (basedn) {
00656       char *p = NULL;
00657       cbasedn = substituted(channel, basedn);
00658       if (*cbasedn == '"') {
00659          cbasedn++;
00660          if (!ast_strlen_zero(cbasedn)) {
00661             int len = strlen(cbasedn);
00662             if (cbasedn[len - 1] == '"')
00663                cbasedn[len - 1] = '\0';
00664 
00665          }
00666       }
00667       p = cbasedn;
00668       while (*p) {
00669          if (*p == '|')
00670             *p = ',';
00671          p++;
00672       }
00673    }
00674    ast_debug(2, "basedn: '%s' => '%s' \n", basedn, cbasedn);
00675    return cbasedn;
00676 }

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 1035 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().

01036 {
01037    const struct category_and_metric *as = a;
01038    const struct category_and_metric *bs = b;
01039 
01040    if (as->metric < bs->metric) {
01041       return -1;
01042    } else if (as->metric > bs->metric) {
01043       return 1;
01044    } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
01045       return strcmp(as->name, bs->name);
01046    } 
01047    /* if the metric and the category name is the same, we check the variable metric */
01048    if (as->var_metric < bs->var_metric) {
01049       return -1;
01050    } else if (as->var_metric > bs->var_metric) {
01051       return 1;
01052    }
01053 
01054    return 0;
01055 }

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 1064 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.

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

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 261 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().

00263 {
00264    int i = 0;
00265    struct ldap_table_config *configs[] = { table_config, base_table_config };
00266 
00267    for (i = 0; i < ARRAY_LEN(configs); i++) {
00268       struct ast_variable *attribute;
00269 
00270       if (!configs[i]) {
00271          continue;
00272       }
00273 
00274       attribute = configs[i]->attributes;
00275       for (; attribute; attribute = attribute->next) {
00276          if (strcasecmp(attribute_name, attribute->value) == 0) {
00277             return attribute->name;
00278          }
00279       }
00280    }
00281 
00282    return attribute_name;
00283 }

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 235 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().

00237 {
00238    int i = 0;
00239    struct ldap_table_config *configs[] = { table_config, base_table_config };
00240 
00241    for (i = 0; i < ARRAY_LEN(configs); i++) {
00242       struct ast_variable *attribute;
00243 
00244       if (!configs[i]) {
00245          continue;
00246       }
00247 
00248       attribute = configs[i]->attributes;
00249       for (; attribute; attribute = attribute->next) {
00250          if (!strcasecmp(attribute_name, attribute->name)) {
00251             return attribute->value;
00252          }
00253       }
00254    }
00255 
00256    return attribute_name;
00257 }

static int is_ldap_connect_error ( int  err  )  [static]

Check if we have a connection error.

Definition at line 555 of file res_config_ldap.c.

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

00556 {
00557    return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
00558 }

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 563 of file res_config_ldap.c.

References ast_debug, ast_free, ast_log(), ast_mutex_unlock, 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().

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

static int ldap_reconnect ( void   )  [static]

Note:
ldap_lock should have been locked before calling this function.

Definition at line 1737 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().

01738 {
01739    int bind_result = 0;
01740    struct berval cred;
01741 
01742    if (ldapConn) {
01743       ast_debug(2, "Everything seems fine.\n");
01744       return 1;
01745    }
01746 
01747    if (ast_strlen_zero(url)) {
01748       ast_log(LOG_ERROR, "Not enough parameters to connect to ldap directory\n");
01749       return 0;
01750    }
01751 
01752    if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
01753       ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
01754       return 0;
01755    }
01756 
01757    if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
01758       ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
01759    }
01760 
01761    if (!ast_strlen_zero(user)) {
01762       ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
01763       cred.bv_val = (char *) pass;
01764       cred.bv_len = strlen(pass);
01765       bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01766    } else {
01767       ast_debug(2, "bind %s anonymously\n", url);
01768       cred.bv_val = NULL;
01769       cred.bv_len = 0;
01770       bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01771    }
01772    if (bind_result == LDAP_SUCCESS) {
01773       ast_debug(2, "Successfully connected to directory.\n");
01774       connect_time = time(NULL);
01775       return 1;
01776    } else {
01777       ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
01778       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01779       ldapConn = NULL;
01780       return 0;
01781    }
01782 }

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 192 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().

00194 {
00195    struct ast_variable *var;
00196 
00197    if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value)) {
00198       return;
00199    }
00200 
00201    if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->table_name))) {
00202       return;
00203    }
00204 
00205    if (table_config->attributes) {
00206       var->next = table_config->attributes;
00207    }
00208    table_config->attributes = var;
00209 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1565 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().

01566 {
01567    if (parse_config() < 0) {
01568       ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
01569       return 0;
01570    }
01571 
01572    ast_mutex_lock(&ldap_lock);
01573 
01574    if (!ldap_reconnect())  {
01575       ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
01576    }
01577 
01578    ast_config_engine_register(&ldap_engine);
01579    ast_verb(1, "LDAP RealTime driver loaded.\n");
01580    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01581 
01582    ast_mutex_unlock(&ldap_lock);
01583 
01584    return 0;
01585 }

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1637 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.

01638 {
01639    struct ast_config *config;
01640    struct ast_flags config_flags = {0};
01641    const char *s, *host;
01642    int port;
01643    char *category_name = NULL;
01644 
01645    /* Make sure that global variables are reset */
01646    url[0] = '\0';
01647    user[0] = '\0';
01648    pass[0] = '\0';
01649    base_distinguished_name[0] = '\0';
01650    version = 3;
01651 
01652    config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
01653    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01654       ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
01655       return -1;
01656    }
01657 
01658    if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
01659       ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
01660       user[0] = '\0';
01661    } else {
01662       ast_copy_string(user, s, sizeof(user));
01663    }
01664 
01665    if (!ast_strlen_zero(user)) {
01666       if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
01667          ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
01668          ast_copy_string(pass, "asterisk", sizeof(pass));
01669       } else {
01670          ast_copy_string(pass, s, sizeof(pass));
01671       }
01672    }
01673 
01674    /* URL is preferred, use host and port if not found */
01675    if ((s = ast_variable_retrieve(config, "_general", "url"))) {
01676       ast_copy_string(url, s, sizeof(url));
01677    } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
01678       if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
01679          ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
01680          port = 389;
01681       }
01682 
01683       snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
01684    } else {
01685       ast_log(LOG_ERROR, "No directory URL or host found.\n");
01686       ast_config_destroy(config);
01687       return -1;
01688    }
01689 
01690    if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
01691       ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
01692       ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
01693    } else 
01694       ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));
01695 
01696    if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
01697       ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
01698    } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
01699       ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
01700       version = 3;
01701    }
01702 
01703    table_configs_free();
01704 
01705    while ((category_name = ast_category_browse(config, category_name))) {
01706       int is_general = (strcasecmp(category_name, "_general") == 0);
01707       int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
01708       struct ast_variable *var = ast_variable_browse(config, category_name);
01709       
01710       if (var) {
01711          struct ldap_table_config *table_config =
01712             table_config_for_table_name(category_name);
01713          if (!table_config) {
01714             table_config = table_config_new(category_name);
01715             AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
01716             if (is_general)
01717                base_table_config = table_config;
01718             if (is_config)
01719                static_table_config = table_config;
01720          }
01721          for (; var; var = var->next) {
01722             if (!strcasecmp(var->name, "additionalFilter")) {
01723                table_config->additional_filter = ast_strdup(var->value);
01724             } else {
01725                ldap_table_config_add_attribute(table_config, var->name, var->value);
01726             }
01727          }
01728       }
01729    }
01730 
01731    ast_config_destroy(config);
01732 
01733    return 1;
01734 }

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 935 of file res_config_ldap.c.

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

00937 {
00938    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00939    struct ast_variable *var = NULL;
00940 
00941    if (vars) {
00942       struct ast_variable *last_var = NULL;
00943       struct ast_variable **p = vars;
00944 
00945       /* Chain the vars array of lists into one list to return. */
00946       while (*p) {
00947          if (last_var) {
00948             while (last_var->next) {
00949                last_var = last_var->next;
00950             }
00951             last_var->next = *p;
00952          } else {
00953             var = *p;
00954             last_var = var;
00955          }
00956          p++;
00957       }
00958       free(vars);
00959    }
00960    return var;
00961 }

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 918 of file res_config_ldap.c.

References realtime_ldap_base_ap().

Referenced by config_ldap().

00920 {
00921    struct ast_variable **vars = NULL;
00922    va_list ap;
00923 
00924    va_start(ap, table_name);
00925    vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, ap);
00926    va_end(ap);
00927 
00928    return vars;
00929 }

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

Todo:
XXX The interactions with base_var and append_var may cause a memory leak of base_var nodes. Also the append_var list and base_var list may get cross linked.

Definition at line 736 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_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().

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

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 289 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().

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

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 371 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().

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

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

Definition at line 1784 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.

01785 {
01786    char status[256], credentials[100] = "";
01787    int ctimesec = time(NULL) - connect_time;
01788 
01789    switch (cmd) {
01790    case CLI_INIT:
01791       e->command = "realtime show ldap status";
01792       e->usage =
01793          "Usage: realtime show ldap status\n"
01794          "         Shows connection information for the LDAP RealTime driver\n";
01795       return NULL;
01796    case CLI_GENERATE:
01797       return NULL;
01798    }
01799 
01800    if (!ldapConn)
01801       return CLI_FAILURE;
01802 
01803    if (!ast_strlen_zero(url)) 
01804       snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
01805 
01806    if (!ast_strlen_zero(user))
01807       snprintf(credentials, sizeof(credentials), " with username %s", user);
01808 
01809    if (ctimesec > 31536000) {
01810       ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
01811             status, credentials, ctimesec / 31536000,
01812             (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
01813             (ctimesec % 3600) / 60, ctimesec % 60);
01814    } else if (ctimesec > 86400) {
01815       ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
01816             status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
01817             (ctimesec % 3600) / 60, ctimesec % 60);
01818    } else if (ctimesec > 3600) {
01819       ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
01820             status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
01821             ctimesec % 60);
01822    } else if (ctimesec > 60) {
01823       ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
01824                ctimesec / 60, ctimesec % 60);
01825    } else {
01826       ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
01827    }
01828 
01829    return CLI_SUCCESS;
01830 }

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 970 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.

00972 {
00973    char *op;
00974    const char *initfield = NULL;
00975    const char *newparam, *newval;
00976    struct ast_variable **vars =
00977       realtime_ldap_base_ap(NULL, basedn, table_name, ap);
00978    struct ast_config *cfg = NULL;
00979 
00980    newparam = va_arg(ap, const char *);
00981    newval = va_arg(ap, const char *);
00982    if (!newparam || !newval) {
00983        ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00984        return NULL;
00985    }
00986    initfield = ast_strdupa(newparam);
00987    if ((op = strchr(initfield, ' '))) {
00988       *op = '\0';
00989    }
00990 
00991    if (vars) {
00992       cfg = ast_config_new();
00993       if (!cfg) {
00994          ast_log(LOG_ERROR, "Unable to create a config!\n");
00995       } else {
00996          struct ast_variable **p = vars;
00997 
00998          while (*p) {
00999             struct ast_category *cat = NULL;
01000             cat = ast_category_new("", table_name, -1);
01001             if (!cat) {
01002                ast_log(LOG_ERROR, "Unable to create a new category!\n");
01003                break;
01004             } else {
01005                struct ast_variable *var = *p;
01006                while (var) {
01007                   struct ast_variable *next = var->next;
01008                   if (initfield && !strcmp(initfield, var->name)) {
01009                      ast_category_rename(cat, var->value);
01010                   }
01011                   var->next = NULL;
01012                   ast_variable_append(cat, var);
01013                   var = next;
01014                }
01015             }
01016             ast_category_append(cfg, cat);
01017             p++;
01018          }
01019       }
01020       free(vars);
01021    }
01022    return cfg;
01023 
01024 }

static int reload ( void   )  [static]

Definition at line 1608 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().

01609 {
01610    /* Aquire control before doing anything to the module itself. */
01611    ast_mutex_lock(&ldap_lock);
01612 
01613    if (ldapConn) {
01614       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01615       ldapConn = NULL;
01616    }
01617 
01618    if (parse_config() < 0) {
01619       ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
01620       ast_mutex_unlock(&ldap_lock);
01621       return 0;
01622    }     
01623 
01624    if (!ldap_reconnect())  {
01625       ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
01626    }
01627 
01628    ast_verb(2, "LDAP RealTime driver reloaded.\n");
01629 
01630    /* Done reloading. Release lock so others can now use driver. */
01631    ast_mutex_unlock(&ldap_lock);
01632 
01633    return 0;
01634 }

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 680 of file res_config_ldap.c.

Referenced by append_var_and_value_to_filter().

00681 {
00682    int search_len = strlen(search);
00683    int by_len = strlen(by);
00684    int replaced = 0;
00685    char *p = strstr(string, search);
00686 
00687    if (p) {
00688       replaced = 1;
00689       while (p) {
00690          if (by_len == search_len) {
00691             memcpy(p, by, by_len);
00692          } else {
00693             memmove(p + by_len, p + search_len, strlen(p + search_len) + 1);
00694             memcpy(p, by, by_len);
00695          }
00696          p = strstr(p + by_len, search);
00697       }
00698    }
00699    return replaced;
00700 }

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 163 of file res_config_ldap.c.

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

00164 {
00165    int count = 0;
00166 
00167    for (; *somestr; somestr++) {
00168       if (*somestr == ';')
00169          count++;
00170    }
00171 
00172    return count;
00173 }

static int semicolon_count_var ( struct ast_variable var  )  [static]

Definition at line 178 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().

00179 {
00180    struct ast_variable *var_value = variable_named(var, "variable_value");
00181 
00182    if (!var_value) {
00183       return 0;
00184    }
00185 
00186    ast_debug(2, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value);
00187 
00188    return semicolon_count_str(var_value->value);
00189 }

static char* substituted ( struct ast_channel channel,
const char *  string 
) [static]

Note:
caller should free returned pointer

Definition at line 638 of file res_config_ldap.c.

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

Referenced by cleaned_basedn().

00639 {
00640 #define MAXRESULT 2048
00641    char *ret_string = NULL;
00642 
00643    if (!ast_strlen_zero(string)) {
00644       ret_string = ast_calloc(1, MAXRESULT);
00645       pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
00646    }
00647    ast_debug(2, "substituted: string: '%s' => '%s' \n", string, ret_string);
00648    return ret_string;
00649 }

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 135 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().

00136 {
00137    struct ldap_table_config *c = NULL;
00138 
00139    AST_LIST_TRAVERSE(&table_configs, c, entry) {
00140       if (!strcmp(c->table_name, table_name))
00141          break;
00142    }
00143 
00144    return c;
00145 }

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

Create a new table_config.

Definition at line 116 of file res_config_ldap.c.

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

Referenced by parse_config().

00117 {
00118    struct ldap_table_config *p;
00119 
00120    if (!(p = ast_calloc(1, sizeof(*p))))
00121       return NULL;
00122 
00123    if (table_name) {
00124       if (!(p->table_name = ast_strdup(table_name))) {
00125          free(p);
00126          return NULL;
00127       }
00128    }
00129 
00130    return p;
00131 }

static void table_configs_free ( void   )  [static]

Free table_config.

Note:
assumes ldap_lock to be locked

Definition at line 213 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().

00214 {
00215    struct ldap_table_config *c;
00216 
00217    while ((c = AST_LIST_REMOVE_HEAD(&table_configs, entry))) {
00218       if (c->table_name) {
00219          ast_free(c->table_name);
00220       }
00221       if (c->additional_filter) {
00222          ast_free(c->additional_filter);
00223       }
00224       if (c->attributes) {
00225          ast_variables_destroy(c->attributes);
00226       }
00227       free(c);
00228    }
00229 
00230    base_table_config = NULL;
00231    static_table_config = NULL;
00232 }

static int unload_module ( void   )  [static]

Definition at line 1587 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().

01588 {
01589    /* Aquire control before doing anything to the module itself. */
01590    ast_mutex_lock(&ldap_lock);
01591 
01592    table_configs_free();
01593 
01594    if (ldapConn) {
01595       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01596       ldapConn = NULL;
01597    }
01598    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01599    ast_config_engine_deregister(&ldap_engine);
01600    ast_verb(1, "LDAP RealTime driver unloaded.\n");
01601 
01602    /* Unlock so something else can destroy the lock. */
01603    ast_mutex_unlock(&ldap_lock);
01604 
01605    return 0;
01606 }

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

Definition at line 1360 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().

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

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

Definition at line 1176 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(), ast_strdup, 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().

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

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

Find variable by name.

Definition at line 148 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().

00149 {
00150    for (; var; var = var->next) {
00151       if (!strcasecmp(name, var->name))
00152          break;
00153    }
00154 
00155    return var;
00156 }


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, } [static]

Definition at line 1837 of file res_config_ldap.c.

Definition at line 1837 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 80 of file res_config_ldap.c.

time_t connect_time [static]

Definition at line 82 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 111 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

struct ast_config_engine ldap_engine [static]

Definition at line 1546 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

ast_mutex_t ldap_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

LDAP* ldapConn [static]

Definition at line 76 of file res_config_ldap.c.

char pass[512] [static]

char url[512] [static]

char user[512] [static]

Definition at line 78 of file res_config_ldap.c.

int version [static]

Definition at line 81 of file res_config_ldap.c.


Generated on Thu Oct 11 06:37:02 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6