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 <tba...@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)
+
+        # 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 <tba...@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 <tba...@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

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to