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 Realtime Documentation.
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.
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.
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
static int load_module (void)
 Load the module.
static int parse_config (void)
 parse the configuration file
static struct ast_variablerealtime_arguments_to_fields (va_list ap)
static struct ast_variablerealtime_ldap (const char *basedn, const char *table_name, const struct ast_variable *fields)
 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, const struct ast_variable *fields)
 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)
 Realtime Status.
static struct ast_configrealtime_multi_ldap (const char *basedn, const char *table_name, const struct ast_variable *fields)
 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)
 Count semicolons in string.
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.
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)
 Unload Module.
static int update2_ldap (const char *basedn, const char *table_name, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
static int update_ldap (const char *basedn, const char *table_name, const char *attribute, const char *lookup, const struct ast_variable *fields)
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, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
 Module Information.
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 70 of file res_config_ldap.c.

Referenced by config_ldap(), and parse_config().

#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Definition at line 71 of file res_config_ldap.c.

Referenced by parse_config().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1895 of file res_config_ldap.c.

static void __unreg_module ( void   )  [static]

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

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

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

00737 {
00738    char *new_name = NULL;
00739    char *new_value = NULL;
00740    char *like_pos = strstr(name, " LIKE");
00741 
00742    ast_debug(2, "name='%s' value='%s'\n", name, value);
00743 
00744    if (like_pos) {
00745       int len = like_pos - name;
00746 
00747       name = new_name = ast_strdupa(name);
00748       new_name[len] = '\0';
00749       value = new_value = ast_strdupa(value);
00750       replace_string_in_string(new_value, "\\_", "_");
00751       replace_string_in_string(new_value, "%", "*");
00752    }
00753 
00754    name = convert_attribute_name_to_ldap(table_config, name);
00755 
00756    ast_str_append(filter, 0, "(%s=%s)", name, value);
00757 }

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

Note:
caller should free returned pointer

Definition at line 681 of file res_config_ldap.c.

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

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

00682 {
00683    char *cbasedn = NULL;
00684    if (basedn) {
00685       char *p = NULL;
00686       cbasedn = substituted(channel, basedn);
00687       if (*cbasedn == '"') {
00688          cbasedn++;
00689          if (!ast_strlen_zero(cbasedn)) {
00690             int len = strlen(cbasedn);
00691             if (cbasedn[len - 1] == '"')
00692                cbasedn[len - 1] = '\0';
00693 
00694          }
00695       }
00696       p = cbasedn;
00697       while (*p) {
00698          if (*p == '|')
00699             *p = ',';
00700          p++;
00701       }
00702    }
00703    ast_debug(2, "basedn: '%s' => '%s' \n", basedn, cbasedn);
00704    return cbasedn;
00705 }

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

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

Referenced by config_ldap().

01084 {
01085    const struct category_and_metric *as = a;
01086    const struct category_and_metric *bs = b;
01087 
01088    if (as->metric < bs->metric) {
01089       return -1;
01090    } else if (as->metric > bs->metric) {
01091       return 1;
01092    } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
01093       return strcmp(as->name, bs->name);
01094    } 
01095    /* if the metric and the category name is the same, we check the variable metric */
01096    if (as->var_metric < bs->var_metric) {
01097       return -1;
01098    } else if (as->var_metric > bs->var_metric) {
01099       return 1;
01100    }
01101 
01102    return 0;
01103 }

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 Realtime Documentation.

This is for Static Realtime

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 1112 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(), categories, compare_categories(), LOG_ERROR, LOG_WARNING, category_and_metric::metric, name, category_and_metric::name, NULL, 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.

