[Freeipa-devel] [PATCHES 0351-0353] Improvements to ID override type validation

Alexander Bokovoy abokovoy at redhat.com
Thu Jul 23 13:08:01 UTC 2015


On Thu, 23 Jul 2015, Tomas Babej wrote:
>Hi,
>
>this patchset deals mainly with the ticket:
>
>https://fedorahosted.org/freeipa/ticket/5029
>
>Details in the commit messages.
>
>Tomas

>From 83defa7e286b9e65a147598b4056abc47b4647bf Mon Sep 17 00:00:00 2001
>From: Tomas Babej <tbabej at redhat.com>
>Date: Wed, 22 Jul 2015 14:00:37 +0200
>Subject: [PATCH] dcerpc: Add get_trusted_domain_object_type method
>
>https://fedorahosted.org/freeipa/ticket/5029
>---
> ipaserver/dcerpc.py | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
>diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
>index 7220c440d16816abf5c022c840e9744f321878c4..be6313e1586cb9e3296361a8d07041d496d3223f 100644
>--- a/ipaserver/dcerpc.py
>+++ b/ipaserver/dcerpc.py
>@@ -107,6 +107,14 @@ dcerpc_error_messages = {
>          errors.RequirementError(name=_('At least the domain or IP address should be specified')),
> }
> 
>+pysss_type_key_translation_dict = {
>+    pysss_nss_idmap.ID_USER: 'user',
>+    pysss_nss_idmap.ID_GROUP: 'group',
>+    # Used for users with magic private groups
>+    pysss_nss_idmap.ID_BOTH: 'both',
>+}
>+
>+
> def assess_dcerpc_exception(num=None,message=None):
>     """
>     Takes error returned by Samba bindings and converts it into
>@@ -368,6 +376,27 @@ class DomainValidator(object):
>             raise errors.ValidationError(name=_('trusted domain object'),
>                error= _('Trusted domain did not return a valid SID for the object'))
> 
>+    def get_trusted_domain_object_type(self, name_or_sid):
>+        """
>+        Return the type of the object corresponding to the given name in
>+        the trusted domain, which is either 'user', 'group' or 'both'.
>+        The 'both' types is used for users with magic private groups.
>+        """
>+
>+        object_type = None
>+
>+        if is_sid_valid(name_or_sid):
>+            result = pysss_nss_idmap.getnamebysid(name_or_sid)
>+        else:
>+            result = pysss_nss_idmap.getsidbyname(name_or_sid)
>+
>+        if name_or_sid in result:
>+            object_type = result[name_or_sid].get(pysss_nss_idmap.TYPE_KEY)
If user or group not found, pysss_nss_idmap.getsidbyname() will return
empty dict and the line above will fail:
 >>> import pysss_nss_idmap
 >>> pysss_nss_idmap.getsidbyname('some-name')
 {}

>+
>+        # Do the translation to hide pysss_nss_idmap constants
>+        # from higher-level code
>+        return pysss_type_key_translation_dict.get(object_type)
>+
>     def get_trusted_domain_object_from_sid(self, sid):
>         root_logger.debug("Converting SID to object name: %s" % sid)
> 
>-- 
>2.1.0
>

>From b331e08905db1deb90e1188e62a51620c3f187b3 Mon Sep 17 00:00:00 2001
>From: Tomas Babej <tbabej at redhat.com>
>Date: Thu, 23 Jul 2015 12:36:53 +0200
>Subject: [PATCH] idviews: Restrict anchor to name and name to anchor
> conversions
>
>When converting the ID override anchor from AD SID representation to
>the object name, we need to properly restrict the type of the object
>that is being resolved.
>
>The same restriction applies for the opposite direction, when
>converting the object name to it's SID.
>
>https://fedorahosted.org/freeipa/ticket/5029
>---
> ipalib/plugins/idviews.py | 50 +++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 46 insertions(+), 4 deletions(-)
>
>diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py
>index 48f646b812c424435233327e8fcfa363e17104f2..4d1aefef2cc8e8259d6b62315eb266c61f5cc5fb 100644
>--- a/ipalib/plugins/idviews.py
>+++ b/ipalib/plugins/idviews.py
>@@ -434,6 +434,36 @@ class idview_unapply(baseidview_apply):
> 
> 
> # ID overrides helper methods
>+def verify_trusted_domain_object_type(validator, desired_type, name_or_sid):
>+
>+    object_type = validator.get_trusted_domain_object_type(name_or_sid)
>+
>+    if object_type == desired_type:
>+        # In case SSSD returns the same type as the type being
>+        # searched, no problems here.
>+        return True
>+
>+    elif desired_type == 'user' and object_type == 'both':
>+        # Type both denotes users with magic private groups.
>+        # Overriding attributes for such users is OK.
>+        return True
>+
>+    elif desired_type == 'group' and object_type == 'both':
>+        # However, overriding attributes for magic private groups
>+        # does not make sense. One should override the GID of
>+        # the user itself.
>+
>+        raise errors.ConversionError(
>+            name='identifier',
>+            error=_('You are trying to reference a magic private group '
>+                    'which is not allowed to be overriden. '
>+                    'Try overriding the GID attribute of the '
>+                    'corresponding user instead.')
>+            )
>+
>+    return False
>+
>+
> def resolve_object_to_anchor(ldap, obj_type, obj, fallback_to_ldap):
>     """
>     Resolves the user/group name to the anchor uuid:
>@@ -484,9 +514,15 @@ def resolve_object_to_anchor(ldap, obj_type, obj, fallback_to_ldap):
>                 sid = domain_validator.get_trusted_domain_object_sid(obj,
>                         fallback_to_ldap=fallback_to_ldap)
> 
>-                # There is no domain prefix since SID contains information
>-                # about the domain
>-                return SID_ANCHOR_PREFIX + sid
>+                # We need to verify that the object type is correct
>+                type_correct = verify_trusted_domain_object_type(
>+                        domain_validator, obj_type, sid)
>+
>+                if type_correct:
>+                    # There is no domain prefix since SID contains information
>+                    # about the domain
>+                    return SID_ANCHOR_PREFIX + sid
>+
>     except errors.ValidationError:
>         # Domain validator raises Validation Error if object name does not
>         # contain domain part (either NETBIOS\ prefix or @domain.name suffix)
>@@ -541,7 +577,13 @@ def resolve_anchor_to_object_name(ldap, obj_type, anchor):
>             domain_validator = ipaserver.dcerpc.DomainValidator(api)
>             if domain_validator.is_configured():
>                 name = domain_validator.get_trusted_domain_object_from_sid(sid)
>-                return name
>+
>+                # We need to verify that the object type is correct
>+                type_correct = verify_trusted_domain_object_type(
>+                        domain_validator, obj_type, name)
>+
>+                if type_correct:
>+                    return name
> 
>     # No acceptable object was found
>     raise errors.NotFound(
>-- 
>2.1.0
>

>From 1086f33dda3b5b92793ad6fb710be59703a186ac Mon Sep 17 00:00:00 2001
>From: Tomas Babej <tbabej at redhat.com>
>Date: Thu, 23 Jul 2015 14:00:06 +0200
>Subject: [PATCH] idviews: Enforce objectclass check in idoverride*-del
>
>Even with anchor to sid type checking, it would be still
>possible to delete a user ID override by specifying a group
>raw anchor and vice versa.
>
>This patch introduces a objectclass check in idoverride*-del
>commands to prevent that.
>
>https://fedorahosted.org/freeipa/ticket/5029
>---
> ipalib/plugins/idviews.py | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
>diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py
>index 4d1aefef2cc8e8259d6b62315eb266c61f5cc5fb..cf5c9b5e8371c89e89a4cf1d334ac0e6b514653a 100644
>--- a/ipalib/plugins/idviews.py
>+++ b/ipalib/plugins/idviews.py
>@@ -718,6 +718,25 @@ class baseidoverride_del(LDAPDelete):
> 
>     takes_options = LDAPDelete.takes_options + (fallback_to_ldap_option,)
> 
>+    def pre_callback(self, ldap, dn, *keys, **options):
>+        assert isinstance(dn, DN)
>+
>+        # Make sure the entry we're deleting has all the objectclasses
>+        # this object requires
>+        try:
>+            entry = ldap.get_entry(dn, ['objectclass'])
>+        except errors.NotFound:
>+            self.obj.handle_not_found(*keys)
>+
>+        required_object_classes = set(self.obj.object_class)
>+        actual_object_classes = set(entry['objectclass'])
>+
>+        # If not, treat it as a failed search
>+        if not required_object_classes.issubset(actual_object_classes):
>+            self.obj.handle_not_found(*keys)
>+
>+        return dn
>+
> 
> class baseidoverride_mod(LDAPUpdate):
>     __doc__ = _('Modify an ID override.')
>-- 
>2.1.0
>


-- 
/ Alexander Bokovoy




More information about the Freeipa-devel mailing list