From b2836dde7ef9f1c14ccd721f2d94ec8f3683433b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 20 Feb 2017 06:30:31 -0500 Subject: res_config_ldap: Fix configuration inheritance from _general The "_general" configuration section allows administrators to provide both general configuration options (host, port, url, etc.) as well as a global realtime-to-LDAP-attribute mapping that is a fallback if one of the later sections do not override it. This neglected to exclude the general configuration options from the mapping. As an example, during my testing, chan_sip requested 'port' from realtime, and because I did not have it defined, it pulled in the 'port' configuration option from "_general." We now filter those out explicitly. Change-Id: I1fc61560bf96b8ba623063cfb7e0a49c4690d778 --- res/res_config_ldap.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index ea7bbadaa..9d34e5709 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -1686,6 +1686,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 +1791,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); + } } } } -- cgit v1.2.3 From 011b7be62a0c64cee904a996d23ad65c13022e39 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 20 Feb 2017 06:45:54 -0500 Subject: res_config_ldap: Make memory allocation more consistent The code in update_ldap() and update2_ldap() was using both Asterisk's memory allocation routines as well as OpenLDAP's. I've changed it so that everything that is passed to OpenLDAP's functions are allocated with their routines. Change-Id: Iafec9c1fd8ea49ccc496d6316769a6a426daa804 --- res/res_config_ldap.c | 97 +++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 58 deletions(-) diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index 9d34e5709..224467722 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -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; } } @@ -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; @@ -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); @@ -516,14 +516,14 @@ 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); } 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); @@ -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; } @@ -1292,7 +1287,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a } 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 +1295,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 +1309,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 +1318,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,10 +1360,10 @@ 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 */ @@ -1401,7 +1393,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; } @@ -1481,16 +1473,12 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct } 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 +1498,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,7 +1540,7 @@ 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 */ @@ -1577,14 +1562,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; } -- cgit v1.2.3 From b980cae1f7a0d392e5b25eaa6676687583fbd3c4 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 20 Feb 2017 06:49:17 -0500 Subject: res_config_ldap: Remove extraneous line numbers from log messages Extraneous line numbers were being output in many log messages. These have been removed. Change-Id: Ice9efa3d252ee87f37fa8f5ea852fda482675431 --- res/res_config_ldap.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index 224467722..b004e7893 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -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); } @@ -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; @@ -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) { @@ -519,14 +519,14 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf 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) { 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; @@ -1246,7 +1246,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); @@ -1282,7 +1282,7 @@ 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; } @@ -1368,12 +1368,12 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a } /* 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); @@ -1466,7 +1466,7 @@ 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; @@ -1546,7 +1546,7 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct /* 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); -- cgit v1.2.3 From d8972f50f4b3c47a2271e6db52604eee1796fd80 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Mon, 20 Feb 2017 06:53:47 -0500 Subject: res_config_ldap: Don't try to delete non-existent attributes OpenLDAP will raise an error when we try to delete an LDAP attribute that doesn't exist. We need to filter out LDAP_MOD_DELETE requests based on which attributes the current LDAP entry actually has. There is of course a small window of opportunity for this to still fail, but it is much less likely now. Change-Id: I3fe1b04472733e43151563aaf9f8b49980273e6b --- res/res_config_ldap.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index b004e7893..374f0dbe9 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -1214,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, @@ -1378,12 +1462,30 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a } 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); } -- cgit v1.2.3