01114 {
01115    unsigned int vars_count = 0;
01116    struct ast_variable **vars;
01117    int i = 0;
01118    struct ast_variable *new_v = NULL;
01119    struct ast_category *cur_cat = NULL;
01120    const char *last_category = NULL;
01121    int last_category_metric = 0;
01122    struct category_and_metric *categories;
01123    struct ast_variable **p;
01124 
01125    if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
01126       ast_log(LOG_ERROR, "Missing configuration file: %s. Can't configure myself.\n", RES_CONFIG_LDAP_CONF);
01127       return NULL;
01128    }
01129 
01130    vars = realtime_ldap_base(&vars_count, basedn, table_name, "filename", file, "commented", "FALSE", NULL);
01131 
01132    if (!vars) {
01133       ast_log(LOG_WARNING, "Could not find config '%s' in directory.\n", file);
01134       return NULL;
01135    }
01136 
01137    /*! \note Since the items come back in random order, they need to be sorted
01138     * first, and since the data could easily exceed stack size, this is
01139     * allocated from the heap.
01140     */
01141    if (!(categories = ast_calloc(sizeof(*categories), vars_count))) {
01142       return NULL;
01143    }
01144 
01145    for (vars_count = 0, p = vars; *p; p++) {
01146       struct ast_variable *category = variable_named(*p, "category");
01147       struct ast_variable *cat_metric = variable_named(*p, "cat_metric");
01148       struct ast_variable *var_name = variable_named(*p, "variable_name");
01149       struct ast_variable *var_val = variable_named(*p, "variable_value");
01150       struct ast_variable *var_metric = variable_named(*p, "var_metric");
01151       struct ast_variable *dn = variable_named(*p, "dn");
01152 
01153       if (!category) {
01154          ast_log(LOG_ERROR, "No category name in entry '%s'  for file '%s'.\n",
01155                (dn ? dn->value : "?"), file);
01156       } else if (!cat_metric) {
01157          ast_log(LOG_ERROR, "No category metric in entry '%s'(category: %s) for file '%s'.\n",
01158                (dn ? dn->value : "?"), category->value, file);
01159       } else if (!var_metric) {
01160          ast_log(LOG_ERROR, "No variable metric in entry '%s'(category: %s) for file '%s'.\n",
01161                (dn ? dn->value : "?"), category->value, file);
01162       } else if (!var_name) {
01163          ast_log(LOG_ERROR, "No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
01164                (dn ? dn->value : "?"), category->value,
01165                cat_metric->value, file);
01166       } else if (!var_val) {
01167          ast_log(LOG_ERROR, "No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
01168                (dn ? dn->value : "?"), category->value,
01169                cat_metric->value, var_name->value, file);
01170       } else {
01171          categories[vars_count].name = category->value;
01172          categories[vars_count].metric = atoi(cat_metric->value);
01173          categories[vars_count].variable_name = var_name->value;
01174          categories[vars_count].variable_value = var_val->value;
01175          categories[vars_count].var_metric = atoi(var_metric->value);
01176          vars_count++;
01177       }
01178 
01179       ast_debug(3, "category: %s\n", category->value);
01180       ast_debug(3, "var_name: %s\n", var_name->value);
01181       ast_debug(3, "var_val: %s\n", var_val->value);
01182       ast_debug(3, "cat_metric: %s\n", cat_metric->value);
01183 
01184    }
01185 
01186    qsort(categories, vars_count, sizeof(*categories), compare_categories);
01187 
01188    for (i = 0; i < vars_count; i++) {
01189       if (!strcmp(categories[i].variable_name, "#include")) {
01190          struct ast_flags flags = { 0 };
01191          if (!ast_config_internal_load(categories[i].variable_value, cfg, flags, "", who_asked)) {
01192             break;
01193          }
01194          continue;
01195       }
01196 
01197       if (!last_category || strcmp(last_category, categories[i].name) ||
01198          last_category_metric != categories[i].metric) {
01199 
01200          cur_cat = ast_category_new(categories[i].name, table_name, -1);
01201          if (!cur_cat) {
01202             break;
01203          }
01204          last_category = categories[i].name;
01205          last_category_metric = categories[i].metric;
01206          ast_category_append(cfg, cur_cat);
01207       }
01208 
01209       if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name))) {
01210          break;
01211       }
01212 
01213       ast_variable_append(cur_cat, new_v);
01214    }
01215 
01216    ast_free(vars);
01217    ast_free(categories);
01218 
01219    return cfg;
01220 }

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

00282 {
00283    int i = 0;
00284    struct ldap_table_config *configs[] = { table_config, base_table_config };
00285 
00286    for (i = 0; i < ARRAY_LEN(configs); i++) {
00287       struct ast_variable *attribute;
00288 
00289       if (!configs[i]) {
00290          continue;
00291       }
00292 
00293       attribute = configs[i]->attributes;
00294       for (; attribute; attribute = attribute->next) {
00295          if (strcasecmp(attribute_name, attribute->value) == 0) {
00296             return attribute->name;
00297          }
00298       }
00299    }
00300 
00301    return attribute_name;
00302 }

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.

Note:
Should be locked before using it

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

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

static int is_ldap_connect_error ( int  err  )  [static]

Check if we have a connection error.

Definition at line 578 of file res_config_ldap.c.

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

00579 {
00580    return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
00581 }

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 590 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, NULL, realtime_ldap_result_to_vars(), result, and var.

Referenced by realtime_ldap_base_ap().

00592 {
00593    if (!table_config) {
00594       ast_log(LOG_ERROR, "No table config\n");
00595       return NULL;
00596    } else {
00597       struct ast_variable **vars = NULL;
00598       struct ast_variable *var = NULL;
00599       int result = -1;
00600       LDAPMessage *ldap_result_msg = NULL;
00601       int tries = 0;
00602 
00603       ast_debug(2, "ldap_loadentry dn=%s\n", dn);
00604 
00605       do {
00606          result = ldap_search_ext_s(ldapConn, dn, LDAP_SCOPE_BASE,
00607                   "(objectclass=*)", NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg);
00608          if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
00609             ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
00610             tries++;
00611             if (tries < 3) {
00612                usleep(500000L * tries);
00613                if (ldapConn) {
00614                   ldap_unbind_ext_s(ldapConn, NULL, NULL);
00615                   ldapConn = NULL;
00616                }
00617                if (!ldap_reconnect()) {
00618                   break;
00619                }
00620             }
00621          }
00622       } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
00623 
00624       if (result != LDAP_SUCCESS) {
00625          ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
00626          ast_debug(2, "dn=%s\n", dn);
00627          ast_mutex_unlock(&ldap_lock);
00628          return NULL;
00629       } else {
00630          int num_entry = 0;
00631          unsigned int *entries_count_ptr = NULL; /*!< not using this */
00632 
00633          if ((num_entry = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
00634             ast_debug(3, "num_entry: %d\n", num_entry);
00635 
00636             vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
00637             if (num_entry > 1) {
00638                ast_log(LOG_NOTICE, "More than one entry for dn=%s. Take only 1st one\n", dn);
00639             }
00640          } else {
00641             ast_debug(2, "Could not find any entry dn=%s.\n", dn);
00642          }
00643       }
00644       ldap_msgfree(ldap_result_msg);
00645 
00646       /* Chopping \a vars down to one variable */
00647       if (vars != NULL) {
00648          struct ast_variable **p = vars;
00649 
00650          /* Only take the first one. */
00651          var = *vars;
00652 
00653          /* Destroy the rest. */
00654          while (*++p) {
00655             ast_variables_destroy(*p);
00656          }
00657          ast_free(vars);
00658       }
00659 
00660       return var;
00661    }
00662 }

