[Home]

Summary:ASTERISK-14743: [patch] LDAP error while unregister UA
Reporter:Dmitry Demchenko (dmitry demchenko)Labels:
Date Opened:2009-08-31 15:50:46Date Closed:2011-06-07 14:07:57
Priority:MinorRegression?No
Status:Closed/CompleteComponents:Resources/res_config_ldap
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:( 0) res_config_ldap.diff
Description:Hi,

While unregistering peer the following message appers:
================
*CLI> [Aug 31 23:25:20] ERROR[13092]: res_config_ldap.c:1331 update_ldap: Couldn't modify dn:cn=????? ????????,ou=???? ??????,ou=?????????????? ??????????,l=??????,o=??????-??????,c=UA,c=Global because No such attribute    -- Unregistered SIP 'vtutov'
================

It's trying to LDAP_MOD_DELETE some atributes regardless of their existance, and when are absent throws "No such attribute"

Please take in consideration that modifications are applied to set of entries from ldap_search in turn, so there is no way to detect presence of attributes before etry is actually processed.

Suggestion: need to check existance of attributes and delete only actual ones.

Corresponding patch supplied.



****** STEPS TO REPRODUCE ******

Unregister UA while sipper is in LDAP tree (OpenLDAP 2.3.x)

****** ADDITIONAL INFORMATION ******

--- res_config_ldap.c.1 2009-08-12 19:19:00.000000000 +0300
+++ res_config_ldap.c   2009-08-31 22:24:24.000000000 +0300
@@ -1195,13 +1195,22 @@
       ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size);
       ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod));

-       ldap_mods[0]->mod_op = LDAP_MOD_REPLACE;
+
+
+//     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(newval) + 1);
-       strcpy(ldap_mods[0]->mod_values[0], newval);
+       if (strlen(newval) == 0) {
+               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[0] = ast_calloc(sizeof(char), strlen(newval) + 1);
+               strcpy(ldap_mods[0]->mod_values[0], newval);
+       }
+

       while ((newparam = va_arg(ap, const char *))) {
               newparam = convert_attribute_name_to_ldap(table_config, newparam);
@@ -1291,9 +1300,36 @@

               for (i = 0; ldap_entry; i++) {
                       dn = ldap_get_dn(ldapConn, ldap_entry);
-                       if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS)
-                               ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));

+                       int local_ldap_mods_size=1;
+                       LDAPMod **local_ldap_mods = ast_calloc(sizeof(LDAPMod *), local_ldap_mods_size);
+                       local_ldap_mods[0]=NULL;
+
+                       for (i = 0; i < mods_size - 1; i++) {
+                               int do_modify = 1;
+                               if (ldap_mods[i]->mod_op==LDAP_MOD_DELETE){
+                                       struct berval ** existing_values =  ldap_get_values_len( ldapConn, ldap_entry, ldap_mods[i]->mod_type);
+                                       if (!existing_values ||  existing_values[0]==NULL) // No values
+                                               do_modify = 0;
+
+                                       if (!existing_values) ldap_value_free_len(existing_values);
+                               }
+                               if (do_modify){
+                               // copy mod from all mods to lcal mods
+                                       local_ldap_mods_size++;
+                                       local_ldap_mods = ast_realloc(local_ldap_mods, sizeof(LDAPMod *) * local_ldap_mods_size);
+                                       local_ldap_mods[local_ldap_mods_size-1]=NULL;
+                                       local_ldap_mods[local_ldap_mods_size-2]=ldap_mods[i];
+                               }
+                       }
+
+
+                       if ((error = ldap_modify_ext_s(ldapConn, dn, local_ldap_mods, NULL, NULL)) != LDAP_SUCCESS)
+                               if (error==LDAP_REFERRAL){
+                                       ast_log(LOG_ERROR, "Referral link recieeved, not supported currently");
+                               }else
+                                       ast_log(LOG_ERROR, "Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
+                       ast_free(local_ldap_mods);
                       ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
               }
       }
diff lines 10-68/68 (END)

Comments:By: Gavin Henry (suretec) 2009-08-31 16:02:18

Thanks! Will look when your license gets approved.

By: Dmitry Demchenko (dmitry demchenko) 2009-09-03 09:21:49

It is now.

By: Gavin Henry (suretec) 2009-11-10 05:35:07.000-0600

See https://issues.asterisk.org/view.php?id=15895

By: Dmitry Demchenko (dmitry demchenko) 2009-11-10 08:03:39.000-0600

Ok, now it's clear. OpenLDAP 2.3.43 seems to be not completely standard compatible. RFC notes (http://www.ietf.org/rfc/rfc2251.txt, p.32)

 replace: replace all existing values of the given attribute
            with the new values listed, creating the attribute if it
            did not already exist.  A replace with no value will delete
            the entire attribute if it exists, and is ignored if the
            attribute does not exist.

This issue might be closed without resolution.

Sorry for fakereport.

By: Gavin Henry (suretec) 2009-11-10 08:07:09.000-0600

OpenLDAP is standards compliant. Can you double check the code in Asterisk.

By: Leif Madsen (lmadsen) 2010-10-21 08:19:24

Closed due to lack of feedback.