Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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 
758  name = convert_attribute_name_to_ldap(table_config, name);
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:734
#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:1117
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:2834
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:3178
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
#define LOG_ERROR
#define LOG_WARNING
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 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 * 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:661

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 
777  filter = ast_str_create(80);
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:640
Support for dynamic strings.
Definition: strings.h:604

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:614
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:188
static ast_mutex_t ldap_lock
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 int ldap_reconnect(void)
static int is_ldap_connect_error(int err)
Check if we have a connection error.

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:3056
#define ast_verb(level,...)
#define ast_mutex_lock(a)
Definition: lock.h:187
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 LDAPMod * ldap_mod_duplicate(const LDAPMod *src)
static int ldap_entry_has_attribute(LDAPMessage *entry, const char *lookup)

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 
1825  config = ast_config_load(RES_CONFIG_LDAP_CONF, config_flags);
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:3327
#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:768
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 struct ldap_table_config * table_config_for_table_name(const char *table_name)
Find a table_config.
static struct ldap_table_config * table_config_new(const char *table_name)
Create a new table_config.
static void table_configs_free(void)
Free 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:406
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 {
988  RAII_VAR(struct ast_variable *, fields, NULL, ast_variables_destroy);
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:936

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 
954  ast_free(filter);
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_variable * ldap_loadentry(struct ldap_table_config *table_config, const char *dn)
Get LDAP entry by dn and return attributes as variables.
static struct ast_str * create_lookup_filter(struct ldap_table_config *config, const struct ast_variable *fields)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739

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 int semicolon_count_var(struct ast_variable *var)
Count semicolons in variables.
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_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:3055
#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

◆ 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) {
1066  struct ast_category *cat = ast_category_new_anonymous();
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;
1077  ast_variable_append(cat, var);
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:1436
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3275
#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 
231  while ((c = AST_LIST_REMOVE_HEAD(&table_configs, entry))) {
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:3072

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 
1674 late_bailout:
1675  ldap_mods_free(modifications, 1);
1676 
1677 early_bailout:
1678  ldap_msgfree(ldap_result_msg);
1679  ast_free(filter);
1680  ast_free(clean_basedn);
1682 
1683  return res;
1684 }
static LDAPMod ** massage_mods_for_entry(LDAPMessage *entry, LDAPMod **mods)
static LDAPMod * ldap_mod_create(const char *attribute, const char *new_value)
static size_t variables_count(const struct ast_variable *vars)
static LDAPMod * ldap_mod_find(LDAPMod **modifications, const char *lookup)
static LDAPMod * ldap_mod_append(LDAPMod *src, 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().

◆ 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)

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

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

◆ 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 108 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 1686 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().