@ -1212,6 +1212,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 ,
@ -1376,12 +1460,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 ) ;
}