static int ldap_reconnect ( void   )  [static]

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

Definition at line 1788 of file res_config_ldap.c.

References ast_debug, ast_log, ast_strlen_zero, LOG_ERROR, LOG_WARNING, and NULL.

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

01789 {
01790    int bind_result = 0;
01791    struct berval cred;
01792 
01793    if (ldapConn) {
01794       ast_debug(2, "Everything seems fine.\n");
01795       return 1;
01796    }
01797 
01798    if (ast_strlen_zero(url)) {
01799       ast_log(LOG_ERROR, "Not enough parameters to connect to ldap directory\n");
01800       return 0;
01801    }
01802 
01803    if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
01804       ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
01805       return 0;
01806    }
01807 
01808    if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
01809       ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
01810    }
01811 
01812    if (!ast_strlen_zero(user)) {
01813       ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
01814       cred.bv_val = (char *) pass;
01815       cred.bv_len = strlen(pass);
01816       bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01817    } else {
01818       ast_debug(2, "bind %s anonymously\n", url);
01819       cred.bv_val = NULL;
01820       cred.bv_len = 0;
01821       bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
01822    }
01823    if (bind_result == LDAP_SUCCESS) {
01824       ast_debug(2, "Successfully connected to directory.\n");
01825       connect_time = time(NULL);
01826       return 1;
01827    } else {
01828       ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
01829       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01830       ldapConn = NULL;
01831       return 0;
01832    }
01833 }

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

00206 {
00207    struct ast_variable *var;
00208 
00209    if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value)) {
00210       return;
00211    }
00212 
00213    if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->table_name))) {
00214       return;
00215    }
00216 
00217    if (table_config->attributes) {
00218       var->next = table_config->attributes;
00219    }
00220    table_config->attributes = var;
00221 }

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.

Todo:
Don't error or warn on a default install. If the config is default we should not attempt to connect to a server. -lathama

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

01611 {
01612    if (parse_config() < 0) {
01613       ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
01614       return 0;
01615    }
01616 
01617    ast_mutex_lock(&ldap_lock);
01618 
01619    if (!ldap_reconnect())  {
01620       ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
01621    }
01622 
01623    ast_config_engine_register(&ldap_engine);
01624    ast_verb(1, "LDAP RealTime driver loaded.\n");
01625    ast_cli_register_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01626 
01627    ast_mutex_unlock(&ldap_lock);
01628 
01629    return 0;
01630 }

static int parse_config ( void   )  [static]

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1688 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, host, ldap_table_config_add_attribute(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, 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.

01689 {
01690    struct ast_config *config;
01691    struct ast_flags config_flags = {0};
01692    const char *s, *host;
01693    int port;
01694    char *category_name = NULL;
01695 
01696    /* Make sure that global variables are reset */
01697    url[0] = '\0';
01698    user[0] = '\0';
01699    pass[0] = '\0';
01700    base_distinguished_name[0] = '\0';
01701    version = 3;
01702 
01703    config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
01704    if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
01705       ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
01706       return -1;
01707    }
01708 
01709    if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
01710       ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
01711       user[0] = '\0';
01712    } else {
01713       ast_copy_string(user, s, sizeof(user));
01714    }
01715 
01716    if (!ast_strlen_zero(user)) {
01717       if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
01718          ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
01719          ast_copy_string(pass, "asterisk", sizeof(pass));
01720       } else {
01721          ast_copy_string(pass, s, sizeof(pass));
01722       }
01723    }
01724 
01725    /* URL is preferred, use host and port if not found */
01726    if ((s = ast_variable_retrieve(config, "_general", "url"))) {
01727       ast_copy_string(url, s, sizeof(url));
01728    } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
01729       if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
01730          ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
01731          port = 389;
01732       }
01733 
01734       snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
01735    } else {
01736       ast_log(LOG_ERROR, "No directory URL or host found.\n");
01737       ast_config_destroy(config);
01738       return -1;
01739    }
01740 
01741    if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
01742       ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
01743       ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
01744    } else 
01745       ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));
01746 
01747    if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
01748       ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
01749    } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
01750       ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
01751       version = 3;
01752    }
01753 
01754    table_configs_free();
01755 
01756    while ((category_name = ast_category_browse(config, category_name))) {
01757       int is_general = (strcasecmp(category_name, "_general") == 0);
01758       int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
01759       struct ast_variable *var = ast_variable_browse(config, category_name);
01760       
01761       if (var) {
01762          struct ldap_table_config *table_config =
01763             table_config_for_table_name(category_name);
01764          if (!table_config) {
01765             table_config = table_config_new(category_name);
01766             AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
01767             if (is_general)
01768                base_table_config = table_config;
01769             if (is_config)
01770                static_table_config = table_config;
01771          }
01772          for (; var; var = var->next) {
01773             if (!strcasecmp(var->name, "additionalFilter")) {
01774                table_config->additional_filter = ast_strdup(var->value);
01775             } else {
01776                ldap_table_config_add_attribute(table_config, var->name, var->value);
01777             }
01778          }
01779       }
01780    }
01781 
01782    ast_config_destroy(config);
01783 
01784    return 1;
01785 }

