Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Macros | Functions | Variables
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...
 

Macros

#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. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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. More...
 
static int config_can_be_inherited (const char *key)
 
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. More...
 
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. More...
 
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. More...
 
static struct ast_strcreate_lookup_filter (struct ldap_table_config *config, const struct ast_variable *fields)
 
static int is_ldap_connect_error (int err)
 Check if we have a connection error. More...
 
static int ldap_entry_has_attribute (LDAPMessage *entry, const char *lookup)
 
static struct ast_variableldap_loadentry (struct ldap_table_config *table_config, const char *dn)
 Get LDAP entry by dn and return attributes as variables. More...
 
static LDAPMod * ldap_mod_append (LDAPMod *src, const char *new_value)
 
static LDAPMod * ldap_mod_create (const char *attribute, const char *new_value)
 
static LDAPMod * ldap_mod_duplicate (const LDAPMod *src)
 
static LDAPMod * ldap_mod_find (LDAPMod **modifications, const char *lookup)
 
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 More...
 
static int load_module (void)
 Load the module. More...
 
static LDAPMod ** massage_mods_for_entry (LDAPMessage *entry, LDAPMod **mods)
 
static int parse_config (void)
 parse the configuration file More...
 
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. More...
 
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 More...
 
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. More...
 
static struct ast_variablerealtime_ldap_entry_to_var (struct ldap_table_config *table_config, LDAPMessage *ldap_entry)
 Get variables from ldap entry attributes. More...
 
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. More...
 
static char * realtime_ldap_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Realtime Status. More...
 
static struct ast_configrealtime_multi_ldap (const char *basedn, const char *table_name, const struct ast_variable *fields)
 See Asterisk doc. More...
 
static int reload (void)
 Reload Module. More...
 
static int replace_string_in_string (char *string, const char *search, const char *by)
 Replace <search> by <by> in string. More...
 
static int semicolon_count_str (const char *somestr)
 Count semicolons in string. More...
 
static int semicolon_count_var (struct ast_variable *var)
 Count semicolons in variables. More...
 
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. More...
 
static struct ldap_table_configtable_config_new (const char *table_name)
 Create a new table_config. More...
 
static void table_configs_free (void)
 Free table_config. More...
 
static int unload_module (void)
 Unload Module. More...
 
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. More...
 
static size_t variables_count (const struct ast_variable *vars)
 

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, .requires = "extconfig", }
 Module Information. More...
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static char base_distinguished_name [512]
 
static struct ldap_table_configbase_table_config
 
static time_t connect_time
 
static struct ast_cli_entry ldap_cli []
 
static struct ast_config_engine ldap_engine
 
static ast_mutex_t ldap_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static LDAP * ldapConn
 
static char pass [512]
 
static struct ldap_table_configstatic_table_config
 
static struct table_configs table_configs = { .first = NULL, .last = NULL, }
 
static char url [512]
 
static char user [512]
 
static int version
 

Detailed Description

LDAP plugin for portable configuration engine (ARA)

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Manuel Guesdon
Carl-Einar Thorner cthor.nosp@m.ner@.nosp@m.voice.nosp@m.rd.c.nosp@m.om
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

OpenLDAP http://www.openldap.org

Definition in file res_config_ldap.c.

Macro Definition Documentation

◆ MAXRESULT

#define MAXRESULT   2048

◆ RES_CONFIG_LDAP_CONF

#define RES_CONFIG_LDAP_CONF   "res_ldap.conf"

Definition at line 68 of file res_config_ldap.c.

◆ RES_CONFIG_LDAP_DEFAULT_BASEDN

#define RES_CONFIG_LDAP_DEFAULT_BASEDN   "asterisk"

Definition at line 69 of file res_config_ldap.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2007 of file res_config_ldap.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2007 of file res_config_ldap.c.

◆ append_var_and_value_to_filter()

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

741{
742 char *new_name = NULL;
743 char *new_value = NULL;
744 char *like_pos = strstr(name, " LIKE");
745
746 ast_debug(2, "name='%s' value='%s'\n", name, value);
747
748 if (like_pos) {
749 int len = like_pos - name;
750
751 name = new_name = ast_strdupa(name);
752 new_name[len] = '\0';
753 value = new_value = ast_strdupa(value);
754 replace_string_in_string(new_value, "\\_", "_");
755 replace_string_in_string(new_value, "%", "*");
756 }
757
759
760 ast_str_append(filter, 0, "(%s=%s)", name, value);
761}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_strings.c:807
#define ast_debug(level,...)
Log a DEBUG message.
static int replace_string_in_string(char *string, const char *search, const char *by)
Replace <search> by <by> in string.
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.
#define NULL
Definition: resample.c:96
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
int value
Definition: syslog.c:37

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

Referenced by create_lookup_filter().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2007 of file res_config_ldap.c.

◆ cleaned_basedn()

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

Definition at line 685 of file res_config_ldap.c.

686{
687 char *cbasedn = NULL;
688 if (basedn) {
689 char *p = NULL;
690 cbasedn = substituted(channel, basedn);
691 if (*cbasedn == '"') {
692 cbasedn++;
693 if (!ast_strlen_zero(cbasedn)) {
694 int len = strlen(cbasedn);
695 if (cbasedn[len - 1] == '"')
696 cbasedn[len - 1] = '\0';
697
698 }
699 }
700 p = cbasedn;
701 while (*p) {
702 if (*p == '|')
703 *p = ',';
704 p++;
705 }
706 }
707 ast_debug(2, "basedn: '%s' => '%s' \n", basedn, cbasedn);
708 return cbasedn;
709}
static char * substituted(struct ast_channel *channel, const char *string)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

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

Referenced by realtime_ldap_base_ap(), and update2_ldap().

◆ compare_categories()

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
apointer to category_and_metric struct
bpointer to category_and_metric struct
Return values
-1for if b is greater
0zero for equal
1if a is greater

Definition at line 1099 of file res_config_ldap.c.

1100{
1101 const struct category_and_metric *as = a;
1102 const struct category_and_metric *bs = b;
1103
1104 if (as->metric < bs->metric) {
1105 return -1;
1106 } else if (as->metric > bs->metric) {
1107 return 1;
1108 } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
1109 return strcmp(as->name, bs->name);
1110 }
1111 /* if the metric and the category name is the same, we check the variable metric */
1112 if (as->var_metric < bs->var_metric) {
1113 return -1;
1114 } else if (as->var_metric > bs->var_metric) {
1115 return 1;
1116 }
1117
1118 return 0;
1119}
char * bs
Definition: eagi_proxy.c:73
static struct test_val b
static struct test_val a

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

Referenced by config_ldap().

◆ config_can_be_inherited()

static int config_can_be_inherited ( const char *  key)
static

Definition at line 1793 of file res_config_ldap.c.

1794{
1795 int i;
1796 static const char * const config[] = {
1797 "basedn", "host", "pass", "port", "protocol", "url", "user", "version", NULL
1798 };
1799
1800 for (i = 0; config[i]; i++) {
1801 if (!strcasecmp(key, config[i])) {
1802 return 0;
1803 }
1804 }
1805 return 1;
1806}
static const char config[]
Definition: chan_ooh323.c:111

References config, and NULL.

Referenced by parse_config().

◆ config_ldap()

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

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

