Asterisk - The Open Source Telephony Project GIT-master-5467495
Loading...
Searching...
No Matches
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.
 
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.
 
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.
 
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 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.
 
static int ldap_entry_has_attribute (LDAPMessage *entry, const char *lookup)
 
static void ldap_filter_escape_value (const char *value, struct ast_str **escaped)
 
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 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
 
static int load_module (void)
 Load the module.
 
static LDAPMod ** massage_mods_for_entry (LDAPMessage *entry, LDAPMod **mods)
 
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)
 Reload Module.
 
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)
 Count semicolons in variables.
 
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.
 
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 = ASTERISK_GPL_KEY , .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.
 
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 = AST_MUTEX_INIT_VALUE
 
static LDAP * ldapConn
 
static char pass [512]
 
static struct ldap_table_configstatic_table_config
 
static struct table_configs table_configs = AST_LIST_HEAD_NOLOCK_INIT_VALUE
 
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 2056 of file res_config_ldap.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

775{
776 char *new_name = NULL;
777 char *new_value = NULL;
778 const char *like_pos = strstr(name, " LIKE");
779 struct ast_str *escaped_value;
780
781 ast_debug(2, "name='%s' value='%s'\n", name, value);
782
783 escaped_value = ast_str_create(256);
784 if (!escaped_value) {
785 return;
786 }
787
788 if (like_pos) {
789 int len = like_pos - name;
790
791 name = new_name = ast_strdupa(name);
792 new_name[len] = '\0';
793 value = new_value = ast_strdupa(value);
794 replace_string_in_string(new_value, "\\_", "_");
795 replace_string_in_string(new_value, "%", "*");
797 /* Note: The LIKE path preserves original wildcard behavior.
798 * A more comprehensive escaping of the LIKE path is left
799 * to the maintainers familiar with the query semantics.
800 */
801 ast_str_append(filter, 0, "(%s=%s)", name, value);
802 } else {
804 ldap_filter_escape_value(value, &escaped_value);
805 ast_str_append(filter, 0, "(%s=%s)", name,
806 ast_str_buffer(escaped_value));
807 }
808
809 ast_free(escaped_value);
810}
#define ast_free(a)
Definition astmm.h:180
#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)
#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 void ldap_filter_escape_value(const char *value, struct ast_str **escaped)
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
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
Support for dynamic strings.
Definition strings.h:623
int value
Definition syslog.c:37

References ast_debug, ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, ast_strdupa, convert_attribute_name_to_ldap(), filter(), ldap_filter_escape_value(), 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 2056 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 1148 of file res_config_ldap.c.

1149{
1150 const struct category_and_metric *as = a;
1151 const struct category_and_metric *bs = b;
1152
1153 if (as->metric < bs->metric) {
1154 return -1;
1155 } else if (as->metric > bs->metric) {
1156 return 1;
1157 } else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
1158 return strcmp(as->name, bs->name);
1159 }
1160 /* if the metric and the category name is the same, we check the variable metric */
1161 if (as->var_metric < bs->var_metric) {
1162 return -1;
1163 } else if (as->var_metric > bs->var_metric) {
1164 return 1;
1165 }
1166
1167 return 0;
1168}
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 1842 of file res_config_ldap.c.

1843{
1844 int i;
1845 static const char * const config[] = {
1846 "basedn", "host", "pass", "port", "protocol", "url", "user", "version", NULL
1847 };
1848
1849 for (i = 0; config[i]; i++) {
1850 if (!strcasecmp(key, config[i])) {
1851 return 0;
1852 }
1853 }
1854 return 1;
1855}
static const char config[]

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