static struct ast_variable* realtime_arguments_to_fields ( va_list  ap  )  [static, read]

Definition at line 944 of file res_config_ldap.c.

References ast_variable_new(), ast_variables_destroy(), ast_variable::next, and NULL.

00945 {
00946    struct ast_variable *fields = NULL;
00947    const char *newparam, *newval;
00948 
00949    while ((newparam = va_arg(ap, const char *))) {
00950       struct ast_variable *field;
00951 
00952       newval = va_arg(ap, const char *);
00953       if (!(field = ast_variable_new(newparam, newval, ""))) {
00954          ast_variables_destroy(fields);
00955          return NULL;
00956       }
00957 
00958       field->next = fields;
00959       fields = field;
00960    }
00961 
00962    return fields;
00963 }

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

See Asterisk doc.

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

Definition at line 987 of file res_config_ldap.c.

References ast_free, ast_variable::next, NULL, realtime_ldap_base_ap(), and var.

00989 {
00990    struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, fields);
00991    struct ast_variable *var = NULL;
00992 
00993    if (vars) {
00994       struct ast_variable *last_var = NULL;
00995       struct ast_variable **p = vars;
00996 
00997       /* Chain the vars array of lists into one list to return. */
00998       while (*p) {
00999          if (last_var) {
01000             while (last_var->next) {
01001                last_var = last_var->next;
01002             }
01003             last_var->next = *p;
01004          } else {
01005             var = *p;
01006             last_var = var;
01007          }
01008          p++;
01009       }
01010       ast_free(vars);
01011    }
01012    return var;
01013 }

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

References ast_variables_destroy(), NULL, RAII_VAR, realtime_arguments_to_fields, and realtime_ldap_base_ap().

Referenced by config_ldap().

00969 {
00970    RAII_VAR(struct ast_variable *, fields, NULL, ast_variables_destroy);
00971    struct ast_variable **vars = NULL;
00972    va_list ap;
00973 
00974    va_start(ap, table_name);
00975    fields = realtime_arguments_to_fields(ap);
00976    va_end(ap);
00977 
00978    vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, fields);
00979 
00980    return vars;
00981 }

static struct ast_variable** realtime_ldap_base_ap ( unsigned int *  entries_count_ptr,
const char *  basedn,
const char *  table_name,
const struct ast_variable fields 
) [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)
fields contains list of pairs name/value

get the default variables from the accountBaseDN, not implemented with delimited values

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 767 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, ldap_table_config::next, ast_variable::next, NULL, realtime_ldap_result_to_vars(), result, table_config_for_table_name(), tmp(), and ast_variable::value.

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

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

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

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

Referenced by realtime_ldap_result_to_vars().

00310 {
00311    BerElement *ber = NULL;
00312    struct ast_variable *var = NULL;
00313    struct ast_variable *prev = NULL;
00314    int is_delimited = 0;
00315    int i = 0;
00316    char *ldap_attribute_name;
00317    struct berval *value;
00318    int pos = 0;
00319 
00320    ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
00321 
00322    while (ldap_attribute_name) {
00323       struct berval **values = NULL;
00324       const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
00325       int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
00326 
00327       values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name); /* these are freed at the end */
00328       if (values) {
00329          struct berval **v;
00330          char *valptr;
00331 
00332          for (v = values; *v; v++) {
00333             value = *v;
00334             valptr = value->bv_val;
00335             ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr);
00336             if (is_realmed_password_attribute) {
00337                if (!strncasecmp(valptr, "{md5}", 5)) {
00338                   valptr += 5;
00339                }
00340                ast_debug(2, "md5: %s\n", valptr);
00341             }
00342             if (valptr) {
00343                /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
00344                if (is_delimited) {
00345                   i = 0;
00346                   pos = 0;
00347                   while (!ast_strlen_zero(valptr + i)) {
00348                      if (valptr[i] == ';') {
00349                         valptr[i] = '\0';
00350                         if (prev) {
00351                            prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00352                            if (prev->next) {
00353                               prev = prev->next;
00354                            }
00355                         } else {
00356                            prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00357                         }
00358                         pos = i + 1;
00359                      }
00360                      i++;
00361                   }
00362                }
00363                /* for the last delimited value or if the value is not delimited: */
00364                if (prev) {
00365                   prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00366                   if (prev->next) {
00367                      prev = prev->next;
00368                   }
00369                } else {
00370                   prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
00371                }
00372             }
00373          }
00374          ldap_value_free_len(values);
00375       }
00376       ldap_memfree(ldap_attribute_name);
00377       ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
00378    }
00379    ber_free(ber, 0);
00380 
00381    return var;
00382 }

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.

Note:
Now that we have the total count we allocate space and create the variables Remember that each element in vars is a linked list that points to realtime variable. If the we are dealing with a static realtime variable we create a new element in the vars array for each delimited value in variable_value; otherwise, we keep vars static and increase the length of the linked list of variables in the array element. This memory must be freed outside of this function.

Definition at line 390 of file res_config_ldap.c.

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

Referenced by ldap_loadentry(), and realtime_ldap_base_ap().

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

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

Realtime Status.

Definition at line 1838 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, NULL, status, and ast_cli_entry::usage.