1130{
1131 unsigned int vars_count = 0;
1132 struct ast_variable **vars;
1133 int i = 0;
1134 struct ast_variable *new_v = NULL;
1135 struct ast_category *cur_cat = NULL;
1136 const char *last_category = NULL;
1137 int last_category_metric = 0;
1139 struct ast_variable **p;
1140
1141 if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
1142 ast_log(LOG_ERROR, "Missing configuration file: %s. Can't configure myself.\n", RES_CONFIG_LDAP_CONF);
1143 return NULL;
1144 }
1145
1146 vars = realtime_ldap_base(&vars_count, basedn, table_name, "filename", file, "commented", "FALSE", NULL);
1147
1148 if (!vars) {
1149 ast_log(LOG_WARNING, "Could not find config '%s' in directory.\n", file);
1150 return NULL;
1151 }
1152
1153 /*! \note Since the items come back in random order, they need to be sorted
1154 * first, and since the data could easily exceed stack size, this is
1155 * allocated from the heap.
1156 */
1157 if (!(categories = ast_calloc(vars_count, sizeof(*categories)))) {
1158 return NULL;
1159 }
1160
1161 for (vars_count = 0, p = vars; *p; p++) {
1162 struct ast_variable *category = variable_named(*p, "category");
1163 struct ast_variable *cat_metric = variable_named(*p, "cat_metric");
1164 struct ast_variable *var_name = variable_named(*p, "variable_name");
1165 struct ast_variable *var_val = variable_named(*p, "variable_value");
1166 struct ast_variable *var_metric = variable_named(*p, "var_metric");
1167 struct ast_variable *dn = variable_named(*p, "dn");
1168
1169 if (!category) {
1170 ast_log(LOG_ERROR, "No category name in entry '%s' for file '%s'.\n",
1171 (dn ? dn->value : "?"), file);
1172 } else if (!cat_metric) {
1173 ast_log(LOG_ERROR, "No category metric in entry '%s'(category: %s) for file '%s'.\n",
1174 (dn ? dn->value : "?"), category->value, file);
1175 } else if (!var_metric) {
1176 ast_log(LOG_ERROR, "No variable metric in entry '%s'(category: %s) for file '%s'.\n",
1177 (dn ? dn->value : "?"), category->value, file);
1178 } else if (!var_name) {
1179 ast_log(LOG_ERROR, "No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
1180 (dn ? dn->value : "?"), category->value,
1181 cat_metric->value, file);
1182 } else if (!var_val) {
1183 ast_log(LOG_ERROR, "No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
1184 (dn ? dn->value : "?"), category->value,
1185 cat_metric->value, var_name->value, file);
1186 } else {
1187 categories[vars_count].name = category->value;
1188 categories[vars_count].metric = atoi(cat_metric->value);
1189 categories[vars_count].variable_name = var_name->value;
1190 categories[vars_count].variable_value = var_val->value;
1191 categories[vars_count].var_metric = atoi(var_metric->value);
1192 vars_count++;
1193 }
1194
1195 ast_debug(3, "category: %s\n", category->value);
1196 ast_debug(3, "var_name: %s\n", var_name->value);
1197 ast_debug(3, "var_val: %s\n", var_val->value);
1198 ast_debug(3, "cat_metric: %s\n", cat_metric->value);
1199
1200 }
1201
1202 qsort(categories, vars_count, sizeof(*categories), compare_categories);
1203
1204 for (i = 0; i < vars_count; i++) {
1205 if (!strcmp(categories[i].variable_name, "#include")) {
1206 struct ast_flags flags = { 0 };
1207 if (!ast_config_internal_load(categories[i].variable_value, cfg, flags, "", who_asked)) {
1208 break;
1209 }
1210 continue;
1211 }
1212
1213 if (!last_category || strcmp(last_category, categories[i].name) ||
1214 last_category_metric != categories[i].metric) {
1215
1217 if (!cur_cat) {
1218 break;
1219 }
1220 last_category = categories[i].name;
1221 last_category_metric = categories[i].metric;
1222 ast_category_append(cfg, cur_cat);
1223 }
1224
1225 if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name))) {
1226 break;
1227 }
1228
1229 ast_variable_append(cur_cat, new_v);
1230 }
1231
1232 ast_free(vars);
1234
1235 return cfg;
1236}
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#define ast_variable_new(name, value, filename)
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
Definition: main/config.c:3279
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
#define LOG_ERROR
#define LOG_WARNING
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_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 * variable_named(struct ast_variable *var, const char *name)
Find variable by name.
#define RES_CONFIG_LDAP_CONF
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Structure for variables, used for configurations and for channel variables.
struct association categories[]

References ast_calloc, ast_category_append(), ast_category_new_dynamic, ast_config_internal_load(), ast_debug, ast_free, ast_log, ast_strlen_zero(), ast_variable_append(), ast_variable_new, categories, compare_categories(), make_ari_stubs::file, ast_flags::flags, LOG_ERROR, LOG_WARNING, name, NULL, realtime_ldap_base(), RES_CONFIG_LDAP_CONF, ast_variable::value, and variable_named().

◆ convert_attribute_name_from_ldap()

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.

282{
283 int i = 0;
284 struct ldap_table_config *configs[] = { table_config, base_table_config };
285
286 for (i = 0; i < ARRAY_LEN(configs); i++) {
287 struct ast_variable *attribute;
288
289 if (!configs[i]) {
290 continue;
291 }
292
293 attribute = configs[i]->attributes;
294 for (; attribute; attribute = attribute->next) {
295 if (strcasecmp(attribute_name, attribute->value) == 0) {
296 return attribute->name;
297 }
298 }
299 }
300
301 return attribute_name;
302}
static struct ldap_table_config * base_table_config
struct ast_variable * next
Table configuration.
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, 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().

◆ convert_attribute_name_to_ldap()

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.

254{
255 int i = 0;
256 struct ldap_table_config *configs[] = { table_config, base_table_config };
257
258 for (i = 0; i < ARRAY_LEN(configs); i++) {
259 struct ast_variable *attribute;
260
261 if (!configs[i]) {
262 continue;
263 }
264
265 attribute = configs[i]->attributes;
266 for (; attribute; attribute = attribute->next) {
267 if (!strcasecmp(attribute_name, attribute->name)) {
268 return attribute->value;
269 }
270 }
271 }
272
273 return attribute_name;
274}

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

Referenced by append_var_and_value_to_filter(), and update2_ldap().

◆ create_lookup_filter()

static struct ast_str * create_lookup_filter ( struct ldap_table_config config,
const struct ast_variable fields 
)
static

Definition at line 772 of file res_config_ldap.c.

773{
774 struct ast_str *filter;
775 const struct ast_variable *field;
776
778 if (!filter) {
779 return NULL;
780 }
781
782 /*
783 * Create the filter with the table additional filter and the
784 * parameter/value pairs we were given
785 */
786 ast_str_append(&filter, 0, "(&");
787 if (config && config->additional_filter) {
788 ast_str_append(&filter, 0, "%s", config->additional_filter);
789 }
794 }
795 /* Append the lookup fields */
796 for (field = fields; field; field = field->next) {
798 }
799 ast_str_append(&filter, 0, ")");
800
801 return filter;
802}
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.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
Support for dynamic strings.
Definition: strings.h:623

References ldap_table_config::additional_filter, append_var_and_value_to_filter(), ast_str_append(), ast_str_create, base_table_config, config, filter(), ast_variable::name, ast_variable::next, NULL, and ast_variable::value.

Referenced by realtime_ldap_base_ap(), and update2_ldap().

◆ is_ldap_connect_error()

static int is_ldap_connect_error ( int  err)
static

Check if we have a connection error.

Definition at line 582 of file res_config_ldap.c.

583{
584 return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
585}

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

◆ ldap_entry_has_attribute()

static int ldap_entry_has_attribute ( LDAPMessage *  entry,
const char *  lookup 
)
static

Definition at line 1399 of file res_config_ldap.c.

1400{
1401 BerElement *ber = NULL;
1402 char *attribute;
1403
1404 attribute = ldap_first_attribute(ldapConn, entry, &ber);
1405 while (attribute) {
1406 if (!strcasecmp(attribute, lookup)) {
1407 ldap_memfree(attribute);
1408 ber_free(ber, 0);
1409 return 1;
1410 }
1411 ldap_memfree(attribute);
1412 attribute = ldap_next_attribute(ldapConn, entry, ber);
1413 }
1414 ber_free(ber, 0);
1415 return 0;
1416}
static LDAP * ldapConn
Definition: search.h:40

References ldapConn, and NULL.

Referenced by massage_mods_for_entry().

◆ ldap_loadentry()

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

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

