[python-ldap] Modlist with a replace sometimes fails
William
william at blackhats.net.au
Thu Feb 18 18:23:39 EST 2016
> Please give more details:
> - OpenLDAP version
> - *exact* modify operation
> - *exact* error message
> - preferrably test code illustrating the issue
389-ds-1.3.5-git-master. The replace was replacing nsslapd-cachememsize on the
ldbm backend instance.
It rejects the op, because you can't delete the nsslapd-cachememsize, only
replace.
The issue is there are *many* attributes like this in cn=config on 389-ds that
can only be replaced, and block deletes.
I propsed a patch to pyldap yesterday for this:
This leaves the *default* behaviour to be the current delete -> add method. It
adds a boolean flag to the operation allowing someone to select if they want to
use replace instead.
The reason I do *not* want to manually craft the modlist is that would mean
practically re-implementing all of modlist, as our testing framework has an ldap
entry wrapper. I'm writing it to have a dict of data, then .save() to commit the
object based on modlist.modifyModlist(). Especially for handling our cn=config
entries, the ability to use mod_replace is vital.
diff --git a/Lib/ldap/modlist.py b/Lib/ldap/modlist.py
index 0053a3f..a56c3e5 100644
--- a/Lib/ldap/modlist.py
+++ b/Lib/ldap/modlist.py
@@ -49,7 +49,7 @@ def addModlist(entry,ignore_attr_types=None):
def modifyModlist(
- old_entry,new_entry,ignore_attr_types=None,ignore_oldexistent=0,case_ignore_at
tr_types=None
+ old_entry,new_entry,ignore_attr_types=None,ignore_oldexistent=0,case_ignore_at
tr_types=None,replace_is_add_then_delete=True
):
"""
Build differential modify list for calling LDAPObject.modify()/modify_s()
@@ -69,6 +69,10 @@ def modifyModlist(
case_ignore_attr_types
List of attribute type names for which comparison will be made
case-insensitive
+ replace_is_add_then_delete
+ Determines if a replace operation is carried out as add then delete
+ or if it is a pure ldap replace. This can have behavioural affects on
+ certain ldap servers and object types IE configuration directories.
"""
ignore_attr_types = list_dict(map(lower,(ignore_attr_types or [])))
case_ignore_attr_types = list_dict(map(lower,(case_ignore_attr_types or [])))
@@ -111,8 +115,11 @@ def modifyModlist(
replace_attr_value = 1
break
if replace_attr_value:
- modlist.append((ldap.MOD_DELETE,attrtype,None))
- modlist.append((ldap.MOD_ADD,attrtype,new_value))
+ if replace_is_add_then_delete:
+ modlist.append((ldap.MOD_DELETE,attrtype,None))
+ modlist.append((ldap.MOD_ADD,attrtype,new_value))
+ else:
+ modlist.append((ldap.MOD_REPLACE,attrtype,new_value))
elif old_value and not new_value:
# Completely delete an existing attribute
modlist.append((ldap.MOD_DELETE,attrtype,None))
--
William <william at blackhats.net.au>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://mail.python.org/pipermail/python-ldap/attachments/20160219/946fc8d1/attachment.sig>
More information about the python-ldap
mailing list