1179{
1180 unsigned int vars_count = 0;
1181 struct ast_variable **vars;
1182 int i = 0;
1183 struct ast_variable *new_v = NULL;
1184 struct ast_category *cur_cat = NULL;
1185 const char *last_category = NULL;
1186 int last_category_metric = 0;
1188 struct ast_variable **p;
1189
1190 if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
1191 ast_log(LOG_ERROR, "Missing configuration file: %s. Can't configure myself.\n", RES_CONFIG_LDAP_CONF);
1192 return NULL;
1193 }
1194
1195 vars = realtime_ldap_base(&vars_count, basedn, table_name, "filename", file, "commented", "FALSE", NULL);
1196
1197 if (!vars) {
1198 ast_log(LOG_WARNING, "Could not find config '%s' in directory.\n", file);
1199 return NULL;
1200 }
1201
1202 /*! \note Since the items come back in random order, they need to be sorted
1203 * first, and since the data could easily exceed stack size, this is
1204 * allocated from the heap.
1205 */
1206 if (!(categories = ast_calloc(vars_count, sizeof(*categories)))) {
1207 return NULL;
1208 }
1209
1210 for (vars_count = 0, p = vars; *p; p++) {
1211 struct ast_variable *category = variable_named(*p, "category");
1212 struct ast_variable *cat_metric = variable_named(*p, "cat_metric");
1213 struct ast_variable *var_name = variable_named(*p, "variable_name");
1214 struct ast_variable *var_val = variable_named(*p, "variable_value");
1215 struct ast_variable *var_metric = variable_named(*p, "var_metric");
1216 struct ast_variable *dn = variable_named(*p, "dn");
1217
1218 if (!category) {
1219 ast_log(LOG_ERROR, "No category name in entry '%s' for file '%s'.\n",
1220 (dn ? dn->value : "?"), file);
1221 } else if (!cat_metric) {
1222 ast_log(LOG_ERROR, "No category metric in entry '%s'(category: %s) for file '%s'.\n",
1223 (dn ? dn->value : "?"), category->value, file);
1224 } else if (!var_metric) {
1225 ast_log(LOG_ERROR, "No variable metric in entry '%s'(category: %s) for file '%s'.\n",
1226 (dn ? dn->value : "?"), category->value, file);
1227 } else if (!var_name) {
1228 ast_log(LOG_ERROR, "No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
1229 (dn ? dn->value : "?"), category->value,
1230 cat_metric->value, file);
1231 } else if (!var_val) {
1232 ast_log(LOG_ERROR, "No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
1233 (dn ? dn->value : "?"), category->value,
1234 cat_metric->value, var_name->value, file);
1235 } else {
1236 categories[vars_count].name = category->value;
1237 categories[vars_count].metric = atoi(cat_metric->value);
1238 categories[vars_count].variable_name = var_name->value;
1239 categories[vars_count].variable_value = var_val->value;
1240 categories[vars_count].var_metric = atoi(var_metric->value);
1241 vars_count++;
1242 }
1243
1244 ast_debug(3, "category: %s\n", category->value);
1245 ast_debug(3, "var_name: %s\n", var_name->value);
1246 ast_debug(3, "var_val: %s\n", var_val->value);
1247 ast_debug(3, "cat_metric: %s\n", cat_metric->value);
1248
1249 }
1250
1251 qsort(categories, vars_count, sizeof(*categories), compare_categories);
1252
1253 for (i = 0; i < vars_count; i++) {
1254 if (!strcmp(categories[i].variable_name, "#include")) {
1255 struct ast_flags flags = { 0 };
1256 if (!ast_config_internal_load(categories[i].variable_value, cfg, flags, "", who_asked)) {
1257 break;
1258 }
1259 continue;
1260 }
1261
1262 if (!last_category || strcmp(last_category, categories[i].name) ||
1263 last_category_metric != categories[i].metric) {
1264
1266 if (!cur_cat) {
1267 break;
1268 }
1269 last_category = categories[i].name;
1270 last_category_metric = categories[i].metric;
1271 ast_category_append(cfg, cur_cat);
1272 }
1273
1274 if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name))) {
1275 break;
1276 }
1277
1278 ast_variable_append(cur_cat, new_v);
1279 }
1280
1281 ast_free(vars);
1283
1284 return cfg;
1285}
#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:2831
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition extconf.c:1175
#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)
#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:220
unsigned int flags
Definition utils.h:221
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(), ast_variable::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:706

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

822{
823 struct ast_str *filter;
824 const struct ast_variable *field;
825
827 if (!filter) {
828 return NULL;
829 }
830
831 /*
832 * Create the filter with the table additional filter and the
833 * parameter/value pairs we were given
834 */
835 ast_str_append(&filter, 0, "(&");
836 if (config && config->additional_filter) {
837 ast_str_append(&filter, 0, "%s", config->additional_filter);
838 }
843 }
844 /* Append the lookup fields */
845 for (field = fields; field; field = field->next) {
847 }
848 ast_str_append(&filter, 0, ")");
849
850 return filter;
851}
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.

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

1449{
1450 BerElement *ber = NULL;
1451 char *attribute;
1452
1453 attribute = ldap_first_attribute(ldapConn, entry, &ber);
1454 while (attribute) {
1455 if (!strcasecmp(attribute, lookup)) {
1456 ldap_memfree(attribute);
1457 ber_free(ber, 0);
1458 return 1;
1459 }
1460 ldap_memfree(attribute);
1461 attribute = ldap_next_attribute(ldapConn, entry, ber);
1462 }
1463 ber_free(ber, 0);
1464 return 0;
1465}
static LDAP * ldapConn

References ldapConn, and NULL.

Referenced by massage_mods_for_entry().

◆ ldap_filter_escape_value()

static void ldap_filter_escape_value ( const char *  value,
struct ast_str **  escaped 
)
static

Definition at line 746 of file res_config_ldap.c.

747{
748 ast_str_reset(*escaped);
749 for (; *value; value++) {
750 switch (*value) {
751 case '*':
752 ast_str_append(escaped, 0, "\\2a");
753 break;
754 case '(':
755 ast_str_append(escaped, 0, "\\28");
756 break;
757 case ')':
758 ast_str_append(escaped, 0, "\\29");
759 break;
760 case '\\':
761 ast_str_append(escaped, 0, "\\5c");
762 break;
763 default:
764 ast_str_append(escaped, 0, "%c", *value);
765 break;
766 }
767 }
768}
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition strings.h:693