596{
597 if (!table_config) {
598 ast_log(LOG_ERROR, "No table config\n");
599 return NULL;
600 } else {
601 struct ast_variable **vars = NULL;
602 struct ast_variable *var = NULL;
603 int result = -1;
604 LDAPMessage *ldap_result_msg = NULL;
605 int tries = 0;
606
607 ast_debug(2, "ldap_loadentry dn=%s\n", dn);
608
609 do {
610 result = ldap_search_ext_s(ldapConn, dn, LDAP_SCOPE_BASE,
611 "(objectclass=*)", NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg);
612 if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
613 ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
614 tries++;
615 if (tries < 3) {
616 usleep(500000L * tries);
617 if (ldapConn) {
618 ldap_unbind_ext_s(ldapConn, NULL, NULL);
619 ldapConn = NULL;
620 }
621 if (!ldap_reconnect()) {
622 break;
623 }
624 }
625 }
626 } while (result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(result));
627
628 if (result != LDAP_SUCCESS) {
629 ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
630 ast_debug(2, "dn=%s\n", dn);
632 return NULL;
633 } else {
634 int num_entry = 0;
635 unsigned int *entries_count_ptr = NULL; /*!< not using this */
636
637 if ((num_entry = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
638 ast_debug(3, "num_entry: %d\n", num_entry);
639
640 vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
641 if (num_entry > 1) {
642 ast_log(LOG_NOTICE, "More than one entry for dn=%s. Take only 1st one\n", dn);
643 }
644 } else {
645 ast_debug(2, "Could not find any entry dn=%s.\n", dn);
646 }
647 }
648 ldap_msgfree(ldap_result_msg);
649
650 /* Chopping \a vars down to one variable */
651 if (vars != NULL) {
652 struct ast_variable **p = vars;
653
654 /* Only take the first one. */
655 var = *vars;
656
657 /* Destroy the rest. */
658 while (*++p) {
660 }
661 ast_free(vars);
662 }
663
664 return var;
665 }
666}
#define var
Definition: ast_expr2f.c:605
static PGresult * result
Definition: cel_pgsql.c:84
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define LOG_NOTICE
#define ast_mutex_unlock(a)
Definition: lock.h:190
static ast_mutex_t ldap_lock
static int ldap_reconnect(void)
static int is_ldap_connect_error(int err)
Check if we have a connection error.
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.

References ast_debug, ast_free, ast_log, ast_mutex_unlock, ast_variables_destroy(), is_ldap_connect_error(), ldap_lock, ldap_reconnect(), ldapConn, LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, realtime_ldap_result_to_vars(), result, and var.

Referenced by realtime_ldap_base_ap().

◆ ldap_mod_append()

static LDAPMod * ldap_mod_append ( LDAPMod *  src,
const char *  new_value 
)
static

Definition at line 1297 of file res_config_ldap.c.

1298{
1299 char *new_buffer;
1300
1301 if (src->mod_op != LDAP_MOD_REPLACE) {
1302 return src;
1303 }
1304
1305 new_buffer = ldap_memrealloc(
1306 src->mod_values[0],
1307 strlen(src->mod_values[0]) + strlen(new_value) + sizeof(";"));
1308
1309 if (!new_buffer) {
1310 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1311 return NULL;
1312 }
1313
1314 strcat(new_buffer, ";");
1315 strcat(new_buffer, new_value);
1316
1317 src->mod_values[0] = new_buffer;
1318
1319 return src;
1320}

References ast_log, LOG_ERROR, and NULL.

Referenced by update2_ldap().

◆ ldap_mod_create()

static LDAPMod * ldap_mod_create ( const char *  attribute,
const char *  new_value 
)
static

Definition at line 1247 of file res_config_ldap.c.

1248{
1249 LDAPMod *mod;
1250 char *type;
1251
1252 mod = ldap_memcalloc(1, sizeof(LDAPMod));
1253 type = ldap_strdup(attribute);
1254
1255 if (!(mod && type)) {
1256 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1257 ldap_memfree(type);
1258 ldap_memfree(mod);
1259 return NULL;
1260 }
1261
1262 mod->mod_type = type;
1263
1264 if (strlen(new_value)) {
1265 char **values, *value;
1266 values = ldap_memcalloc(2, sizeof(char *));
1267 value = ldap_strdup(new_value);
1268
1269 if (!(values && value)) {
1270 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1271 ldap_memfree(value);
1272 ldap_memfree(values);
1273 ldap_memfree(type);
1274 ldap_memfree(mod);
1275 return NULL;
1276 }
1277
1278 mod->mod_op = LDAP_MOD_REPLACE;
1279 mod->mod_values = values;
1280 mod->mod_values[0] = value;
1281 } else {
1282 mod->mod_op = LDAP_MOD_DELETE;
1283 }
1284
1285 return mod;
1286}
static const char type[]
Definition: chan_ooh323.c:109

References ast_log, LOG_ERROR, NULL, type, and value.

Referenced by update2_ldap().

◆ ldap_mod_duplicate()

static LDAPMod * ldap_mod_duplicate ( const LDAPMod *  src)
static

Definition at line 1330 of file res_config_ldap.c.

1331{
1332 LDAPMod *mod;
1333 char *type, **values = NULL;
1334
1335 mod = ldap_memcalloc(1, sizeof(LDAPMod));
1336 type = ldap_strdup(src->mod_type);
1337
1338 if (!(mod && type)) {
1339 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1340 ldap_memfree(type);
1341 ldap_memfree(mod);
1342 return NULL;
1343 }
1344
1345 if (src->mod_op == LDAP_MOD_REPLACE) {
1346 char *value;
1347
1348 values = ldap_memcalloc(2, sizeof(char *));
1349 value = ldap_strdup(src->mod_values[0]);
1350
1351 if (!(values && value)) {
1352 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1353 ldap_memfree(value);
1354 ldap_memfree(values);
1355 ldap_memfree(type);
1356 ldap_memfree(mod);
1357 return NULL;
1358 }
1359
1360 values[0] = value;
1361 }
1362
1363 mod->mod_op = src->mod_op;
1364 mod->mod_type = type;
1365 mod->mod_values = values;
1366 return mod;
1367}

References ast_log, LOG_ERROR, NULL, type, and value.

Referenced by massage_mods_for_entry().

◆ ldap_mod_find()

static LDAPMod * ldap_mod_find ( LDAPMod **  modifications,
const char *  lookup 
)
static

Definition at line 1378 of file res_config_ldap.c.

1379{
1380 size_t i;
1381 for (i = 0; modifications[i]; i++) {
1382 if (modifications[i]->mod_op == LDAP_MOD_REPLACE &&
1383 !strcasecmp(modifications[i]->mod_type, lookup)) {
1384 return modifications[i];
1385 }
1386 }
1387 return NULL;
1388}

References NULL.

Referenced by update2_ldap().

◆ ldap_reconnect()

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

Definition at line 1912 of file res_config_ldap.c.

1913{
1914 int bind_result = 0;
1915 struct berval cred;
1916
1917 if (ldapConn) {
1918 ast_debug(2, "Everything seems fine.\n");
1919 return 1;
1920 }
1921
1922 if (ast_strlen_zero(url)) {
1923 ast_log(LOG_ERROR, "Not enough parameters to connect to ldap directory\n");
1924 return 0;
1925 }
1926
1927 if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
1928 ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
1929 return 0;
1930 }
1931
1932 if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
1933 ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
1934 }
1935
1936 if (!ast_strlen_zero(user)) {
1937 ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
1938 cred.bv_val = (char *) pass;
1939 cred.bv_len = strlen(pass);
1940 bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
1941 } else {
1942 ast_debug(2, "bind %s anonymously\n", url);
1943 cred.bv_val = NULL;
1944 cred.bv_len = 0;
1945 bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
1946 }
1947 if (bind_result == LDAP_SUCCESS) {
1948 ast_debug(2, "Successfully connected to directory.\n");
1949 connect_time = time(NULL);
1950 return 1;
1951 } else {
1952 ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
1953 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1954 ldapConn = NULL;
1955 return 0;
1956 }
1957}
static char pass[512]
static char url[512]
static int version
static time_t connect_time
structure to hold users read from users.conf

