Merge changes from topic 'ASTERISK-26580' into 13

* changes:
  res_config_ldap: Don't try to delete non-existent attributes
  res_config_ldap: Remove extraneous line numbers from log messages
  res_config_ldap: Make memory allocation more consistent
  res_config_ldap: Fix configuration inheritance from _general
changes/55/5055/1
Joshua Colp 9 years ago committed by Gerrit Code Review
commit ef105410d8

@ -124,7 +124,7 @@ static struct ldap_table_config *table_config_new(const char *table_name)
if (table_name) {
if (!(p->table_name = ast_strdup(table_name))) {
free(p);
ast_free(p);
return NULL;
}
}
@ -192,7 +192,7 @@ static int semicolon_count_var(struct ast_variable *var)
return 0;
}
ast_debug(2, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value);
ast_debug(2, "semicolon_count_var: %s\n", var_value->value);
return semicolon_count_str(var_value->value);
}
@ -238,7 +238,7 @@ static void table_configs_free(void)
if (c->attributes) {
ast_variables_destroy(c->attributes);
}
free(c);
ast_free(c);
}
base_table_config = NULL;
@ -332,7 +332,7 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config
for (v = values; *v; v++) {
value = *v;
valptr = value->bv_val;
ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr);
ast_debug(2, "attribute_name: %s LDAP value: %s\n", attribute_name, valptr);
if (is_realmed_password_attribute) {
if (!strncasecmp(valptr, "{md5}", 5)) {
valptr += 5;
@ -424,7 +424,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
* 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.
*/
vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1);
vars = ast_calloc(tot_count + 1, sizeof(struct ast_variable *));
ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
@ -469,7 +469,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
delim_value = ast_strdup(valptr);
if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) {
ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value);
ast_debug(4, "is delimited %d times: %s\n", delim_tot_count, delim_value);
is_delimited = 1;
}
}
@ -479,11 +479,11 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
/* for non-Static RealTime, first */
for (i = pos; !ast_strlen_zero(valptr + i); i++) {
ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
ast_debug(4, "DELIM pos: %d i: %d\n", pos, i);
if (delim_value[i] == ';') {
delim_value[i] = '\0';
ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
ast_debug(2, "DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos);
if (prev) {
prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
@ -501,9 +501,9 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
}
}
if (ast_strlen_zero(valptr + i)) {
ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count);
ast_debug(4, "DELIM pos: %d i: %d delim_count: %d\n", pos, i, delim_count);
/* Last delimited value */
ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos);
ast_debug(4, "DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos);
if (prev) {
prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name);
if (prev->next) {
@ -516,17 +516,17 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
is_delimited = 0;
pos = 0;
}
free(delim_value);
ast_free(delim_value);
delim_value = NULL;
ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i);
ast_debug(4, "DELIM pos: %d i: %d\n", pos, i);
} else {
/* not delimited */
if (delim_value) {
free(delim_value);
ast_free(delim_value);
delim_value = NULL;
}
ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr);
ast_debug(2, "attribute_name: %s value: %s\n", attribute_name, valptr);
if (prev) {
prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name);
@ -550,7 +550,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
if (tmpdebug && tmpdebug2) {
ast_debug(3, "LINE(%d) Added to vars - %s = %s\n", __LINE__, tmpdebug->value, tmpdebug2->value);
ast_debug(3, "Added to vars - %s = %s\n", tmpdebug->value, tmpdebug2->value);
}
}
vars[entry_index++] = var;
@ -561,7 +561,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
} while (delim_count <= delim_tot_count && static_table_config == table_config);
if (static_table_config != table_config) {
ast_debug(3, "LINE(%d) Added to vars - non static\n", __LINE__);
ast_debug(3, "Added to vars - non static\n");
vars[entry_index++] = var;
prev = NULL;
@ -928,13 +928,8 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
}
}
if (filter) {
ast_free(filter);
}
if (clean_basedn) {
ast_free(clean_basedn);
}
ast_free(filter);
ast_free(clean_basedn);
ast_mutex_unlock(&ldap_lock);
@ -1007,7 +1002,7 @@ static struct ast_variable *realtime_ldap(const char *basedn,
}
p++;
}
free(vars);
ast_free(vars);
}
return var;
}
@ -1066,7 +1061,7 @@ static struct ast_config *realtime_multi_ldap(const char *basedn,
p++;
}
}
free(vars);
ast_free(vars);
}
return cfg;
@ -1138,7 +1133,7 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name
* first, and since the data could easily exceed stack size, this is
* allocated from the heap.
*/
if (!(categories = ast_calloc(sizeof(*categories), vars_count))) {
if (!(categories = ast_calloc(vars_count, sizeof(*categories)))) {
return NULL;
}
@ -1219,6 +1214,90 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name
return cfg;
}
/*!
* \internal
* \brief Remove LDAP_MOD_DELETE modifications that will not succeed
*
* \details
* A LDAP_MOD_DELETE operation will fail if the LDAP entry does not already have
* the corresponding attribute. Because we may be updating multiple LDAP entries
* in a single call to update_ldap(), we may need our own copy of the
* modifications array for each one.
*
* \note
* This function dynamically allocates memory. If it returns a non-NULL pointer,
* it is up to the caller to free it with ldap_mods_free()
*
* \returns an LDAPMod * if modifications needed to be removed, NULL otherwise.
*/
static LDAPMod **massage_mods_for_entry(LDAPMessage *entry, LDAPMod **mods, size_t count)
{
size_t i;
int remove[count];
size_t remove_count = 0;
for (i = 0; i < count; i++) {
BerElement *ber = NULL;
char *attribute;
int exists = 0;
if (mods[i]->mod_op != LDAP_MOD_DELETE) {
continue;
}
/* If we are deleting something, it has to exist */
attribute = ldap_first_attribute(ldapConn, entry, &ber);
while (attribute) {
if (!strcasecmp(attribute, mods[i]->mod_type)) {
/* OK, we have the attribute */
exists = 1;
ldap_memfree(attribute);
break;
}
ldap_memfree(attribute);
attribute = ldap_next_attribute(ldapConn, entry, ber);
}
if (!exists) {
remove[remove_count++] = i;
}
}
if (remove_count) {
size_t k, remove_index;
LDAPMod **x = ldap_memcalloc(count - remove_count + 1, sizeof(LDAPMod *));
for (i = 0, k = 0; i < count; i++) {
int skip = 0;
/* Is this one we have to remove? */
for (remove_index = 0; !skip && remove_index < remove_count; remove_index++) {
skip = (remove[remove_index] == i);
}
if (skip) {
ast_debug(3, "Skipping %s deletion because it doesn't exist\n",
mods[i]->mod_type);
continue;
}
x[k] = ldap_memcalloc(1, sizeof(LDAPMod));
x[k]->mod_op = mods[i]->mod_op;
x[k]->mod_type = ldap_strdup(mods[i]->mod_type);
if (mods[i]->mod_values) {
x[k]->mod_values = ldap_memcalloc(2, sizeof(char *));
x[k]->mod_values[0] = ldap_strdup(mods[i]->mod_values[0]);
}
k++;
}
/* NULL terminate */
x[k] = NULL;
return x;
}
return NULL;
}
/* \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,
@ -1251,7 +1330,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
}
if (!attribute || !lookup) {
ast_log(LOG_WARNING, "LINE(%d): search parameters are empty.\n", __LINE__);
ast_log(LOG_WARNING, "Search parameters are empty.\n");
return -1;
}
ast_mutex_lock(&ldap_lock);
@ -1287,12 +1366,12 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
* one parameter/value pair and delimit them with a semicolon */
newparam = convert_attribute_name_to_ldap(table_config, field->name);
if (!newparam) {
ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
ast_log(LOG_WARNING, "Need at least one parameter to modify.\n");
return -1;
}
mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
ldap_mods = ldap_memcalloc(sizeof(LDAPMod *), mods_size);
ldap_mods = ldap_memcalloc(mods_size, sizeof(LDAPMod *));
ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod));
ldap_mods[0]->mod_type = ldap_strdup(newparam);
@ -1300,7 +1379,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
ldap_mods[0]->mod_op = LDAP_MOD_DELETE;
} else {
ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2);
ldap_mods[0]->mod_values = ldap_memcalloc(2, sizeof(char *));
ldap_mods[0]->mod_values[0] = ldap_strdup(field->value);
}
@ -1314,7 +1393,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
ldap_mods[i]->mod_values[0] = ldap_memrealloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(field->value) + 2));
strcat(ldap_mods[i]->mod_values[0], ";");
strcat(ldap_mods[i]->mod_values[0], field->value);
mod_exists = 1;
mod_exists = 1;
break;
}
}
@ -1323,22 +1402,19 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
if (!mod_exists) {
mods_size++;
ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
ldap_mods[mods_size - 1] = NULL;
ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod));
ldap_mods[mods_size - 2]->mod_type = ldap_memcalloc(sizeof(char), strlen(newparam) + 1);
strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
ldap_mods[mods_size - 2]->mod_type = ldap_strdup(newparam);
if (strlen(field->value) == 0) {
ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE;
} else {
ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(sizeof(char *), 2);
ldap_mods[mods_size - 2]->mod_values[0] = ldap_memcalloc(sizeof(char), strlen(field->value) + 1);
strcpy(ldap_mods[mods_size - 2]->mod_values[0], field->value);
ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(2, sizeof(char *));
ldap_mods[mods_size - 2]->mod_values[0] = ldap_strdup(field->value);
}
/* NULL terminate */
ldap_mods[mods_size - 1] = NULL;
}
}
/* freeing ldap_mods further down */
@ -1368,30 +1444,48 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
ast_mutex_unlock(&ldap_lock);
free(filter);
free(clean_basedn);
ast_free(filter);
ast_free(clean_basedn);
ldap_msgfree(ldap_result_msg);
ldap_mods_free(ldap_mods, 0);
ldap_mods_free(ldap_mods, 1);
return -1;
}
/* Ready to update */
if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries);
ast_debug(3, "Modifying %s=%s hits: %d\n", attribute, lookup, num_entries);
for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) {
ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
ast_debug(3, "%s=%s\n", ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
} else {
ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type);
ast_debug(3, "deleting %s\n", ldap_mods[i]->mod_type);
}
}
ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
for (i = 0; ldap_entry; i++) {
for (i = 0; ldap_entry; i++) {
LDAPMod **working = ldap_mods;
LDAPMod **massaged = massage_mods_for_entry(ldap_entry, ldap_mods, mods_size - 1);
if (massaged) {
/* Did we massage everything out of the list? */
if (massaged[0] == NULL) {
ast_debug(3, "Nothing left to modify - skipping\n");
ldap_mods_free(massaged, 1);
continue;
}
working = massaged;
}
dn = ldap_get_dn(ldapConn, ldap_entry);
if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) {
if ((error = ldap_modify_ext_s(ldapConn, dn, working, NULL, NULL)) != LDAP_SUCCESS) {
ast_log(LOG_ERROR, "Couldn't modify '%s'='%s', dn:%s because %s\n",
attribute, lookup, dn, ldap_err2string(error));
}
if (massaged) {
ldap_mods_free(massaged, 1);
}
ldap_memfree(dn);
ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
}
@ -1401,7 +1495,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a
ast_free(filter);
ast_free(clean_basedn);
ldap_msgfree(ldap_result_msg);
ldap_mods_free(ldap_mods, 0);
ldap_mods_free(ldap_mods, 1);
return num_entries;
}
@ -1474,23 +1568,19 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct
field = update_fields;
newparam = convert_attribute_name_to_ldap(table_config, field->name);
if (!newparam) {
ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__);
ast_log(LOG_WARNING, "Need at least one parameter to modify.\n");
ast_free(filter);
ast_free(clean_basedn);
return -1;
}
mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */
ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));
ldap_mods = ldap_memcalloc(mods_size, sizeof(LDAPMod *));
ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod));
ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
strcpy(ldap_mods[0]->mod_type, newparam);
ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2);
ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(field->value) + 1);
strcpy(ldap_mods[0]->mod_values[0], field->value);
ldap_mods[0]->mod_type = ldap_strdup(newparam);
ldap_mods[0]->mod_values = ldap_memcalloc(2, sizeof(char *));
ldap_mods[0]->mod_values[0] = ldap_strdup(field->value);
while ((field = field->next)) {
newparam = convert_attribute_name_to_ldap(table_config, field->name);
@ -1510,18 +1600,15 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct
/* create new mod */
if (!mod_exists) {
mods_size++;
ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
ldap_mods[mods_size - 1] = NULL;
ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod));
ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size);
ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod));
ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE;
ldap_mods[mods_size - 2]->mod_type = ldap_strdup(newparam);
ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(2, sizeof(char *));
ldap_mods[mods_size - 2]->mod_values[0] = ldap_strdup(field->value);
ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1);
strcpy(ldap_mods[mods_size - 2]->mod_type, newparam);
ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2);
ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(field->value) + 1);
strcpy(ldap_mods[mods_size - 2]->mod_values[0], field->value);
/* NULL terminate */
ldap_mods[mods_size - 1] = NULL;
}
}
/* freeing ldap_mods further down */
@ -1555,13 +1642,13 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct
ast_free(filter);
ast_free(clean_basedn);
ldap_msgfree(ldap_result_msg);
ldap_mods_free(ldap_mods, 0);
ldap_mods_free(ldap_mods, 1);
return -1;
}
/* Ready to update */
if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
for (i = 0; option_debug > 2 && i < mods_size - 1; i++) {
ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
ast_debug(3, "%s=%s\n", ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]);
}
ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
@ -1577,14 +1664,10 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct
}
ast_mutex_unlock(&ldap_lock);
if (filter) {
ast_free(filter);
}
if (clean_basedn) {
ast_free(clean_basedn);
}
ast_free(filter);
ast_free(clean_basedn);
ldap_msgfree(ldap_result_msg);
ldap_mods_free(ldap_mods, 0);
ldap_mods_free(ldap_mods, 1);
return num_entries;
}
@ -1686,6 +1769,21 @@ static int reload(void)
return 0;
}
static int config_can_be_inherited(const char *key)
{
int i;
static const char * const config[] = {
"basedn", "host", "pass", "port", "protocol", "url", "user", "version", NULL
};
for (i = 0; config[i]; i++) {
if (!strcasecmp(key, config[i])) {
return 0;
}
}
return 1;
}
/*! \brief parse the configuration file
*/
static int parse_config(void)
@ -1776,7 +1874,9 @@ static int parse_config(void)
if (!strcasecmp(var->name, "additionalFilter")) {
table_config->additional_filter = ast_strdup(var->value);
} else {
ldap_table_config_add_attribute(table_config, var->name, var->value);
if (!is_general || config_can_be_inherited(var->name)) {
ldap_table_config_add_attribute(table_config, var->name, var->value);
}
}
}
}

Loading…
Cancel
Save