References ast_str_append(), ast_str_reset(), and value.

Referenced by append_var_and_value_to_filter().

◆ 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:1260
#define LOG_NOTICE
#define ast_mutex_unlock(a)
Definition lock.h:197
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 1346 of file res_config_ldap.c.

1347{
1348 char *new_buffer;
1349
1350 if (src->mod_op != LDAP_MOD_REPLACE) {
1351 return src;
1352 }
1353
1354 new_buffer = ldap_memrealloc(
1355 src->mod_values[0],
1356 strlen(src->mod_values[0]) + strlen(new_value) + sizeof(";"));
1357
1358 if (!new_buffer) {
1359 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1360 return NULL;
1361 }
1362
1363 strcat(new_buffer, ";");
1364 strcat(new_buffer, new_value);
1365
1366 src->mod_values[0] = new_buffer;
1367
1368 return src;
1369}

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

1297{
1298 LDAPMod *mod;
1299 char *type;
1300
1301 mod = ldap_memcalloc(1, sizeof(LDAPMod));
1302 type = ldap_strdup(attribute);
1303
1304 if (!(mod && type)) {
1305 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1306 ldap_memfree(type);
1307 ldap_memfree(mod);
1308 return NULL;
1309 }
1310
1311 mod->mod_type = type;
1312
1313 if (strlen(new_value)) {
1314 char **values, *value;
1315 values = ldap_memcalloc(2, sizeof(char *));
1316 value = ldap_strdup(new_value);
1317
1318 if (!(values && value)) {
1319 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1320 ldap_memfree(value);
1321 ldap_memfree(values);
1322 ldap_memfree(type);
1323 ldap_memfree(mod);
1324 return NULL;
1325 }
1326
1327 mod->mod_op = LDAP_MOD_REPLACE;
1328 mod->mod_values = values;
1329 mod->mod_values[0] = value;
1330 } else {
1331 mod->mod_op = LDAP_MOD_DELETE;
1332 }
1333
1334 return mod;
1335}
static const char type[]

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

1380{
1381 LDAPMod *mod;
1382 char *type, **values = NULL;
1383
1384 mod = ldap_memcalloc(1, sizeof(LDAPMod));
1385 type = ldap_strdup(src->mod_type);
1386
1387 if (!(mod && type)) {
1388 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1389 ldap_memfree(type);
1390 ldap_memfree(mod);
1391 return NULL;
1392 }
1393
1394 if (src->mod_op == LDAP_MOD_REPLACE) {
1395 char *value;
1396
1397 values = ldap_memcalloc(2, sizeof(char *));
1398 value = ldap_strdup(src->mod_values[0]);
1399
1400 if (!(values && value)) {
1401 ast_log(LOG_ERROR, "Memory allocation failure creating LDAP modification\n");
1402 ldap_memfree(value);
1403 ldap_memfree(values);
1404 ldap_memfree(type);
1405 ldap_memfree(mod);
1406 return NULL;
1407 }
1408
1409 values[0] = value;
1410 }
1411
1412 mod->mod_op = src->mod_op;
1413 mod->mod_type = type;
1414 mod->mod_values = values;
1415 return mod;
1416}

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

1428{
1429 size_t i;
1430 for (i = 0; modifications[i]; i++) {
1431 if (modifications[i]->mod_op == LDAP_MOD_REPLACE &&
1432 !strcasecmp(modifications[i]->mod_type, lookup)) {
1433 return modifications[i];
1434 }
1435 }
1436 return NULL;
1437}

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

1962{
1963 int bind_result = 0;
1964 struct berval cred;
1965
1966 if (ldapConn) {
1967 ast_debug(2, "Everything seems fine.\n");
1968 return 1;
1969 }
1970
1971 if (ast_strlen_zero(url)) {
1972 ast_log(LOG_ERROR, "Not enough parameters to connect to ldap directory\n");
1973 return 0;
1974 }
1975
1976 if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
1977 ast_log(LOG_ERROR, "Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
1978 return 0;
1979 }
1980
1981 if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
1982 ast_log(LOG_WARNING, "Unable to set LDAP protocol version to %d, falling back to default.\n", version);
1983 }
1984
1985 if (!ast_strlen_zero(user)) {
1986 ast_debug(2, "bind to '%s' as user '%s'\n", url, user);
1987 cred.bv_val = (char *) pass;
1988 cred.bv_len = strlen(pass);
1989 bind_result = ldap_sasl_bind_s(ldapConn, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
1990 } else {
1991 ast_debug(2, "bind %s anonymously\n", url);
1992 cred.bv_val = NULL;
1993 cred.bv_len = 0;
1994 bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
1995 }
1996 if (bind_result == LDAP_SUCCESS) {
1997 ast_debug(2, "Successfully connected to directory.\n");
1998 connect_time = time(NULL);
1999 return 1;
2000 } else {
2001 ast_log(LOG_WARNING, "bind failed: %s\n", ldap_err2string(bind_result));
2002 ldap_unbind_ext_s(ldapConn, NULL, NULL);
2003 ldapConn = NULL;
2004 return 0;
2005 }
2006}
static char pass[512]
static char url[512]
static int version
static time_t connect_time
structure to hold users read from phoneprov_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, ast_variable::next, 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 1766 of file res_config_ldap.c.