References ast_debug, ast_log, ast_strlen_zero(), connect_time, ldapConn, LOG_ERROR, LOG_WARNING, NULL, pass, url, and version.

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

◆ ldap_table_config_add_attribute()

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.

206{
207 struct ast_variable *var;
208
209 if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value)) {
210 return;
211 }
212
213 if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->table_name))) {
214 return;
215 }
216
217 if (table_config->attributes) {
218 var->next = table_config->attributes;
219 }
220 table_config->attributes = var;
221}
struct ast_variable * attributes

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

Referenced by parse_config().

◆ load_module()

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

1718{
1719 if (parse_config() < 0) {
1720 ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
1721 return 0;
1722 }
1723
1725
1726 if (!ldap_reconnect()) {
1727 ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
1728 }
1729
1731 ast_verb(1, "LDAP RealTime driver loaded.\n");
1733
1735
1736 return 0;
1737}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: main/config.c:3157
#define ast_verb(level,...)
#define ast_mutex_lock(a)
Definition: lock.h:189
static struct ast_cli_entry ldap_cli[]
static struct ast_config_engine ldap_engine
static int parse_config(void)
parse the configuration file

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

◆ massage_mods_for_entry()

static LDAPMod ** massage_mods_for_entry ( LDAPMessage *  entry,
LDAPMod **  mods 
)
static

Definition at line 1434 of file res_config_ldap.c.

1435{
1436 size_t k, i, remove_count;
1437 LDAPMod **copies;
1438
1439 for (i = remove_count = 0; mods[i]; i++) {
1440 if (mods[i]->mod_op == LDAP_MOD_DELETE
1441 && !ldap_entry_has_attribute(entry, mods[i]->mod_type)) {
1442 remove_count++;
1443 }
1444 }
1445
1446 if (!remove_count) {
1447 return NULL;
1448 }
1449
1450 copies = ldap_memcalloc(i - remove_count + 1, sizeof(LDAPMod *));
1451 if (!copies) {
1452 ast_log(LOG_ERROR, "Memory allocation failure massaging LDAP modification\n");
1453 return NULL;
1454 }
1455
1456 for (i = k = 0; mods[i]; i++) {
1457 if (mods[i]->mod_op != LDAP_MOD_DELETE
1458 || ldap_entry_has_attribute(entry, mods[i]->mod_type)) {
1459 copies[k] = ldap_mod_duplicate(mods[i]);
1460 if (!copies[k]) {
1461 ast_log(LOG_ERROR, "Memory allocation failure massaging LDAP modification\n");
1462 ldap_mods_free(copies, 1);
1463 return NULL;
1464 }
1465 k++;
1466 } else {
1467 ast_debug(3, "Skipping %s deletion because it doesn't exist\n",
1468 mods[i]->mod_type);
1469 }
1470 }
1471
1472 return copies;
1473}
static int ldap_entry_has_attribute(LDAPMessage *entry, const char *lookup)
static LDAPMod * ldap_mod_duplicate(const LDAPMod *src)

References ast_debug, ast_log, ldap_entry_has_attribute(), ldap_mod_duplicate(), LOG_ERROR, and NULL.

Referenced by update2_ldap().

◆ parse_config()

static int parse_config ( void  )
static

parse the configuration file

< using the [config] context for Static RealTime

Definition at line 1810 of file res_config_ldap.c.

1811{
1812 struct ast_config *config;
1813 struct ast_flags config_flags = {0};
1814 const char *s, *host;
1815 int port;
1816 char *category_name = NULL;
1817
1818 /* Make sure that global variables are reset */
1819 url[0] = '\0';
1820 user[0] = '\0';
1821 pass[0] = '\0';
1822 base_distinguished_name[0] = '\0';
1823 version = 3;
1824
1827 ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
1828 return -1;
1829 }
1830
1831 if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
1832 ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
1833 user[0] = '\0';
1834 } else {
1835 ast_copy_string(user, s, sizeof(user));
1836 }
1837
1838 if (!ast_strlen_zero(user)) {
1839 if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
1840 ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
1841 ast_copy_string(pass, "asterisk", sizeof(pass));
1842 } else {
1843 ast_copy_string(pass, s, sizeof(pass));
1844 }
1845 }
1846
1847 /* URL is preferred, use host and port if not found */
1848 if ((s = ast_variable_retrieve(config, "_general", "url"))) {
1849 ast_copy_string(url, s, sizeof(url));
1850 } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
1851 if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
1852 ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
1853 port = 389;
1854 }
1855
1856 snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
1857 } else {
1858 ast_log(LOG_ERROR, "No directory URL or host found.\n");
1860 return -1;
1861 }
1862
1863 if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
1864 ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
1866 } else
1868
1869 if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
1870 ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
1871 } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
1872 ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
1873 version = 3;
1874 }
1875
1877
1878 while ((category_name = ast_category_browse(config, category_name))) {
1879 int is_general = (strcasecmp(category_name, "_general") == 0);
1880 int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
1881 struct ast_variable *var = ast_variable_browse(config, category_name);
1882
1883 if (var) {
1884 struct ldap_table_config *table_config =
1885 table_config_for_table_name(category_name);
1886 if (!table_config) {
1887 table_config = table_config_new(category_name);
1888 AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
1889 if (is_general)
1890 base_table_config = table_config;
1891 if (is_config)
1892 static_table_config = table_config;
1893 }
1894 for (; var; var = var->next) {
1895 if (!strcasecmp(var->name, "additionalFilter")) {
1896 table_config->additional_filter = ast_strdup(var->value);
1897 } else {
1898 if (!is_general || config_can_be_inherited(var->name)) {
1899 ldap_table_config_add_attribute(table_config, var->name, var->value);
1900 }
1901 }
1902 }
1903 }
1904 }
1905
1907
1908 return 1;
1909}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
static int config_can_be_inherited(const char *key)
static struct ldap_table_config * static_table_config
static void table_configs_free(void)
Free table_config.
static struct ldap_table_config * table_config_new(const char *table_name)
Create a new table_config.
static struct ldap_table_config * table_config_for_table_name(const char *table_name)
Find a table_config.
#define RES_CONFIG_LDAP_DEFAULT_BASEDN
static char base_distinguished_name[512]
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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Should be locked before using it.

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_distinguished_name, base_table_config, config, config_can_be_inherited(), CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ldap_table_config_add_attribute(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, pass, RES_CONFIG_LDAP_CONF, RES_CONFIG_LDAP_DEFAULT_BASEDN, static_table_config, table_config_for_table_name(), table_config_new(), table_configs_free(), url, var, and version.

Referenced by load_module(), and reload().

◆ realtime_arguments_to_fields()

static struct ast_variable * realtime_arguments_to_fields ( va_list  ap)
static

Definition at line 962 of file res_config_ldap.c.

963{
964 struct ast_variable *fields = NULL;
965 const char *newparam, *newval;
966
967 while ((newparam = va_arg(ap, const char *))) {
968 struct ast_variable *field;
969
970 newval = va_arg(ap, const char *);
971 if (!(field = ast_variable_new(newparam, newval, ""))) {
972 ast_variables_destroy(fields);
973 return NULL;
974 }
975
976 field->next = fields;
977 fields = field;
978 }
979
980 return fields;
981}

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

Referenced by realtime_ldap_base().

◆ realtime_ldap()

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

See Asterisk doc.

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

Definition at line 1005 of file res_config_ldap.c.

1007{
1008 struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, fields);
1009 struct ast_variable *var = NULL;
1010
1011 if (vars) {
1012 struct ast_variable *last_var = NULL;
1013 struct ast_variable **p = vars;
1014
1015 /* Chain the vars array of lists into one list to return. */
1016 while (*p) {
1017 if (last_var) {
1018 while (last_var->next) {
1019 last_var = last_var->next;
1020 }
1021 last_var->next = *p;
1022 } else {
1023 var = *p;
1024 last_var = var;
1025 }
1026 p++;
1027 }
1028 ast_free(vars);
1029 }
1030 return var;
1031}
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.

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