01839 {
01840    char status[256], credentials[100] = "";
01841    int ctimesec = time(NULL) - connect_time;
01842 
01843    switch (cmd) {
01844    case CLI_INIT:
01845       e->command = "realtime show ldap status";
01846       e->usage =
01847          "Usage: realtime show ldap status\n"
01848          "         Shows connection information for the LDAP RealTime driver\n";
01849       return NULL;
01850    case CLI_GENERATE:
01851       return NULL;
01852    }
01853 
01854    if (!ldapConn)
01855       return CLI_FAILURE;
01856 
01857    if (!ast_strlen_zero(url)) 
01858       snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
01859 
01860    if (!ast_strlen_zero(user))
01861       snprintf(credentials, sizeof(credentials), " with username %s", user);
01862 
01863    if (ctimesec > 31536000) {
01864       ast_cli(a->fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
01865             status, credentials, ctimesec / 31536000,
01866             (ctimesec % 31536000) / 86400, (ctimesec % 86400) / 3600,
01867             (ctimesec % 3600) / 60, ctimesec % 60);
01868    } else if (ctimesec > 86400) {
01869       ast_cli(a->fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n",
01870             status, credentials, ctimesec / 86400, (ctimesec % 86400) / 3600,
01871             (ctimesec % 3600) / 60, ctimesec % 60);
01872    } else if (ctimesec > 3600) {
01873       ast_cli(a->fd, "%s%s for %d hours, %d minutes, %d seconds.\n",
01874             status, credentials, ctimesec / 3600, (ctimesec % 3600) / 60,
01875             ctimesec % 60);
01876    } else if (ctimesec > 60) {
01877       ast_cli(a->fd, "%s%s for %d minutes, %d seconds.\n", status, credentials,
01878                ctimesec / 60, ctimesec % 60);
01879    } else {
01880       ast_cli(a->fd, "%s%s for %d seconds.\n", status, credentials, ctimesec);
01881    }
01882 
01883    return CLI_SUCCESS;
01884 }