1767{
1768 if (parse_config() < 0) {
1769 ast_log(LOG_ERROR, "Cannot load LDAP RealTime driver.\n");
1770 return 0;
1771 }
1772
1774
1775 if (!ldap_reconnect()) {
1776 ast_log(LOG_WARNING, "Couldn't establish connection to LDAP directory. Check debug.\n");
1777 }
1778
1780 ast_verb(1, "LDAP RealTime driver loaded.\n");
1782
1784
1785 return 0;
1786}
#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.
#define ast_verb(level,...)
#define ast_mutex_lock(a)
Definition lock.h:196
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 1483 of file res_config_ldap.c.

1484{
1485 size_t k, i, remove_count;
1486 LDAPMod **copies;
1487
1488 for (i = remove_count = 0; mods[i]; i++) {
1489 if (mods[i]->mod_op == LDAP_MOD_DELETE
1490 && !ldap_entry_has_attribute(entry, mods[i]->mod_type)) {
1491 remove_count++;
1492 }
1493 }
1494
1495 if (!remove_count) {
1496 return NULL;
1497 }
1498
1499 copies = ldap_memcalloc(i - remove_count + 1, sizeof(LDAPMod *));
1500 if (!copies) {
1501 ast_log(LOG_ERROR, "Memory allocation failure massaging LDAP modification\n");
1502 return NULL;
1503 }
1504
1505 for (i = k = 0; mods[i]; i++) {
1506 if (mods[i]->mod_op != LDAP_MOD_DELETE
1507 || ldap_entry_has_attribute(entry, mods[i]->mod_type)) {
1508 copies[k] = ldap_mod_duplicate(mods[i]);
1509 if (!copies[k]) {
1510 ast_log(LOG_ERROR, "Memory allocation failure massaging LDAP modification\n");
1511 ldap_mods_free(copies, 1);
1512 return NULL;
1513 }
1514 k++;
1515 } else {
1516 ast_debug(3, "Skipping %s deletion because it doesn't exist\n",
1517 mods[i]->mod_type);
1518 }
1519 }
1520
1521 return copies;
1522}
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 1859 of file res_config_ldap.c.

1860{
1861 struct ast_config *config;
1862 struct ast_flags config_flags = {0};
1863 const char *s, *host;
1864 int port;
1865 char *category_name = NULL;
1866
1867 /* Make sure that global variables are reset */
1868 url[0] = '\0';
1869 user[0] = '\0';
1870 pass[0] = '\0';
1871 base_distinguished_name[0] = '\0';
1872 version = 3;
1873
1876 ast_log(LOG_ERROR, "Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
1877 return -1;
1878 }
1879
1880 if (!(s = ast_variable_retrieve(config, "_general", "user"))) {
1881 ast_log(LOG_NOTICE, "No directory user found, anonymous binding as default.\n");
1882 user[0] = '\0';
1883 } else {
1884 ast_copy_string(user, s, sizeof(user));
1885 }
1886
1887 if (!ast_strlen_zero(user)) {
1888 if (!(s = ast_variable_retrieve(config, "_general", "pass"))) {
1889 ast_log(LOG_WARNING, "No directory password found, using 'asterisk' as default.\n");
1890 ast_copy_string(pass, "asterisk", sizeof(pass));
1891 } else {
1892 ast_copy_string(pass, s, sizeof(pass));
1893 }
1894 }
1895
1896 /* URL is preferred, use host and port if not found */
1897 if ((s = ast_variable_retrieve(config, "_general", "url"))) {
1898 ast_copy_string(url, s, sizeof(url));
1899 } else if ((host = ast_variable_retrieve(config, "_general", "host"))) {
1900 if (!(s = ast_variable_retrieve(config, "_general", "port")) || sscanf(s, "%5d", &port) != 1 || port > 65535) {
1901 ast_log(LOG_NOTICE, "No directory port found, using 389 as default.\n");
1902 port = 389;
1903 }
1904
1905 snprintf(url, sizeof(url), "ldap://%s:%d", host, port);
1906 } else {
1907 ast_log(LOG_ERROR, "No directory URL or host found.\n");
1909 return -1;
1910 }
1911
1912 if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
1913 ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
1915 } else
1917
1918 if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
1919 ast_log(LOG_NOTICE, "No explicit LDAP version found, using 3 as default.\n");
1920 } else if (sscanf(s, "%30d", &version) != 1 || version < 1 || version > 6) {
1921 ast_log(LOG_WARNING, "Invalid LDAP version '%s', using 3 as default.\n", s);
1922 version = 3;
1923 }
1924
1926
1927 while ((category_name = ast_category_browse(config, category_name))) {
1928 int is_general = (strcasecmp(category_name, "_general") == 0);
1929 int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
1930 struct ast_variable *var = ast_variable_browse(config, category_name);
1931
1932 if (var) {
1933 struct ldap_table_config *table_config =
1934 table_config_for_table_name(category_name);
1935 if (!table_config) {
1936 table_config = table_config_new(category_name);
1937 AST_LIST_INSERT_HEAD(&table_configs, table_config, entry);
1938 if (is_general)
1939 base_table_config = table_config;
1940 if (is_config)
1941 static_table_config = table_config;
1942 }
1943 for (; var; var = var->next) {
1944 if (!strcasecmp(var->name, "additionalFilter")) {
1945 table_config->additional_filter = ast_strdup(var->value);
1946 } else {
1947 if (!is_general || config_can_be_inherited(var->name)) {
1948 ldap_table_config_add_attribute(table_config, var->name, var->value);
1949 }
1950 }
1951 }
1952 }
1953 }
1954
1956
1957 return 1;
1958}
#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:3324
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
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
struct ldap_table_config::@460 entry
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::entry, 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(), load_module(), load_module(), load_module(), load_module(), reload(), reload(), reload(), reload(), and reload().