◆ realtime_ldap_base()

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

same as realtime_ldap_base_ap but take variable arguments count list

Definition at line 985 of file res_config_ldap.c.

987{
989 struct ast_variable **vars = NULL;
990 va_list ap;
991
992 va_start(ap, table_name);
993 fields = realtime_arguments_to_fields(ap);
994 va_end(ap);
995
996 vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, fields);
997
998 return vars;
999}
static struct ast_variable * realtime_arguments_to_fields(va_list ap)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

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

Referenced by config_ldap().

◆ realtime_ldap_base_ap()

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

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_ptris a pointer to found entries count (can be NULL)
basednis the base DN
table_nameis the table_name (used dor attribute convertion and additional filter)
fieldscontains list of pairs name/value
Todo:
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 812 of file res_config_ldap.c.

814{
815 struct ast_variable **vars = NULL;
816 const struct ast_variable *field = fields;
817 struct ldap_table_config *table_config = NULL;
818 char *clean_basedn = cleaned_basedn(NULL, basedn);
819 struct ast_str *filter = NULL;
820 int tries = 0;
821 int result = 0;
822 LDAPMessage *ldap_result_msg = NULL;
823
824 if (!table_name) {
825 ast_log(LOG_ERROR, "No table_name specified.\n");
826 ast_free(clean_basedn);
827 return NULL;
828 }
829
830 if (!field) {
831 ast_log(LOG_ERROR, "Realtime retrieval requires at least 1 parameter"
832 " and 1 value to search on.\n");
833 ast_free(clean_basedn);
834 return NULL;
835 }
836
838
839 /* We now have our complete statement; Lets connect to the server and execute it. */
840 if (!ldap_reconnect()) {
842 ast_free(clean_basedn);
843 return NULL;
844 }
845
846 table_config = table_config_for_table_name(table_name);
847 if (!table_config) {
848 ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
850 ast_free(clean_basedn);
851 return NULL;
852 }
853
854 filter = create_lookup_filter(table_config, fields);
855 if (!filter) {
857 ast_free(clean_basedn);
858 return NULL;
859 }
860
861 do {
862 /* freeing ldap_result further down */
863 result = ldap_search_ext_s(ldapConn, clean_basedn,
864 LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
865 &ldap_result_msg);
866 if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
867 ast_debug(1, "Failed to query directory. Try %d/10\n", tries + 1);
868 if (++tries < 10) {
869 usleep(1);
870 if (ldapConn) {
871 ldap_unbind_ext_s(ldapConn, NULL, NULL);
872 ldapConn = NULL;
873 }
874 if (!ldap_reconnect()) {
875 break;
876 }
877 }
878 }
879 } while (result != LDAP_SUCCESS && tries < 10 && is_ldap_connect_error(result));
880
881 if (result != LDAP_SUCCESS) {
882 ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
883 ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
884 } else {
885 /* this is where we create the variables from the search result
886 * freeing this \a vars outside this function */
887 if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
888 /* is this a static var or some other? they are handled different for delimited values */
889 vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
890 } else {
891 ast_debug(1, "Could not find any entry matching %s in base dn %s.\n", ast_str_buffer(filter), clean_basedn);
892 }
893
894 ldap_msgfree(ldap_result_msg);
895
896 /*! \todo get the default variables from the accountBaseDN, not implemented with delimited values
897 */
898 if (vars) {
899 struct ast_variable **p = vars;
900 while (*p) {
901 struct ast_variable *append_var = NULL;
902 struct ast_variable *tmp = *p;
903 while (tmp) {
904 if (strcasecmp(tmp->name, "accountBaseDN") == 0) {
905 /* Get the variable to compare with for the defaults */
906 struct ast_variable *base_var = ldap_loadentry(table_config, tmp->value);
907
908 while (base_var) {
909 struct ast_variable *next = base_var->next;
910 struct ast_variable *test_var = *p;
911 int base_var_found = 0;
912
913 /* run throught the default values and fill it inn if it is missing */
914 while (test_var) {
915 if (strcasecmp(test_var->name, base_var->name) == 0) {
916 base_var_found = 1;
917 break;
918 } else {
919 test_var = test_var->next;
920 }
921 }
922 if (base_var_found) {
923 base_var->next = NULL;
924 ast_variables_destroy(base_var);
925 base_var = next;
926 } else {
927 /*!
928 * \todo XXX The interactions with base_var and append_var may
929 * cause a memory leak of base_var nodes. Also the append_var
930 * list and base_var list may get cross linked.
931 */
932 if (append_var) {
933 base_var->next = append_var;
934 } else {
935 base_var->next = NULL;
936 }
937 append_var = base_var;
938 base_var = next;
939 }
940 }
941 }
942 if (!tmp->next && append_var) {
943 tmp->next = append_var;
944 tmp = NULL;
945 } else {
946 tmp = tmp->next;
947 }
948 }
949 p++;
950 }
951 }
952 }
953
955 ast_free(clean_basedn);
956
958
959 return vars;
960}
static int tmp()
Definition: bt_open.c:389
static char * cleaned_basedn(struct ast_channel *channel, const char *basedn)
static struct ast_str * create_lookup_filter(struct ldap_table_config *config, const struct ast_variable *fields)
static struct ast_variable * ldap_loadentry(struct ldap_table_config *table_config, const char *dn)
Get LDAP entry by dn and return attributes as variables.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761

References ast_debug, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), ast_variables_destroy(), cleaned_basedn(), create_lookup_filter(), filter(), is_ldap_connect_error(), ldap_loadentry(), ldap_lock, ldap_reconnect(), ldapConn, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, realtime_ldap_result_to_vars(), result, table_config_for_table_name(), and tmp().

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

◆ realtime_ldap_entry_to_var()

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

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.

310{
311 BerElement *ber = NULL;
312 struct ast_variable *var = NULL;
313 struct ast_variable *prev = NULL;
314#if 0
315 int is_delimited = 0;
316 int i = 0;
317#endif
318 char *ldap_attribute_name;
319 struct berval *value;
320 int pos = 0;
321
322 ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
323
324 while (ldap_attribute_name) {
325 struct berval **values = NULL;
326 const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
327 int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
328
329 values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name); /* these are freed at the end */
330 if (values) {
331 struct berval **v;
332 char *valptr;
333
334 for (v = values; *v; v++) {
335 value = *v;
336 valptr = value->bv_val;
337 ast_debug(2, "attribute_name: %s LDAP value: %s\n", attribute_name, valptr);
338 if (is_realmed_password_attribute) {
339 if (!strncasecmp(valptr, "{md5}", 5)) {
340 valptr += 5;
341 }
342 ast_debug(2, "md5: %s\n", valptr);
343 }
344 if (valptr) {
345#if 0
346 /* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
347 if (is_delimited) {
348 i = 0;
349 pos = 0;
350 while (!ast_strlen_zero(valptr + i)) {
351 if (valptr[i] == ';') {
352 valptr[i] = '\0';
353 if (prev) {
354 prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
355 if (prev->next) {
356 prev = prev->next;
357 }
358 } else {
359 prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
360 }
361 pos = i + 1;
362 }
363 i++;
364 }
365 }
366#endif
367 /* for the last delimited value or if the value is not delimited: */
368 if (prev) {
369 prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
370 if (prev->next) {
371 prev = prev->next;
372 }
373 } else {
374 prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
375 }
376 }
377 }
378 ldap_value_free_len(values);
379 }
380 ldap_memfree(ldap_attribute_name);
381 ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
382 }
383 ber_free(ber, 0);
384
385 return var;
386}
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.

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

Referenced by realtime_ldap_result_to_vars().

◆ realtime_ldap_result_to_vars()

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

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.

First find the total count

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.

For each static realtime variable we may create several entries in the vars array if it's delimited

Definition at line 394 of file res_config_ldap.c.

