diff options
author | Rob Crittenden <rcritten@redhat.com> | 2011-05-16 17:39:23 -0400 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2011-05-27 13:51:37 -0400 |
commit | 9cc0754b710500519c6f5fd41a0a0237a43e04b0 (patch) | |
tree | 73534c646557c583290f0b9e070b7d1cf0e553d7 /ipalib/plugins/baseldap.py | |
parent | aa29a8a769c62b07cc4e6d82fc79846505cc9fa3 (diff) | |
download | freeipa-9cc0754b710500519c6f5fd41a0a0237a43e04b0.tar.gz freeipa-9cc0754b710500519c6f5fd41a0a0237a43e04b0.tar.xz freeipa-9cc0754b710500519c6f5fd41a0a0237a43e04b0.zip |
Add option to limit the attributes allowed in an entry.
Kerberos ticket policy can update policy in a user entry. This allowed
set/addattr to be used to modify attributes outside of the ticket policy
perview, also bypassing all validation/normalization. Likewise the
ticket policy was updatable by the user plugin bypassing all validation.
Add two new LDAPObject values to control this behavior:
limit_object_classes: only attributes in these are allowed
disallow_object_classes: attributes in these are disallowed
By default both of these lists are empty so are skipped.
ticket 744
Diffstat (limited to 'ipalib/plugins/baseldap.py')
-rw-r--r-- | ipalib/plugins/baseldap.py | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index 43533c8c9..f07fb2774 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -253,6 +253,8 @@ class LDAPObject(Object): # If an objectclass is possible but not default in an entry. Needed for # collecting attributes for ACI UI. possible_objectclasses = [] + limit_object_classes = [] # Only attributes in these are allowed + disallow_object_classes = [] # Disallow attributes in these search_attributes = [] search_attributes_config = None default_attributes = [] @@ -438,6 +440,36 @@ def _check_empty_attrs(params, entry_attrs): raise errors.RequirementError(name=a) +def _check_limit_object_class(attributes, attrs, allow_only): + """ + If the set of objectclasses is limited enforce that only those + are updated in entry_attrs (plus dn) + + allow_only tells us what mode to check in: + + If True then we enforce that the attributes must be in the list of + allowed. + + If False then those attributes are not allowed. + """ + if len(attributes[0]) == 0 and len(attributes[1]) == 0: + return + limitattrs = deepcopy(attrs) + # Go through the MUST first + for (oid, attr) in attributes[0].iteritems(): + if attr.names[0].lower() in limitattrs: + if not allow_only: + raise errors.ObjectclassViolation(info='attribute "%(attribute)s" not allowed' % dict(attribute=attr.names[0].lower())) + limitattrs.remove(attr.names[0].lower()) + # And now the MAY + for (oid, attr) in attributes[1].iteritems(): + if attr.names[0].lower() in limitattrs: + if not allow_only: + raise errors.ObjectclassViolation(info='attribute "%(attribute)s" not allowed' % dict(attribute=attr.names[0].lower())) + limitattrs.remove(attr.names[0].lower()) + if len(limitattrs) > 0 and allow_only: + raise errors.ObjectclassViolation(info='attribute "%(attribute)s" not allowed' % dict(attribute=limitattrs[0])) + class CallbackInterface(Method): """ Callback registration interface @@ -568,6 +600,8 @@ class LDAPCreate(CallbackInterface, crud.Create): ) _check_single_value_attrs(self.params, entry_attrs) + _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True) + _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False) try: ldap.add_entry(dn, entry_attrs, normalize=self.obj.normalize_dn) @@ -848,6 +882,8 @@ class LDAPUpdate(LDAPQuery, crud.Update): _check_single_value_attrs(self.params, entry_attrs) _check_empty_attrs(self.obj.params, entry_attrs) + _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True) + _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False) rdnupdate = False try: |