◆ realtime_arguments_to_fields()

static struct ast_variable * realtime_arguments_to_fields ( va_list  ap)
static

Definition at line 1011 of file res_config_ldap.c.

1012{
1013 struct ast_variable *fields = NULL;
1014 const char *newparam, *newval;
1015
1016 while ((newparam = va_arg(ap, const char *))) {
1017 struct ast_variable *field;
1018
1019 newval = va_arg(ap, const char *);
1020 if (!(field = ast_variable_new(newparam, newval, ""))) {
1021 ast_variables_destroy(fields);
1022 return NULL;
1023 }
1024
1025 field->next = fields;
1026 fields = field;
1027 }
1028
1029 return fields;
1030}

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

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

1056{
1057 struct ast_variable **vars = realtime_ldap_base_ap(NULL, basedn, table_name, fields);
1058 struct ast_variable *var = NULL;
1059
1060 if (vars) {
1061 struct ast_variable *last_var = NULL;
1062 struct ast_variable **p = vars;
1063
1064 /* Chain the vars array of lists into one list to return. */
1065 while (*p) {
1066 if (last_var) {
1067 while (last_var->next) {
1068 last_var = last_var->next;
1069 }
1070 last_var->next = *p;
1071 } else {
1072 var = *p;
1073 last_var = var;
1074 }
1075 p++;
1076 }
1077 ast_free(vars);
1078 }
1079 return var;
1080}
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 1034 of file res_config_ldap.c.

1036{
1037 RAII_VAR(struct ast_variable *, fields, NULL, ast_variables_destroy);
1038 struct ast_variable **vars = NULL;
1039 va_list ap;
1040
1041 va_start(ap, table_name);
1042 fields = realtime_arguments_to_fields(ap);
1043 va_end(ap);
1044
1045 vars = realtime_ldap_base_ap(entries_count_ptr, basedn, table_name, fields);
1046
1047 return vars;
1048}
#define realtime_arguments_to_fields(ap, result)
#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:981

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