396{
397 struct ast_variable **vars;
398 int i = 0;
399 int tot_count = 0;
400 int entry_index = 0;
401 LDAPMessage *ldap_entry = NULL;
402 BerElement *ber = NULL;
403 struct ast_variable *var = NULL;
404 struct ast_variable *prev = NULL;
405 int is_delimited = 0;
406 char *delim_value = NULL;
407 int delim_tot_count = 0;
408 int delim_count = 0;
409
410 /*! \brief First find the total count
411 */
412 ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
413
414 for (tot_count = 0; ldap_entry; tot_count++) {
415 struct ast_variable *tmp = realtime_ldap_entry_to_var(table_config, ldap_entry);
416 tot_count += semicolon_count_var(tmp);
417 ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
419 }
420
421 if (entries_count_ptr) {
422 *entries_count_ptr = tot_count;
423 }
424
425 /*! \note Now that we have the total count we allocate space and create the variables
426 * Remember that each element in vars is a linked list that points to realtime variable.
427 * If the we are dealing with a static realtime variable we create a new element in the \a vars array for each delimited
428 * 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.
429 * This memory must be freed outside of this function.
430 */
431 vars = ast_calloc(tot_count + 1, sizeof(struct ast_variable *));
432
433 ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
434
435 i = 0;
436
437 /*! \brief For each static realtime variable we may create several entries in the \a vars array if it's delimited
438 */
439 for (entry_index = 0; ldap_entry; ) {
440 int pos = 0;
441 delim_value = NULL;
442 delim_tot_count = 0;
443 delim_count = 0;
444
445 do { /* while delim_count */
446
447 /* Starting new static var */
448 char *ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
449 struct berval *value;
450 while (ldap_attribute_name) {
451 const char *attribute_name = convert_attribute_name_from_ldap(table_config, ldap_attribute_name);
452 int is_realmed_password_attribute = strcasecmp(attribute_name, "md5secret") == 0;
453 struct berval **values = NULL;
454
455 values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
456 if (values) {
457 struct berval **v;
458 char *valptr;
459
460 for (v = values; *v; v++) {
461 value = *v;
462 valptr = value->bv_val;
463 if (is_realmed_password_attribute) {
464 if (strncasecmp(valptr, "{md5}", 5) == 0) {
465 valptr += 5;
466 }
467 ast_debug(2, "md5: %s\n", valptr);
468 }
469 if (valptr) {
470 if (delim_value == NULL && !is_realmed_password_attribute
471 && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0)) {
472
473 delim_value = ast_strdup(valptr);
474
475 if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
476 ast_debug(4, "is delimited %d times: %s\n", delim_tot_count, delim_value);
477 is_delimited = 1;
478 }
479 }
480
481 if (is_delimited != 0 && !is_realmed_password_attribute
482 && (static_table_config != table_config || strcmp(attribute_name, "variable_value") == 0) ) {
483 /* for non-Static RealTime, first */
484
485 for (i = pos; !ast_strlen_zero(valptr + i); i++) {
486 ast_debug(4, "DELIM pos: %d i: %d\n", pos, i);
487 if (delim_value[i] == ';') {
488 delim_value[i] = '\0';
489
490 ast_debug(2, "DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos);
491
492 if (prev) {
493 prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
494 if (prev->next) {
495 prev = prev->next;
496 }
497 } else {
498 prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
499 }
500 pos = i + 1;
501
502 if (static_table_config == table_config) {
503 break;
504 }
505 }
506 }
507 if (ast_strlen_zero(valptr + i)) {
508 ast_debug(4, "DELIM pos: %d i: %d delim_count: %d\n", pos, i, delim_count);
509 /* Last delimited value */
510 ast_debug(4, "DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos);
511 if (prev) {
512 prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
513 if (prev->next) {
514 prev = prev->next;
515 }
516 } else {
517 prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
518 }
519 /* Remembering to free memory */
520 is_delimited = 0;
521 pos = 0;
522 }
523 ast_free(delim_value);
524 delim_value = NULL;
525
526 ast_debug(4, "DELIM pos: %d i: %d\n", pos, i);
527 } else {
528 /* not delimited */
529 if (delim_value) {
530 ast_free(delim_value);
531 delim_value = NULL;
532 }
533 ast_debug(2, "attribute_name: %s value: %s\n", attribute_name, valptr);
534
535 if (prev) {
536 prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
537 if (prev->next) {
538 prev = prev->next;
539 }
540 } else {
541 prev = var = ast_variable_new(attribute_name, valptr, table_config->table_name);
542 }
543 }
544 }
545 } /*!< for (v = values; *v; v++) */
546 ldap_value_free_len(values);
547 }/*!< if (values) */
548 ldap_memfree(ldap_attribute_name);
549 ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
550 } /*!< while (ldap_attribute_name) */
551 ber_free(ber, 0);
552 if (static_table_config == table_config) {
553 if (DEBUG_ATLEAST(3)) {
554 const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
555 const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
556 if (tmpdebug && tmpdebug2) {
557 ast_log(LOG_DEBUG, "Added to vars - %s = %s\n", tmpdebug->value, tmpdebug2->value);
558 }
559 }
560 vars[entry_index++] = var;
561 prev = NULL;
562 }
563
564 delim_count++;
565 } while (delim_count <= delim_tot_count && static_table_config == table_config);
566
567 if (static_table_config != table_config) {
568 ast_debug(3, "Added to vars - non static\n");
569
570 vars[entry_index++] = var;
571 prev = NULL;
572 }
573 ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
574 } /*!< end for loop over ldap_entry */
575
576 return vars;
577}
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
static struct ast_variable * realtime_ldap_entry_to_var(struct ldap_table_config *table_config, LDAPMessage *ldap_entry)
Get variables from ldap entry attributes.
static int semicolon_count_var(struct ast_variable *var)
Count semicolons in variables.
static int semicolon_count_str(const char *somestr)
Count semicolons in string.

References ast_calloc, ast_debug, ast_free, ast_log, ast_strdup, ast_strlen_zero(), ast_variable_new, ast_variables_destroy(), convert_attribute_name_from_ldap(), DEBUG_ATLEAST, ldapConn, LOG_DEBUG, ast_variable::next, NULL, 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().

◆ realtime_ldap_status()

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

Realtime Status.

Definition at line 1962 of file res_config_ldap.c.

1963{
1964 struct ast_str *buf;
1965 int ctimesec = time(NULL) - connect_time;
1966
1967 switch (cmd) {
1968 case CLI_INIT:
1969 e->command = "realtime show ldap status";
1970 e->usage =
1971 "Usage: realtime show ldap status\n"
1972 " Shows connection information for the LDAP RealTime driver\n";
1973 return NULL;
1974 case CLI_GENERATE:
1975 return NULL;
1976 }
1977
1978 if (!ldapConn)
1979 return CLI_FAILURE;
1980
1981 buf = ast_str_create(512);
1982 if (!ast_strlen_zero(url)) {
1983 ast_str_append(&buf, 0, "Connected to '%s', baseDN %s", url, base_distinguished_name);
1984 }
1985
1986 if (!ast_strlen_zero(user)) {
1987 ast_str_append(&buf, 0, " with username %s", user);
1988 }
1989
1990 ast_str_append(&buf, 0, " for ");
1992 ast_free(buf);
1993
1994 return CLI_SUCCESS;
1995}
void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix)
Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s),...
Definition: main/cli.c:3051
#define CLI_SUCCESS
Definition: cli.h:44
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177

References a, ast_cli_print_timestr_fromseconds(), ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, ast_strlen_zero(), base_distinguished_name, buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, connect_time, ldapConn, NULL, url, and ast_cli_entry::usage.

◆ realtime_multi_ldap()

static struct ast_config * realtime_multi_ldap ( const char *  basedn,
const char *  table_name,
const struct ast_variable fields 
)
static

See Asterisk doc.

this function will be called for the switch statement 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 1040 of file res_config_ldap.c.

