|
|
|
@ -21,7 +21,7 @@
|
|
|
|
|
|
|
|
|
|
/*! \file
|
|
|
|
|
*
|
|
|
|
|
* \brief ldap plugin for portable configuration engine (ARA)
|
|
|
|
|
* \brief LDAP plugin for portable configuration engine (ARA)
|
|
|
|
|
*
|
|
|
|
|
* \author Mark Spencer <markster@digium.com>
|
|
|
|
|
* \author Manuel Guesdon
|
|
|
|
@ -92,7 +92,8 @@ struct category_and_metric {
|
|
|
|
|
int var_metric; /*!< For organizing variables (particularly includes and switch statments) within a context */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*! \brief Table configuration */
|
|
|
|
|
/*! \brief Table configuration
|
|
|
|
|
*/
|
|
|
|
|
struct ldap_table_config {
|
|
|
|
|
char *table_name; /*!< table name */
|
|
|
|
|
char *additional_filter; /*!< additional filter */
|
|
|
|
@ -102,7 +103,8 @@ struct ldap_table_config {
|
|
|
|
|
/* TODO: Make proxies work */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*! \brief Should be locked before using it */
|
|
|
|
|
/*! \brief Should be locked before using it
|
|
|
|
|
*/
|
|
|
|
|
static AST_LIST_HEAD_NOLOCK_STATIC(table_configs, ldap_table_config);
|
|
|
|
|
static struct ldap_table_config *base_table_config;
|
|
|
|
|
static struct ldap_table_config *static_table_config;
|
|
|
|
@ -111,7 +113,8 @@ static struct ast_cli_entry ldap_cli[] = {
|
|
|
|
|
AST_CLI_DEFINE(realtime_ldap_status, "Shows connection information for the LDAP RealTime driver"),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*! \brief Create a new table_config */
|
|
|
|
|
/*! \brief Create a new table_config
|
|
|
|
|
*/
|
|
|
|
|
static struct ldap_table_config *table_config_new(const char *table_name)
|
|
|
|
|
{
|
|
|
|
|
struct ldap_table_config *p;
|
|
|
|
@ -129,8 +132,11 @@ static struct ldap_table_config *table_config_new(const char *table_name)
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Find a table_config - Should be locked before using it
|
|
|
|
|
* \note This function assumes ldap_lock to be locked. */
|
|
|
|
|
/*! \brief Find a table_config
|
|
|
|
|
*
|
|
|
|
|
* Should be locked before using it
|
|
|
|
|
* \note This function assumes ldap_lock to be locked.
|
|
|
|
|
*/
|
|
|
|
|
static struct ldap_table_config *table_config_for_table_name(const char *table_name)
|
|
|
|
|
{
|
|
|
|
|
struct ldap_table_config *c = NULL;
|
|
|
|
@ -143,7 +149,8 @@ static struct ldap_table_config *table_config_for_table_name(const char *table_n
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Find variable by name */
|
|
|
|
|
/*! \brief Find variable by name
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_variable *variable_named(struct ast_variable *var, const char *name)
|
|
|
|
|
{
|
|
|
|
|
for (; var; var = var->next) {
|
|
|
|
@ -154,10 +161,10 @@ static struct ast_variable *variable_named(struct ast_variable *var, const char
|
|
|
|
|
return var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief for the semicolon delimiter
|
|
|
|
|
\param somestr - pointer to a string
|
|
|
|
|
|
|
|
|
|
\return number of occurances of the delimiter(semicolon)
|
|
|
|
|
/*! \brief Count semicolons in string
|
|
|
|
|
* \param somestr - pointer to a string
|
|
|
|
|
*
|
|
|
|
|
* \return number of occurances of the delimiter(semicolon)
|
|
|
|
|
*/
|
|
|
|
|
static int semicolon_count_str(const char *somestr)
|
|
|
|
|
{
|
|
|
|
@ -171,7 +178,9 @@ static int semicolon_count_str(const char *somestr)
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* takes a linked list of \a ast_variable variables, finds the one with the name variable_value
|
|
|
|
|
/* \brief Count semicolons in variables
|
|
|
|
|
*
|
|
|
|
|
* takes a linked list of \a ast_variable variables, finds the one with the name variable_value
|
|
|
|
|
* and returns the number of semicolons in the value for that \a ast_variable
|
|
|
|
|
*/
|
|
|
|
|
static int semicolon_count_var(struct ast_variable *var)
|
|
|
|
@ -187,7 +196,10 @@ static int semicolon_count_var(struct ast_variable *var)
|
|
|
|
|
return semicolon_count_str(var_value->value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief add attribute to table config - Should be locked before using it */
|
|
|
|
|
/*! \brief add attribute to table config
|
|
|
|
|
*
|
|
|
|
|
* Should be locked before using it
|
|
|
|
|
*/
|
|
|
|
|
static void ldap_table_config_add_attribute(struct ldap_table_config *table_config,
|
|
|
|
|
const char *attribute_name, const char *attribute_value)
|
|
|
|
|
{
|
|
|
|
@ -208,7 +220,8 @@ static void ldap_table_config_add_attribute(struct ldap_table_config *table_conf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Free table_config
|
|
|
|
|
* \note assumes ldap_lock to be locked */
|
|
|
|
|
* \note assumes ldap_lock to be locked
|
|
|
|
|
*/
|
|
|
|
|
static void table_configs_free(void)
|
|
|
|
|
{
|
|
|
|
|
struct ldap_table_config *c;
|
|
|
|
@ -230,7 +243,10 @@ static void table_configs_free(void)
|
|
|
|
|
static_table_config = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Convert variable name to ldap attribute name - Should be locked before using it */
|
|
|
|
|
/*! \brief Convert variable name to ldap attribute name
|
|
|
|
|
*
|
|
|
|
|
* Should be locked before using it
|
|
|
|
|
*/
|
|
|
|
|
static const char *convert_attribute_name_to_ldap(struct ldap_table_config *table_config,
|
|
|
|
|
const char *attribute_name)
|
|
|
|
|
{
|
|
|
|
@ -256,7 +272,8 @@ static const char *convert_attribute_name_to_ldap(struct ldap_table_config *tabl
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Convert ldap attribute name to variable name
|
|
|
|
|
\note Should be locked before using it */
|
|
|
|
|
* \note Should be locked before using it
|
|
|
|
|
*/
|
|
|
|
|
static const char *convert_attribute_name_from_ldap(struct ldap_table_config *table_config,
|
|
|
|
|
const char *attribute_name)
|
|
|
|
|
{
|
|
|
|
@ -282,8 +299,8 @@ static const char *convert_attribute_name_from_ldap(struct ldap_table_config *ta
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Get variables from ldap entry attributes
|
|
|
|
|
\note Should be locked before using it
|
|
|
|
|
\return a linked list of ast_variable variables.
|
|
|
|
|
* \note Should be locked before using it
|
|
|
|
|
* \return a linked list of ast_variable variables.
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config *table_config,
|
|
|
|
|
LDAPMessage *ldap_entry)
|
|
|
|
@ -366,7 +383,7 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config
|
|
|
|
|
* The results are freed outside this function so is the \a vars array.
|
|
|
|
|
*
|
|
|
|
|
* \return \a vars - an array of ast_variable variables terminated with a null.
|
|
|
|
|
**/
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_config *table_config,
|
|
|
|
|
LDAPMessage *ldap_result_msg, unsigned int *entries_count_ptr)
|
|
|
|
|
{
|
|
|
|
@ -401,7 +418,8 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
|
|
|
|
|
* 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 \a vars array for each delimited
|
|
|
|
|
* 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.
|
|
|
|
|
* This memory must be freed outside of this function. */
|
|
|
|
|
* This memory must be freed outside of this function.
|
|
|
|
|
*/
|
|
|
|
|
vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1);
|
|
|
|
|
|
|
|
|
|
ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
|
|
|
|
@ -550,14 +568,19 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Check if we have a connection error */
|
|
|
|
|
/*! \brief Check if we have a connection error
|
|
|
|
|
*/
|
|
|
|
|
static int is_ldap_connect_error(int err)
|
|
|
|
|
{
|
|
|
|
|
return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief 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)
|
|
|
|
|
/*! \brief Get LDAP entry by dn and return attributes as variables
|
|
|
|
|
*
|
|
|
|
|
* Should be locked before using it
|
|
|
|
|
*
|
|
|
|
|
* This is used for setting the default values of an object
|
|
|
|
|
* i.e., with accountBaseDN
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_variable *ldap_loadentry(struct ldap_table_config *table_config,
|
|
|
|
|
const char *dn)
|
|
|
|
@ -633,7 +656,8 @@ static struct ast_variable *ldap_loadentry(struct ldap_table_config *table_confi
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \note caller should free returned pointer */
|
|
|
|
|
/*! \note caller should free returned pointer
|
|
|
|
|
*/
|
|
|
|
|
static char *substituted(struct ast_channel *channel, const char *string)
|
|
|
|
|
{
|
|
|
|
|
#define MAXRESULT 2048
|
|
|
|
@ -647,7 +671,8 @@ static char *substituted(struct ast_channel *channel, const char *string)
|
|
|
|
|
return ret_string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \note caller should free returned pointer */
|
|
|
|
|
/*! \note caller should free returned pointer
|
|
|
|
|
*/
|
|
|
|
|
static char *cleaned_basedn(struct ast_channel *channel, const char *basedn)
|
|
|
|
|
{
|
|
|
|
|
char *cbasedn = NULL;
|
|
|
|
@ -675,7 +700,8 @@ static char *cleaned_basedn(struct ast_channel *channel, const char *basedn)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Replace \<search\> by \<by\> in string.
|
|
|
|
|
\note No check is done on string allocated size ! */
|
|
|
|
|
* \note No check is done on string allocated size !
|
|
|
|
|
*/
|
|
|
|
|
static int replace_string_in_string(char *string, const char *search, const char *by)
|
|
|
|
|
{
|
|
|
|
|
int search_len = strlen(search);
|
|
|
|
@ -698,7 +724,8 @@ static int replace_string_in_string(char *string, const char *search, const char
|
|
|
|
|
return replaced;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief Append a name=value filter string. The filter string can grow. */
|
|
|
|
|
/*! \brief Append a name=value filter string. The filter string can grow.
|
|
|
|
|
*/
|
|
|
|
|
static void append_var_and_value_to_filter(struct ast_str **filter,
|
|
|
|
|
struct ldap_table_config *table_config,
|
|
|
|
|
const char *name, const char *value)
|
|
|
|
@ -798,8 +825,9 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
|
|
|
|
|
ast_str_append(&filter, 0, "%s", base_table_config->additional_filter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create the first part of the query using the first parameter/value pairs we just extracted */
|
|
|
|
|
/* If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
|
|
|
|
|
/* Create the first part of the query using the first parameter/value pairs we just extracted.
|
|
|
|
|
* If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
append_var_and_value_to_filter(&filter, table_config, newparam, newval);
|
|
|
|
|
while ((newparam = va_arg(ap, const char *))) {
|
|
|
|
@ -843,7 +871,8 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
|
|
|
|
|
|
|
|
|
|
ldap_msgfree(ldap_result_msg);
|
|
|
|
|
|
|
|
|
|
/* TODO: get the default variables from the accountBaseDN, not implemented with delimited values */
|
|
|
|
|
/*! \TODO get the default variables from the accountBaseDN, not implemented with delimited values
|
|
|
|
|
*/
|
|
|
|
|
if (vars) {
|
|
|
|
|
struct ast_variable **p = vars;
|
|
|
|
|
while (*p) {
|
|
|
|
@ -913,7 +942,8 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
|
|
|
|
|
return vars;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief same as realtime_ldap_base_ap but take variable arguments count list */
|
|
|
|
|
/*! \brief same as realtime_ldap_base_ap but take variable arguments count list
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_variable **realtime_ldap_base(unsigned int *entries_count_ptr,
|
|
|
|
|
const char *basedn, const char *table_name, ...)
|
|
|
|
|
{
|
|
|
|
@ -928,9 +958,9 @@ static struct ast_variable **realtime_ldap_base(unsigned int *entries_count_ptr,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief See Asterisk doc
|
|
|
|
|
*
|
|
|
|
|
* For Realtime Dynamic(i.e., switch, queues, and directory) -- I think
|
|
|
|
|
*/
|
|
|
|
|
*
|
|
|
|
|
* For Realtime Dynamic(i.e., switch, queues, and directory) -- I think
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_variable *realtime_ldap(const char *basedn,
|
|
|
|
|
const char *table_name, va_list ap)
|
|
|
|
|
{
|
|
|
|
@ -960,12 +990,12 @@ static struct ast_variable *realtime_ldap(const char *basedn,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! \brief See Asterisk doc
|
|
|
|
|
*
|
|
|
|
|
* this function will be called for the switch statment if no match is found with the realtime_ldap function(i.e. it is a failover);
|
|
|
|
|
* however, the ast_load_realtime wil match on wildcharacters also depending on what the mode is set to
|
|
|
|
|
* this is an area of asterisk that could do with a lot of modification
|
|
|
|
|
* I think this function returns Realtime dynamic objects
|
|
|
|
|
*/
|
|
|
|
|
*
|
|
|
|
|
* this function will be called for the switch statment if no match is found with the realtime_ldap function(i.e. it is a failover);
|
|
|
|
|
* however, the ast_load_realtime wil match on wildcharacters also depending on what the mode is set to
|
|
|
|
|
* this is an area of asterisk that could do with a lot of modification
|
|
|
|
|
* I think this function returns Realtime dynamic objects
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_config *realtime_multi_ldap(const char *basedn,
|
|
|
|
|
const char *table_name, va_list ap)
|
|
|
|
|
{
|
|
|
|
@ -1022,8 +1052,7 @@ static struct ast_config *realtime_multi_ldap(const char *basedn,
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Sorting alogrithm for qsort to find the order of the variables \a a and \a b
|
|
|
|
|
/*! \brief Sorting alogrithm for qsort to find the order of the variables \a a and \a b
|
|
|
|
|
* \param a pointer to category_and_metric struct
|
|
|
|
|
* \param b pointer to category_and_metric struct
|
|
|
|
|
*
|
|
|
|
@ -1055,11 +1084,11 @@ static int compare_categories(const void *a, const void *b)
|
|
|
|
|
|
|
|
|
|
/*! \brief See Asterisk doc
|
|
|
|
|
*
|
|
|
|
|
* This is for Static Realtime (again: I think...)
|
|
|
|
|
*
|
|
|
|
|
* load the configuration stuff for the .conf files
|
|
|
|
|
* called on a reload
|
|
|
|
|
*/
|
|
|
|
|
* This is for Static Realtime (again: I think...)
|
|
|
|
|
*
|
|
|
|
|
* load the configuration stuff for the .conf files
|
|
|
|
|
* called on a reload
|
|
|
|
|
*/
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
@ -1085,7 +1114,7 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!\note Since the items come back in random order, they need to be sorted
|
|
|
|
|
/*! \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.
|
|
|
|
|
*/
|
|
|
|
@ -1171,7 +1200,7 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* \brief Function to update a set of values in ldap static mode
|
|
|
|
|
*/
|
|
|
|
|
*/
|
|
|
|
|
static int update_ldap(const char *basedn, const char *table_name, const char *attribute,
|
|
|
|
|
const char *lookup, va_list ap)
|
|
|
|
|
{
|
|
|
|
|