863{
864 struct ast_variable **vars = NULL;
865 const struct ast_variable *field = fields;
866 struct ldap_table_config *table_config = NULL;
867 char *clean_basedn = cleaned_basedn(NULL, basedn);
868 struct ast_str *filter = NULL;
869 int tries = 0;
870 int result = 0;
871 LDAPMessage *ldap_result_msg = NULL;
872
873 if (!table_name) {
874 ast_log(LOG_ERROR, "No table_name specified.\n");
875 ast_free(clean_basedn);
876 return NULL;
877 }
878
879 if (!field) {
880 ast_log(LOG_ERROR, "Realtime retrieval requires at least 1 parameter"
881 " and 1 value to search on.\n");
882 ast_free(clean_basedn);
883 return NULL;
884 }
885
887
888 /* We now have our complete statement; Lets connect to the server and execute it. */
889 if (!ldap_reconnect()) {
891 ast_free(clean_basedn);
892 return NULL;
893 }
894
895 table_config = table_config_for_table_name(table_name);
896 if (!table_config) {
897 ast_log(LOG_WARNING, "No table named '%s'.\n", table_name);
899 ast_free(clean_basedn);
900 return NULL;
901 }
902
903 filter = create_lookup_filter(table_config, fields);
904 if (!filter) {
906 ast_free(clean_basedn);
907 return NULL;
908 }
909
910 do {
911 /* freeing ldap_result further down */
912 result = ldap_search_ext_s(ldapConn, clean_basedn,
913 LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
914 &ldap_result_msg);
915 if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) {
916 ast_debug(1, "Failed to query directory. Try %d/10\n", tries + 1);
917 if (++tries < 10) {
918 usleep(1);
919 if (ldapConn) {
920 ldap_unbind_ext_s(ldapConn, NULL, NULL);
921 ldapConn = NULL;
922 }
923 if (!ldap_reconnect()) {
924 break;
925 }
926 }
927 }
928 } while (result != LDAP_SUCCESS && tries < 10 && is_ldap_connect_error(result));
929
930 if (result != LDAP_SUCCESS) {
931 ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
932 ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
933 } else {
934 /* this is where we create the variables from the search result
935 * freeing this \a vars outside this function */
936 if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
937 /* is this a static var or some other? they are handled different for delimited values */
938 vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr);
939 } else {
940 ast_debug(1, "Could not find any entry matching %s in base dn %s.\n", ast_str_buffer(filter), clean_basedn);
941 }
942
943 ldap_msgfree(ldap_result_msg);
944
945 /*! \todo get the default variables from the accountBaseDN, not implemented with delimited values
946 */
947 if (vars) {
948 struct ast_variable **p = vars;
949 while (*p) {
950 struct ast_variable *append_var = NULL;
951 struct ast_variable *tmp = *p;
952 while (tmp) {
953 if (strcasecmp(tmp->name, "accountBaseDN") == 0) {
954 /* Get the variable to compare with for the defaults */
955 struct ast_variable *base_var = ldap_loadentry(table_config, tmp->value);
956
957 while (base_var) {
958 struct ast_variable *next = base_var->next;
959 struct ast_variable *test_var = *p;
960 int base_var_found = 0;
961
962 /* run throught the default values and fill it inn if it is missing */
963 while (test_var) {
964 if (strcasecmp(test_var->name, base_var->name) == 0) {
965 base_var_found = 1;
966 break;
967 } else {
968 test_var = test_var->next;
969 }
970 }
971 if (base_var_found) {
972 base_var->next = NULL;
973 ast_variables_destroy(base_var);
974 base_var = next;
975 } else {
976 /*!
977 * \todo XXX The interactions with base_var and append_var may
978 * cause a memory leak of base_var nodes. Also the append_var
979 * list and base_var list may get cross linked.
980 */
981 if (append_var) {
982 base_var->next = append_var;
983 } else {
984 base_var->next = NULL;
985 }
986 append_var = base_var;
987 base_var = next;
988 }
989 }
990 }
991 if (!tmp->next && append_var) {
992 tmp->next = append_var;
993 tmp = NULL;
994 } else {
995 tmp = tmp->next;
996 }
997 }
998 p++;
999 }
1000 }
1001 }
1002
1004 ast_free(clean_basedn);
1005
1007
1008 return vars;
1009}
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.

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 ast_variable::value.

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

2012{
2013 struct ast_str *buf;
2014 int ctimesec = time(NULL) - connect_time;
2015
2016 switch (cmd) {
2017 case CLI_INIT:
2018 e->command = "realtime show ldap status";
2019 e->usage =
2020 "Usage: realtime show ldap status\n"
2021 " Shows connection information for the LDAP RealTime driver\n";
2022 return NULL;
2023 case CLI_GENERATE:
2024 return NULL;
2025 }
2026
2027 if (!ldapConn)
2028 return CLI_FAILURE;
2029
2030 buf = ast_str_create(512);
2031 if (!ast_strlen_zero(url)) {
2032 ast_str_append(&buf, 0, "Connected to '%s', baseDN %s", url, base_distinguished_name);
2033 }
2034
2035 if (!ast_strlen_zero(user)) {
2036 ast_str_append(&buf, 0, " with username %s", user);
2037 }
2038
2039 ast_str_append(&buf, 0, " for ");
2041 ast_free(buf);
2042
2043 return CLI_SUCCESS;
2044}
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:3140
#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 1089 of file res_config_ldap.c.