static struct ast_config* realtime_multi_ldap ( const char *  basedn,
const char *  table_name,
const struct ast_variable fields 
) [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 1022 of file res_config_ldap.c.

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

01024 {
01025    char *op;
01026    const char *initfield = NULL;
01027    struct ast_variable **vars =
01028       realtime_ldap_base_ap(NULL, basedn, table_name, fields);
01029    struct ast_config *cfg = NULL;
01030 
01031    if (!fields) {
01032        ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
01033        return NULL;
01034    }
01035    initfield = ast_strdupa(fields->name);
01036    if ((op = strchr(initfield, ' '))) {
01037       *op = '\0';
01038    }
01039 
01040    if (vars) {
01041       cfg = ast_config_new();
01042       if (!cfg) {
01043          ast_log(LOG_ERROR, "Unable to create a config!\n");
01044       } else {
01045          struct ast_variable **p = vars;
01046 
01047          while (*p) {
01048             struct ast_category *cat = NULL;
01049             cat = ast_category_new("", table_name, -1);
01050             if (!cat) {
01051                ast_log(LOG_ERROR, "Unable to create a new category!\n");
01052                break;
01053             } else {
01054                struct ast_variable *var = *p;
01055                while (var) {
01056                   struct ast_variable *next = var->next;
01057                   if (initfield && !strcmp(initfield, var->name)) {
01058                      ast_category_rename(cat, var->value);
01059                   }
01060                   var->next = NULL;
01061                   ast_variable_append(cat, var);
01062                   var = next;
01063                }
01064             }
01065             ast_category_append(cfg, cat);
01066             p++;
01067          }
01068       }
01069       ast_free(vars);
01070    }
01071    return cfg;
01072 
01073 }

static int reload ( void   )  [static]

Relod Module

Definition at line 1658 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, NULL, and parse_config().

01659 {
01660    /* Aquire control before doing anything to the module itself. */
01661    ast_mutex_lock(&ldap_lock);
01662 
01663    if (ldapConn) {
01664       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01665       ldapConn = NULL;
01666    }
01667 
01668    if (parse_config() < 0) {
01669       ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
01670       ast_mutex_unlock(&ldap_lock);
01671       return 0;
01672    }     
01673 
01674    if (!ldap_reconnect())  {
01675       ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
01676    }
01677 
01678    ast_verb(2, "LDAP RealTime driver reloaded.\n");
01679 
01680    /* Done reloading. Release lock so others can now use driver. */
01681    ast_mutex_unlock(&ldap_lock);
01682 
01683    return 0;
01684 }

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

Referenced by append_var_and_value_to_filter().

00711 {
00712    int search_len = strlen(search);
00713    int by_len = strlen(by);
00714    int replaced = 0;
00715    char *p = strstr(string, search);
00716 
00717    if (p) {
00718       replaced = 1;
00719       while (p) {
00720          if (by_len == search_len) {
00721             memcpy(p, by, by_len);
00722          } else {
00723             memmove(p + by_len, p + search_len, strlen(p + search_len) + 1);
00724             memcpy(p, by, by_len);
00725          }
00726          p = strstr(p + by_len, search);
00727       }
00728    }
00729    return replaced;
00730 }

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

Count semicolons in string.

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

Definition at line 170 of file res_config_ldap.c.

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

00171 {
00172    int count = 0;
00173 
00174    for (; *somestr; somestr++) {
00175       if (*somestr == ';')
00176          count++;
00177    }
00178 
00179    return count;
00180 }

static int semicolon_count_var ( struct ast_variable var  )  [static]

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

00188 {
00189    struct ast_variable *var_value = variable_named(var, "variable_value");
00190 
00191    if (!var_value) {
00192       return 0;
00193    }
00194 
00195    ast_debug(2, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value);
00196 
00197    return semicolon_count_str(var_value->value);
00198 }

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

Note:
caller should free returned pointer

Definition at line 666 of file res_config_ldap.c.

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

Referenced by cleaned_basedn().

00667 {
00668 #define MAXRESULT 2048
00669    char *ret_string = NULL;
00670 
00671    if (!ast_strlen_zero(string)) {
00672       ret_string = ast_calloc(1, MAXRESULT);
00673       pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
00674    }
00675    ast_debug(2, "substituted: string: '%s' => '%s' \n", string, ret_string);
00676    return ret_string;
00677 }

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

References AST_LIST_TRAVERSE, c, NULL, and ldap_table_config::table_name.

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

00142 {
00143    struct ldap_table_config *c = NULL;
00144 
00145    AST_LIST_TRAVERSE(&table_configs, c, entry) {
00146       if (!strcmp(c->table_name, table_name))
00147          break;
00148    }
00149 
00150    return c;
00151 }

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

Create a new table_config.

Definition at line 118 of file res_config_ldap.c.

References ast_calloc, ast_free, ast_strdup, NULL, and ldap_table_config::table_name.

Referenced by parse_config().

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

static void table_configs_free ( void   )  [static]

Free table_config.

Note:
assumes ldap_lock to be locked

Definition at line 227 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, c, NULL, static_table_config, and ldap_table_config::table_name.

Referenced by parse_config(), and unload_module().

00228 {
00229    struct ldap_table_config *c;
00230 
00231    while ((c = AST_LIST_REMOVE_HEAD(&table_configs, entry))) {
00232       if (c->table_name) {
00233          ast_free(c->table_name);
00234       }
00235       if (c->additional_filter) {
00236          ast_free(c->additional_filter);
00237       }
00238       if (c->attributes) {
00239          ast_variables_destroy(c->attributes);
00240       }
00241       ast_free(c);
00242    }
00243 
00244    base_table_config = NULL;
00245    static_table_config = NULL;
00246 }

static int unload_module ( void   )  [static]

Unload Module.

Definition at line 1635 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, NULL, and table_configs_free().

01636 {
01637    /* Aquire control before doing anything to the module itself. */
01638    ast_mutex_lock(&ldap_lock);
01639 
01640    table_configs_free();
01641 
01642    if (ldapConn) {
01643       ldap_unbind_ext_s(ldapConn, NULL, NULL);
01644       ldapConn = NULL;
01645    }
01646    ast_cli_unregister_multiple(ldap_cli, ARRAY_LEN(ldap_cli));
01647    ast_config_engine_deregister(&ldap_engine);
01648    ast_verb(1, "LDAP RealTime driver unloaded.\n");
01649 
01650    /* Unlock so something else can destroy the lock. */
01651    ast_mutex_unlock(&ldap_lock);
01652 
01653    return 0;
01654 }

static int update2_ldap ( const char *  basedn,
const char *  table_name,
const struct ast_variable lookup_fields,
const struct ast_variable update_fields 
) [static]

Definition at line 1405 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(), error(), filter(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, option_debug, result, table_config_for_table_name(), and ast_variable::value.

01406 {
01407    int error = 0;
01408    LDAPMessage *ldap_entry = NULL;
01409    LDAPMod **ldap_mods;
01410    const char *newparam;
01411    const struct ast_variable *field;
01412    char *dn;
01413    int num_entries = 0;
01414    int i = 0;
01415    int mods_size = 0;
01416    int mod_exists = 0;
01417    struct ldap_table_config *table_config = NULL;
01418    char *clean_basedn = NULL;
01419    struct ast_str *filter = NULL;
01420    int tries = 0;
01421    int result = 0;
01422    LDAPMessage *ldap_result_msg = NULL;
01423 
01424    if (!table_name) {
01425       ast_log(LOG_ERROR, "No table_name specified.\n");
01426       return -1;
01427    } 
01428 
01429    if (!(filter = ast_str_create(80))) {
01430       return -1;
01431    }
01432 
01433    ast_mutex_lock(&ldap_lock);
01434 
01435    /* We now have our complete statement; Lets connect to the server and execute it.  */
01436    if (!ldap_reconnect()) {
01437       ast_mutex_unlock(&ldap_lock);
01438       ast_free(filter);
01439       return -1;
01440    }
01441 
01442    table_config = table_config_for_table_name(table_name);
01443    if (!table_config) {
01444       ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
01445       ast_mutex_unlock(&ldap_lock);
01446       ast_free(filter);
01447       return -1;
01448    }
01449 
01450    clean_basedn = cleaned_basedn(NULL, basedn);
01451 
01452    /* Create the filter with the table additional filter and the parameter/value pairs we were given */
01453    ast_str_append(&filter, 0, "(&");
01454    if (table_config && table_config->additional_filter) {
01455       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
01456    }
01457    if (table_config != base_table_config && base_table_config
01458       && base_table_config->additional_filter) {
01459       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
01460    }
01461 
01462    /* Get multiple lookup keyfields and values */
01463    for (field = lookup_fields; field; field = field->next) {
01464       append_var_and_value_to_filter(&filter, table_config, field->name, field->value);
01465    }
01466    ast_str_append(&filter, 0, ")");
01467 
01468    /* Create the modification array with the parameter/value pairs we were given, 
01469     * if there are several parameters with the same name, we collect them into 
01470     * one parameter/value pair and delimit them with a semicolon */
01471    field = update_fields;
01472    newparam = convert_attribute_name_to_ldap(table_config, field->name);
01473    if (!newparam) {
01474       ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
01475       ast_free(filter);
01476       ast_free(clean_basedn);
01477       return -1;
01478    }
01479 
01480    mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
01481    ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
01482    ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
01483 
01484    ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
01485    ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01486    strcpy(ldap_mods[0]->mod_type, newparam);
01487 
01488    ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2);
01489    ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(field->value) + 1);
01490    strcpy(ldap_mods[0]->mod_values[0], field->value);
01491 
01492    while ((field = field->next)) {
01493       newparam = convert_attribute_name_to_ldap(table_config, field->name);
01494       mod_exists = 0;
01495 
01496       for (i = 0; i < mods_size - 1; i++) {
01497          if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
01498             /* We have the parameter allready, adding the value as a semicolon delimited value */
01499             ldap_mods[i]->mod_values[0] = ast_realloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(field->value) + 2));
01500             strcat(ldap_mods[i]->mod_values[0], ";");
01501             strcat(ldap_mods[i]->mod_values[0], field->value);
01502             mod_exists = 1;   
01503             break;
01504          }
01505       }
01506 
01507       /* create new mod */
01508       if (!mod_exists) {
01509          mods_size++;
01510          ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
01511          ldap_mods[mods_size - 1] = NULL;
01512          ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
01513 
01514          ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
01515 
01516          ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
01517          strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
01518 
01519          ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
01520          ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(field->value) + 1);
01521          strcpy(ldap_mods[mods_size - 2]->mod_values[0], field->value);
01522       }
01523    }
01524    /* freeing ldap_mods further down */
01525 
01526    do {
01527       /* freeing ldap_result further down */
01528       result = ldap_search_ext_s(ldapConn, clean_basedn,
01529               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
01530               &ldap_result_msg);
01531       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
01532          ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
01533          tries++;
01534          if (tries < 3) {
01535             usleep(500000L * tries);
01536             if (ldapConn) {
01537                ldap_unbind_ext_s(ldapConn, NULL, NULL);
01538                ldapConn = NULL;
01539             }
01540             if (!ldap_reconnect()) {
01541                break;
01542             }
01543          }
01544       }
01545    } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
01546 
01547    if (result != LDAP_SUCCESS) {
01548       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
01549       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
01550 
01551       ast_mutex_unlock(&ldap_lock);
01552       ast_free(filter);
01553       ast_free(clean_basedn);
01554       ldap_msgfree(ldap_result_msg);
01555       ldap_mods_free(ldap_mods, 0);
01556       return -1;
01557    }
01558    /* Ready to update */
01559    if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
01560       for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
01561          ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
01562       }
01563 
01564       ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
01565 
01566       for (i = 0; ldap_entry; i++) {
01567          dn = ldap_get_dn(ldapConn, ldap_entry);
01568          if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)  {
01569             ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
01570          }
01571          ldap_memfree(dn);
01572          ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
01573       }
01574    }
01575 
01576    ast_mutex_unlock(&ldap_lock);
01577    if (filter) {
01578       ast_free(filter);
01579    }
01580    if (clean_basedn) {
01581       ast_free(clean_basedn);
01582    }
01583    ldap_msgfree(ldap_result_msg);
01584    ldap_mods_free(ldap_mods, 0);
01585    return num_entries;
01586 }