1042{
1043 char *op;
1044 const char *initfield = NULL;
1045 struct ast_variable **vars =
1046 realtime_ldap_base_ap(NULL, basedn, table_name, fields);
1047 struct ast_config *cfg = NULL;
1048
1049 if (!fields) {
1050 ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
1051 return NULL;
1052 }
1053 initfield = ast_strdupa(fields->name);
1054 if ((op = strchr(initfield, ' '))) {
1055 *op = '\0';
1056 }
1057
1058 if (vars) {
1059 cfg = ast_config_new();
1060 if (!cfg) {
1061 ast_log(LOG_ERROR, "Unable to create a config!\n");
1062 } else {
1063 struct ast_variable **p = vars;
1064
1065 while (*p) {
1067 if (!cat) {
1068 break;
1069 } else {
1070 struct ast_variable *var = *p;
1071 while (var) {
1072 struct ast_variable *next = var->next;
1073 if (initfield && !strcmp(initfield, var->name)) {
1074 ast_category_rename(cat, var->value);
1075 }
1076 var->next = NULL;
1078 var = next;
1079 }
1080 }
1081 ast_category_append(cfg, cat);
1082 p++;
1083 }
1084 }
1085 ast_free(vars);
1086 }
1087 return cfg;
1088
1089}
void ast_category_rename(struct ast_category *cat, const char *name)
Definition: main/config.c:1451
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.

References ast_category_append(), ast_category_new_anonymous, 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, NULL, realtime_ldap_base_ap(), and var.

◆ reload()

static int reload ( void  )
static

Reload Module.

Definition at line 1765 of file res_config_ldap.c.

1766{
1767 /* Aquire control before doing anything to the module itself. */
1769
1770 if (ldapConn) {
1771 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1772 ldapConn = NULL;
1773 }
1774
1775 if (parse_config() < 0) {
1776 ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
1778 return 0;
1779 }
1780
1781 if (!ldap_reconnect()) {
1782 ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
1783 }
1784
1785 ast_verb(2, "LDAP RealTime driver reloaded.\n");
1786
1787 /* Done reloading. Release lock so others can now use driver. */
1789
1790 return 0;
1791}

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

◆ replace_string_in_string()

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

715{
716 int search_len = strlen(search);
717 int by_len = strlen(by);
718 int replaced = 0;
719 char *p = strstr(string, search);
720
721 if (p) {
722 replaced = 1;
723 while (p) {
724 if (by_len == search_len) {
725 memcpy(p, by, by_len);
726 } else {
727 memmove(p + by_len, p + search_len, strlen(p + search_len) + 1);
728 memcpy(p, by, by_len);
729 }
730 p = strstr(p + by_len, search);
731 }
732 }
733 return replaced;
734}

Referenced by append_var_and_value_to_filter().

◆ semicolon_count_str()

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

170{
171 int count = 0;
172
173 for (; *somestr; somestr++) {
174 if (*somestr == ';')
175 count++;
176 }
177
178 return count;
179}

Referenced by realtime_ldap_result_to_vars(), and semicolon_count_var().

◆ semicolon_count_var()

static int semicolon_count_var ( struct ast_variable var)
static

Count semicolons in variables.

takes a linked list of ast_variable variables, finds the one with the name variable_value and returns the number of semicolons in the value for that ast_variable

Definition at line 187 of file res_config_ldap.c.

188{
189 struct ast_variable *var_value = variable_named(var, "variable_value");
190
191 if (!var_value) {
192 return 0;
193 }
194
195 ast_debug(2, "semicolon_count_var: %s\n", var_value->value);
196
197 return semicolon_count_str(var_value->value);
198}

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

Referenced by realtime_ldap_result_to_vars().

◆ substituted()

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

Definition at line 670 of file res_config_ldap.c.

671{
672#define MAXRESULT 2048
673 char *ret_string = NULL;
674
675 if (!ast_strlen_zero(string)) {
676 ret_string = ast_calloc(1, MAXRESULT);
677 pbx_substitute_variables_helper(channel, string, ret_string, MAXRESULT - 1);
678 }
679 ast_debug(2, "substituted: string: '%s' => '%s' \n", string, ret_string);
680 return ret_string;
681}
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
#define MAXRESULT

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

Referenced by cleaned_basedn(), and handle_eval_function().

◆ table_config_for_table_name()

static struct ldap_table_config * table_config_for_table_name ( const char *  table_name)
static

Find a table_config.

Should be locked before using it

Note
This function assumes ldap_lock to be locked.

Definition at line 139 of file res_config_ldap.c.

140{
141 struct ldap_table_config *c = NULL;
142
144 if (!strcmp(c->table_name, table_name))
145 break;
146 }
147
148 return c;
149}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
static struct test_val c

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

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

◆ table_config_new()

static struct ldap_table_config * table_config_new ( const char *  table_name)
static

Create a new table_config.

Definition at line 116 of file res_config_ldap.c.

117{
118 struct ldap_table_config *p;
119
120 if (!(p = ast_calloc(1, sizeof(*p))))
121 return NULL;
122
123 if (table_name) {
124 if (!(p->table_name = ast_strdup(table_name))) {
125 ast_free(p);
126 return NULL;
127 }
128 }
129
130 return p;
131}

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

Referenced by parse_config().

◆ table_configs_free()

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.

228{
229 struct ldap_table_config *c;
230
232 if (c->table_name) {
233 ast_free(c->table_name);
234 }
235 if (c->additional_filter) {
236 ast_free(c->additional_filter);
237 }
238 if (c->attributes) {
239 ast_variables_destroy(c->attributes);
240 }
241 ast_free(c);
242 }
243
246}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

References ast_free, AST_LIST_REMOVE_HEAD, ast_variables_destroy(), base_table_config, c, NULL, and static_table_config.

Referenced by parse_config(), and unload_module().

◆ unload_module()

static int unload_module ( void  )
static

Unload Module.

Definition at line 1742 of file res_config_ldap.c.

1743{
1744 /* Aquire control before doing anything to the module itself. */
1746
1748
1749 if (ldapConn) {
1750 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1751 ldapConn = NULL;
1752 }
1755 ast_verb(1, "LDAP RealTime driver unloaded.\n");
1756
1757 /* Unlock so something else can destroy the lock. */
1759
1760 return 0;
1761}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: main/config.c:3173

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, ldapConn, NULL, and table_configs_free().

◆ update2_ldap()

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