1091{
1092 char *op;
1093 char *initfield = NULL;
1094 struct ast_variable **vars =
1095 realtime_ldap_base_ap(NULL, basedn, table_name, fields);
1096 struct ast_config *cfg = NULL;
1097
1098 if (!fields) {
1099 ast_log(LOG_WARNING, "realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
1100 return NULL;
1101 }
1102 initfield = ast_strdupa(fields->name);
1103 if ((op = strchr(initfield, ' '))) {
1104 *op = '\0';
1105 }
1106
1107 if (vars) {
1108 cfg = ast_config_new();
1109 if (!cfg) {
1110 ast_log(LOG_ERROR, "Unable to create a config!\n");
1111 } else {
1112 struct ast_variable **p = vars;
1113
1114 while (*p) {
1116 if (!cat) {
1117 break;
1118 } else {
1119 struct ast_variable *var = *p;
1120 while (var) {
1121 struct ast_variable *next = var->next;
1122 if (initfield && !strcmp(initfield, var->name)) {
1123 ast_category_rename(cat, var->value);
1124 }
1125 var->next = NULL;
1127 var = next;
1128 }
1129 }
1130 ast_category_append(cfg, cat);
1131 p++;
1132 }
1133 }
1134 ast_free(vars);
1135 }
1136 return cfg;
1137
1138}
void ast_category_rename(struct ast_category *cat, const char *name)
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition extconf.c:3272
#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 1814 of file res_config_ldap.c.

1815{
1816 /* Aquire control before doing anything to the module itself. */
1818
1819 if (ldapConn) {
1820 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1821 ldapConn = NULL;
1822 }
1823
1824 if (parse_config() < 0) {
1825 ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
1827 return 0;
1828 }
1829
1830 if (!ldap_reconnect()) {
1831 ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
1832 }
1833
1834 ast_verb(2, "LDAP RealTime driver reloaded.\n");
1835
1836 /* Done reloading. Release lock so others can now use driver. */
1838
1839 return 0;
1840}

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.
static struct test_val c

References AST_LIST_TRAVERSE, c, ldap_table_config::entry, 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.

References ast_free, AST_LIST_REMOVE_HEAD, ast_variables_destroy(), base_table_config, c, ldap_table_config::entry, 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 1791 of file res_config_ldap.c.

1792{
1793 /* Aquire control before doing anything to the module itself. */
1795
1797
1798 if (ldapConn) {
1799 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1800 ldapConn = NULL;
1801 }
1804 ast_verb(1, "LDAP RealTime driver unloaded.\n");
1805
1806 /* Unlock so something else can destroy the lock. */
1808
1809 return 0;
1810}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.

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

1543{
1544 const struct ast_variable *field;
1545 struct ldap_table_config *table_config = NULL;
1546 char *clean_basedn = NULL;
1547 struct ast_str *filter = NULL;
1548 int search_result = 0;
1549 int res = -1;
1550 int tries = 0;
1551 size_t update_count, update_index, entry_count;
1552
1553 LDAPMessage *ldap_entry = NULL;
1554 LDAPMod **modifications;
1555 LDAPMessage *ldap_result_msg = NULL;
1556
1557 if (!table_name) {
1558 ast_log(LOG_ERROR, "No table_name specified.\n");
1559 return res;
1560 }
1561
1562 update_count = variables_count(update_fields);
1563 if (!update_count) {
1564 ast_log(LOG_WARNING, "Need at least one parameter to modify.\n");
1565 return res;
1566 }
1567
1569
1570 /* We now have our complete statement; Lets connect to the server and execute it. */
1571 if (!ldap_reconnect()) {
1573 return res;
1574 }
1575
1576 table_config = table_config_for_table_name(table_name);
1577 if (!table_config) {
1578 ast_log(LOG_ERROR, "No table named '%s'.\n", table_name);
1580 return res;
1581 }
1582
1583 clean_basedn = cleaned_basedn(NULL, basedn);
1584
1585 filter = create_lookup_filter(table_config, lookup_fields);
1586 if (!filter) {
1588 ast_free(clean_basedn);
1589 return res;
1590 }
1591
1592 /*
1593 * Find LDAP records that match our lookup filter. If there are none, then
1594 * we don't go through the hassle of building our modifications list.
1595 */
1596
1597 do {
1598 search_result = ldap_search_ext_s(
1599 ldapConn,
1600 clean_basedn,
1601 LDAP_SCOPE_SUBTREE,
1603 NULL, 0, NULL, NULL, NULL,
1604 LDAP_NO_LIMIT,
1605 &ldap_result_msg);
1606 if (search_result != LDAP_SUCCESS && is_ldap_connect_error(search_result)) {
1607 ast_log(LOG_WARNING, "Failed to query directory. Try %d/3\n", tries + 1);
1608 tries++;
1609 if (tries < 3) {
1610 usleep(500000L * tries);
1611 if (ldapConn) {
1612 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1613 ldapConn = NULL;
1614 }
1615 if (!ldap_reconnect()) {
1616 break;
1617 }
1618 }
1619 }
1620 } while (search_result != LDAP_SUCCESS && tries < 3 && is_ldap_connect_error(search_result));
1621
1622 if (search_result != LDAP_SUCCESS) {
1623 ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(search_result));
1624 ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
1625 goto early_bailout;
1626 }
1627
1628 entry_count = ldap_count_entries(ldapConn, ldap_result_msg);
1629 if (!entry_count) {
1630 /* Nothing found, nothing to update */
1631 res = 0;
1632 goto early_bailout;
1633 }
1634
1635 /* We need to NULL terminate, so we allocate one more than we need */
1636 modifications = ldap_memcalloc(update_count + 1, sizeof(LDAPMod *));
1637 if (!modifications) {
1638 ast_log(LOG_ERROR, "Memory allocation failure\n");
1639 goto early_bailout;
1640 }
1641
1642 /*
1643 * Create the modification array with the parameter/value pairs we were given,
1644 * if there are several parameters with the same name, we collect them into
1645 * one parameter/value pair and delimit them with a semicolon
1646 */
1647 for (field = update_fields, update_index = 0; field; field = field->next) {
1648 LDAPMod *mod;
1649
1650 const char *ldap_attribute_name = convert_attribute_name_to_ldap(
1651 table_config,
1652 field->name);
1653
1654 /* See if we already have it */
1655 mod = ldap_mod_find(modifications, ldap_attribute_name);
1656 if (mod) {
1657 mod = ldap_mod_append(mod, field->value);
1658 if (!mod) {
1659 goto late_bailout;
1660 }
1661 } else {
1662 mod = ldap_mod_create(ldap_attribute_name, field->value);
1663 if (!mod) {
1664 goto late_bailout;
1665 }
1666 modifications[update_index++] = mod;
1667 }
1668 }
1669
1670 /* Ready to update */
1671 ast_debug(3, "Modifying %zu matched entries\n", entry_count);
1672 if (DEBUG_ATLEAST(3)) {
1673 size_t i;
1674 for (i = 0; modifications[i]; i++) {
1675 if (modifications[i]->mod_op != LDAP_MOD_DELETE) {
1676 ast_log(LOG_DEBUG, "%s => %s\n", modifications[i]->mod_type,
1677 modifications[i]->mod_values[0]);
1678 } else {
1679 ast_log(LOG_DEBUG, "deleting %s\n", modifications[i]->mod_type);
1680 }
1681 }
1682 }
1683
1684 for (ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
1685 ldap_entry;
1686 ldap_entry = ldap_next_entry(ldapConn, ldap_entry)) {
1687 int error;
1688 LDAPMod **massaged, **working;
1689
1690 char *dn = ldap_get_dn(ldapConn, ldap_entry);
1691 if (!dn) {
1692 ast_log(LOG_ERROR, "Memory allocation failure\n");
1693 goto late_bailout;
1694 }
1695
1696 working = modifications;
1697
1698 massaged = massage_mods_for_entry(ldap_entry, modifications);
1699 if (massaged) {
1700 /* Did we massage everything out of the list? */
1701 if (!massaged[0]) {
1702 ast_debug(3, "Nothing left to modify - skipping\n");
1703 ldap_mods_free(massaged, 1);
1704 ldap_memfree(dn);
1705 continue;
1706 }
1707 working = massaged;
1708 }
1709
1710 if ((error = ldap_modify_ext_s(ldapConn, dn, working, NULL, NULL)) != LDAP_SUCCESS) {
1711 ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
1712 }
1713
1714 if (massaged) {
1715 ldap_mods_free(massaged, 1);
1716 }
1717
1718 ldap_memfree(dn);
1719 }
1720
1721 res = entry_count;
1722
1723late_bailout:
1724 ldap_mods_free(modifications, 1);
1725
1726early_bailout:
1727 ldap_msgfree(ldap_result_msg);
1729 ast_free(clean_basedn);
1731
1732 return res;
1733}
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,...)

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