static int update_ldap ( const char *  basedn,
const char *  table_name,
const char *  attribute,
const char *  lookup,
const struct ast_variable fields 
) [static]

Definition at line 1224 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(), error(), filter(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, option_debug, result, table_config_for_table_name(), and ast_variable::value.

01226 {
01227    int error = 0;
01228    LDAPMessage *ldap_entry = NULL;
01229    LDAPMod **ldap_mods;
01230    const char *newparam;
01231    const struct ast_variable *field = fields;
01232    char *dn;
01233    int num_entries = 0;
01234    int i = 0;
01235    int mods_size = 0;
01236    int mod_exists = 0;
01237    struct ldap_table_config *table_config = NULL;
01238    char *clean_basedn = NULL;
01239    struct ast_str *filter = NULL;
01240    int tries = 0;
01241    int result = 0;
01242    LDAPMessage *ldap_result_msg = NULL;
01243 
01244    if (!table_name) {
01245       ast_log(LOG_ERROR, "No table_name specified.\n");
01246       return -1;
01247    } 
01248 
01249    if (!(filter = ast_str_create(80))) {
01250       return -1;
01251    }
01252 
01253    if (!attribute || !lookup) {
01254       ast_log(LOG_WARNING, "LINE(%d): search parameters are empty.\n", __LINE__);
01255       return -1;
01256    }
01257    ast_mutex_lock(&ldap_lock);
01258 
01259    /* We now have our complete statement; Lets connect to the server and execute it.  */
01260    if (!ldap_reconnect()) {
01261       ast_mutex_unlock(&ldap_lock);
01262       return -1;
01263    }
01264 
01265    table_config = table_config_for_table_name(table_name);
01266    if (!table_config) {
01267       ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
01268       ast_mutex_unlock(&ldap_lock);
01269       return -1;
01270    }
01271 
01272    clean_basedn = cleaned_basedn(NULL, basedn);
01273 
01274    /* Create the filter with the table additional filter and the parameter/value pairs we were given */
01275    ast_str_append(&filter, 0, "(&");
01276    if (table_config && table_config->additional_filter) {
01277       ast_str_append(&filter, 0, "%s", table_config->additional_filter);
01278    }
01279    if (table_config != base_table_config && base_table_config && base_table_config->additional_filter) {
01280       ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
01281    }
01282    append_var_and_value_to_filter(&filter, table_config, attribute, lookup);
01283    ast_str_append(&filter, 0, ")");
01284 
01285    /* Create the modification array with the parameter/value pairs we were given, 
01286     * if there are several parameters with the same name, we collect them into 
01287     * one parameter/value pair and delimit them with a semicolon */
01288    newparam = convert_attribute_name_to_ldap(table_config, field->name);
01289    if (!newparam) {
01290       ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
01291       return -1;
01292    }
01293 
01294    mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
01295    ldap_mods = ldap_memcalloc(sizeof(LDAPMod *), mods_size);
01296    ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod));
01297 
01298    ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
01299    ldap_mods[0]->mod_type = ldap_strdup(newparam);
01300 
01301    ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2);
01302    ldap_mods[0]->mod_values[0] = ldap_strdup(field->value);
01303 
01304    while ((field = field->next)) {
01305       newparam = convert_attribute_name_to_ldap(table_config, field->name);
01306       mod_exists = 0;
01307 
01308       for (i = 0; i < mods_size - 1; i++) {
01309          if (ldap_mods[i]&& !strcmp(ldap_mods[i]->mod_type, newparam)) {
01310             /* We have the parameter allready, adding the value as a semicolon delimited value */
01311             ldap_mods[i]->mod_values[0] = ldap_memrealloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(field->value) + 2));
01312             strcat(ldap_mods[i]->mod_values[0], ";");
01313             strcat(ldap_mods[i]->mod_values[0], field->value);
01314             mod_exists = 1;   
01315             break;
01316          }
01317       }
01318 
01319       /* create new mod */
01320       if (!mod_exists) {
01321          mods_size++;
01322          ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
01323          ldap_mods[mods_size - 1] = NULL;
01324          
01325          ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod));
01326 
01327          ldap_mods[mods_size - 2]->mod_type = ldap_memcalloc(sizeof(char), strlen(newparam) + 1);
01328          strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
01329 
01330          if (strlen(field->value) == 0) {
01331             ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE;
01332          } else {
01333             ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
01334 
01335             ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(sizeof(char *), 2);
01336             ldap_mods[mods_size - 2]->mod_values[0] = ldap_memcalloc(sizeof(char), strlen(field->value) + 1);
01337             strcpy(ldap_mods[mods_size - 2]->mod_values[0], field->value);
01338          }
01339       }
01340    }
01341    /* freeing ldap_mods further down */
01342 
01343    do {
01344       /* freeing ldap_result further down */
01345       result = ldap_search_ext_s(ldapConn, clean_basedn,
01346               LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
01347               &ldap_result_msg);
01348       if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
01349          ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
01350          tries++;
01351          if (tries < 3) {
01352             usleep(500000L * tries);
01353             if (ldapConn) {
01354                ldap_unbind_ext_s(ldapConn, NULL, NULL);
01355                ldapConn = NULL;
01356             }
01357             if (!ldap_reconnect())
01358                break;
01359          }
01360       }
01361    } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
01362 
01363    if (result != LDAP_SUCCESS) {
01364       ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
01365       ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
01366 
01367       ast_mutex_unlock(&ldap_lock);
01368       ast_free(filter);
01369       ast_free(clean_basedn);
01370       ldap_msgfree(ldap_result_msg);
01371       ldap_mods_free(ldap_mods, 0);
01372       return -1;
01373    }
01374    /* Ready to update */
01375    if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
01376       ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries);
01377       for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
01378          if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) {
01379             ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
01380          } else {
01381             ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type);
01382          }
01383       }
01384       ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
01385 
01386       for (i = 0; ldap_entry; i++) { 
01387          dn = ldap_get_dn(ldapConn, ldap_entry);
01388          if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)  {
01389             ast_log(LOG_ERROR, "Couldn't modify '%s'='%s', dn:%s because %s\n",
01390                   attribute, lookup, dn, ldap_err2string(error));
01391          }
01392          ldap_memfree(dn);
01393          ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
01394       }
01395    }
01396 
01397    ast_mutex_unlock(&ldap_lock);
01398    ast_free(filter);
01399    ast_free(clean_basedn);
01400    ldap_msgfree(ldap_result_msg);
01401    ldap_mods_free(ldap_mods, 0);
01402    return num_entries;
01403 }

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

Find variable by name.

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

00156 {
00157    for (; var; var = var->next) {
00158       if (!strcasecmp(name, var->name))
00159          break;
00160    }
00161 
00162    return var;
00163 }


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

Module Information.

Definition at line 1895 of file res_config_ldap.c.

Definition at line 1895 of file res_config_ldap.c.

char base_distinguished_name[512] [static]

Definition at line 79 of file res_config_ldap.c.

time_t connect_time [static]

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

Referenced by load_module(), and unload_module().

struct ast_config_engine ldap_engine [static]

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

char pass[512] [static]

char url[512] [static]

char user[512] [static]

Definition at line 77 of file res_config_ldap.c.

int version [static]

Definition at line 80 of file res_config_ldap.c.


Generated on Thu Apr 16 06:32:44 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6