1494{
1495 const struct ast_variable *field;
1496 struct ldap_table_config *table_config = NULL;
1497 char *clean_basedn = NULL;
1498 struct ast_str *filter = NULL;
1499 int search_result = 0;
1500 int res = -1;
1501 int tries = 0;
1502 size_t update_count, update_index, entry_count;
1503
1504 LDAPMessage *ldap_entry = NULL;
1505 LDAPMod **modifications;
1506 LDAPMessage *ldap_result_msg = NULL;
1507
1508 if (!table_name) {
1509 ast_log(LOG_ERROR, "No table_name specified.\n");
1510 return res;
1511 }
1512
1513 update_count = variables_count(update_fields);
1514 if (!update_count) {
1515 ast_log(LOG_WARNING, "Need at least one parameter to modify.\n");
1516 return res;
1517 }
1518
1520
1521 /* We now have our complete statement; Lets connect to the server and execute it. */
1522 if (!ldap_reconnect()) {
1524 return res;
1525 }
1526
1527 table_config = table_config_for_table_name(table_name);
1528 if (!table_config) {
1529 ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
1531 return res;
1532 }
1533
1534 clean_basedn = cleaned_basedn(NULL, basedn);
1535
1536 filter = create_lookup_filter(table_config, lookup_fields);
1537 if (!filter) {
1539 ast_free(clean_basedn);
1540 return res;
1541 }
1542
1543 /*
1544 * Find LDAP records that match our lookup filter. If there are none, then
1545 * we don't go through the hassle of building our modifications list.
1546 */
1547
1548 do {
1549 search_result = ldap_search_ext_s(
1550 ldapConn,
1551 clean_basedn,
1552 LDAP_SCOPE_SUBTREE,
1554 NULL, 0, NULL, NULL, NULL,
1555 LDAP_NO_LIMIT,
1556 &ldap_result_msg);
1557 if (search_result != LDAP_SUCCESS && is_ldap_connect_error(search_result)) {
1558 ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
1559 tries++;
1560 if (tries < 3) {
1561 usleep(500000L * tries);
1562 if (ldapConn) {
1563 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1564 ldapConn = NULL;
1565 }
1566 if (!ldap_reconnect()) {
1567 break;
1568 }
1569 }
1570 }
1571 } while (search_result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(search_result));
1572
1573 if (search_result != LDAP_SUCCESS) {
1574 ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(search_result));
1575 ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
1576 goto early_bailout;
1577 }
1578
1579 entry_count = ldap_count_entries(ldapConn, ldap_result_msg);
1580 if (!entry_count) {
1581 /* Nothing found, nothing to update */
1582 res = 0;
1583 goto early_bailout;
1584 }
1585
1586 /* We need to NULL terminate, so we allocate one more than we need */
1587 modifications = ldap_memcalloc(update_count + 1, sizeof(LDAPMod *));
1588 if (!modifications) {
1589 ast_log(LOG_ERROR, "Memory allocation failure\n");
1590 goto early_bailout;
1591 }
1592
1593 /*
1594 * Create the modification array with the parameter/value pairs we were given,
1595 * if there are several parameters with the same name, we collect them into
1596 * one parameter/value pair and delimit them with a semicolon
1597 */
1598 for (field = update_fields, update_index = 0; field; field = field->next) {
1599 LDAPMod *mod;
1600
1601 const char *ldap_attribute_name = convert_attribute_name_to_ldap(
1602 table_config,
1603 field->name);
1604
1605 /* See if we already have it */
1606 mod = ldap_mod_find(modifications, ldap_attribute_name);
1607 if (mod) {
1608 mod = ldap_mod_append(mod, field->value);
1609 if (!mod) {
1610 goto late_bailout;
1611 }
1612 } else {
1613 mod = ldap_mod_create(ldap_attribute_name, field->value);
1614 if (!mod) {
1615 goto late_bailout;
1616 }
1617 modifications[update_index++] = mod;
1618 }
1619 }
1620
1621 /* Ready to update */
1622 ast_debug(3, "Modifying %zu matched entries\n", entry_count);
1623 if (DEBUG_ATLEAST(3)) {
1624 size_t i;
1625 for (i = 0; modifications[i]; i++) {
1626 if (modifications[i]->mod_op != LDAP_MOD_DELETE) {
1627 ast_log(LOG_DEBUG, "%s => %s\n", modifications[i]->mod_type,
1628 modifications[i]->mod_values[0]);
1629 } else {
1630 ast_log(LOG_DEBUG, "deleting %s\n", modifications[i]->mod_type);
1631 }
1632 }
1633 }
1634
1635 for (ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
1636 ldap_entry;
1637 ldap_entry = ldap_next_entry(ldapConn, ldap_entry)) {
1638 int error;
1639 LDAPMod **massaged, **working;
1640
1641 char *dn = ldap_get_dn(ldapConn, ldap_entry);
1642 if (!dn) {
1643 ast_log(LOG_ERROR, "Memory allocation failure\n");
1644 goto late_bailout;
1645 }
1646
1647 working = modifications;
1648
1649 massaged = massage_mods_for_entry(ldap_entry, modifications);
1650 if (massaged) {
1651 /* Did we massage everything out of the list? */
1652 if (!massaged[0]) {
1653 ast_debug(3, "Nothing left to modify - skipping\n");
1654 ldap_mods_free(massaged, 1);
1655 ldap_memfree(dn);
1656 continue;
1657 }
1658 working = massaged;
1659 }
1660
1661 if ((error = ldap_modify_ext_s(ldapConn, dn, working, NULL, NULL)) != LDAP_SUCCESS) {
1662 ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
1663 }
1664
1665 if (massaged) {
1666 ldap_mods_free(massaged, 1);
1667 }
1668
1669 ldap_memfree(dn);
1670 }
1671
1672 res = entry_count;
1673
1674late_bailout:
1675 ldap_mods_free(modifications, 1);
1676
1677early_bailout:
1678 ldap_msgfree(ldap_result_msg);
1680 ast_free(clean_basedn);
1682
1683 return res;
1684}
static LDAPMod * ldap_mod_find(LDAPMod **modifications, const char *lookup)
static LDAPMod ** massage_mods_for_entry(LDAPMessage *entry, LDAPMod **mods)
static size_t variables_count(const struct ast_variable *vars)
static LDAPMod * ldap_mod_append(LDAPMod *src, const char *new_value)
static LDAPMod * ldap_mod_create(const char *attribute, const char *new_value)
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_debug, ast_free, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), cleaned_basedn(), convert_attribute_name_to_ldap(), create_lookup_filter(), DEBUG_ATLEAST, error(), filter(), is_ldap_connect_error(), ldap_lock, ldap_mod_append(), ldap_mod_create(), ldap_mod_find(), ldap_reconnect(), ldapConn, LOG_DEBUG, LOG_ERROR, LOG_WARNING, massage_mods_for_entry(), ast_variable::name, ast_variable::next, NULL, table_config_for_table_name(), ast_variable::value, and variables_count().

Referenced by update_ldap().

◆ update_ldap()

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

1687{
1688 int res;
1689 struct ast_variable *lookup_fields = ast_variable_new(attribute, lookup, "");
1690 res = update2_ldap(basedn, table_name, lookup_fields, fields);
1691 ast_variables_destroy(lookup_fields);
1692 return res;
1693}
static int update2_ldap(const char *basedn, const char *table_name, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)

References ast_variable_new, ast_variables_destroy(), and update2_ldap().

◆ variable_named()

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

Find variable by name.

Definition at line 153 of file res_config_ldap.c.

154{
155 for (; var; var = var->next) {
156 if (!strcasecmp(name, var->name))
157 break;
158 }
159
160 return var;
161}

References name, and var.

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

◆ variables_count()

static size_t variables_count ( const struct ast_variable vars)
static

Definition at line 1483 of file res_config_ldap.c.

1484{
1485 const struct ast_variable *var;
1486 size_t count = 0;
1487 for (var = vars; var; var = var->next) {
1488 count++;
1489 }
1490 return count;
1491}

References var.

Referenced by update2_ldap().

Variable Documentation

◆ __mod_info

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, .requires = "extconfig", }
static

Module Information.

Definition at line 2007 of file res_config_ldap.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2007 of file res_config_ldap.c.

◆ base_distinguished_name

char base_distinguished_name[512]
static

Definition at line 77 of file res_config_ldap.c.

Referenced by parse_config(), and realtime_ldap_status().

◆ base_table_config

struct ldap_table_config* base_table_config
static

◆ connect_time

time_t connect_time
static

Definition at line 79 of file res_config_ldap.c.

Referenced by ldap_reconnect(), and realtime_ldap_status().

◆ ldap_cli

struct ast_cli_entry ldap_cli[]
static
Initial value:
= {
{ .handler = realtime_ldap_status , .summary = "Shows connection information for the LDAP RealTime driver" ,},
}
static char * realtime_ldap_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Realtime Status.

Definition at line 110 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

◆ ldap_engine

struct ast_config_engine ldap_engine
static

Definition at line 1695 of file res_config_ldap.c.

Referenced by load_module(), and unload_module().

◆ ldap_lock

ast_mutex_t ldap_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

◆ ldapConn

LDAP* ldapConn
static

◆ pass

char pass[512]
static

◆ static_table_config

struct ldap_table_config* static_table_config
static

◆ table_configs

struct table_configs table_configs = { .first = NULL, .last = NULL, }
static

◆ url

char url[512]
static

◆ user

char user[512]
static

◆ version

int version
static

Definition at line 78 of file res_config_ldap.c.

Referenced by ldap_reconnect(), and parse_config().