1736{
1737 int res;
1738 struct ast_variable *lookup_fields = ast_variable_new(attribute, lookup, "");
1739 res = update2_ldap(basedn, table_name, lookup_fields, fields);
1740 ast_variables_destroy(lookup_fields);
1741 return res;
1742}
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 1532 of file res_config_ldap.c.

1533{
1534 const struct ast_variable *var;
1535 size_t count = 0;
1536 for (var = vars; var; var = var->next) {
1537 count++;
1538 }
1539 return count;
1540}

References ast_variable::next, and 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 = ASTERISK_GPL_KEY , .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 2056 of file res_config_ldap.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

110 {
111 AST_CLI_DEFINE(realtime_ldap_status, "Shows connection information for the LDAP RealTime driver"),
112};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

◆ ldap_engine

struct ast_config_engine ldap_engine
static

Definition at line 1744 of file res_config_ldap.c.

1744 {
1745 .name = "ldap",
1746 .load_func = config_ldap,
1747 .realtime_func = realtime_ldap,
1748 .realtime_multi_func = realtime_multi_ldap,
1749 .update_func = update_ldap,
1750 .update2_func = update2_ldap,
1751};
static struct ast_config * realtime_multi_ldap(const char *basedn, const char *table_name, const struct ast_variable *fields)
See Asterisk doc.
static struct ast_variable * realtime_ldap(const char *basedn, const char *table_name, const struct ast_variable *fields)
See Asterisk doc.
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)
See Asterisk Realtime Documentation.
static int update_ldap(const char *basedn, const char *table_name, const char *attribute, const char *lookup, const struct ast_variable *fields)

Referenced by load_module(), and unload_module().

◆ ldap_lock

ast_mutex_t ldap_lock = AST_MUTEX_INIT_VALUE
static

◆ ldapConn

LDAP* ldapConn
static

◆ pass

char pass[512]
static

◆ static_table_config

struct ldap_table_config* static_table_config
static

◆ table_configs

◆ url

char url[512]
static

◆ user

char user[512]
static

Definition at line 75 of file res_config_ldap.c.

◆ version

int version
static

Definition at line 78 of file res_config_ldap.c.

Referenced by ldap_reconnect(), and parse_config().