ldap2: fix implementation of can_add

ldap2.can_add checks for add permission of a given entry.
It did not work properly due to a defect in 389 DS.  Now that the
defect has been fixed, we also need to update can_add to work with
the mechanism 389 DS provides for checking add permission for
entries where ACIs are in effect.

Update the ldap2.can_add implementation to perform the add
permission check properly.  Also update call sites accordingly.

Update the spec file to require 389-ds-base-1.3.7.9-1 which is the
first release containing the fix.  This version of 389-ds-base also
resolves a couple of other issues related to replication and
connection management.

Fixes: https://pagure.io/freeipa/issue/6609
Fixes: https://pagure.io/freeipa/issue/7165
Fixes: https://pagure.io/freeipa/issue/7228
Reviewed-By: Christian Heimes <cheimes@redhat.com>
This commit is contained in:
Fraser Tweedale 2018-02-05 19:47:33 +11:00 committed by Christian Heimes
parent 4daac52ddd
commit b466172d68
3 changed files with 39 additions and 15 deletions

View File

@ -315,8 +315,10 @@ Requires: python3-pyldap >= %{python3_ldap_version}
Requires: python2-ipaserver = %{version}-%{release} Requires: python2-ipaserver = %{version}-%{release}
Requires: python2-ldap >= %{python2_ldap_version} Requires: python2-ldap >= %{python2_ldap_version}
%endif %endif
# 1.3.7.6-1: https://bugzilla.redhat.com/show_bug.cgi?id=1488295 # 1.3.7.9-1: https://bugzilla.redhat.com/show_bug.cgi?id=1459946
Requires: 389-ds-base >= 1.3.7.6-1 # https://bugzilla.redhat.com/show_bug.cgi?id=1511462
# https://bugzilla.redhat.com/show_bug.cgi?id=1514033
Requires: 389-ds-base >= 1.3.7.9-1
Requires: openldap-clients > 2.4.35-4 Requires: openldap-clients > 2.4.35-4
Requires: nss >= 3.14.3-12.0 Requires: nss >= 3.14.3-12.0
Requires: nss-tools >= 3.14.3-12.0 Requires: nss-tools >= 3.14.3-12.0
@ -361,8 +363,10 @@ Requires(postun): systemd-units
Requires: policycoreutils >= 2.1.12-5 Requires: policycoreutils >= 2.1.12-5
Requires: tar Requires: tar
Requires(pre): certmonger >= 0.79.5-1 Requires(pre): certmonger >= 0.79.5-1
# 1.3.7.6-1: https://bugzilla.redhat.com/show_bug.cgi?id=1488295 # 1.3.7.9-1: https://bugzilla.redhat.com/show_bug.cgi?id=1459946
Requires(pre): 389-ds-base >= 1.3.7.6-1 # https://bugzilla.redhat.com/show_bug.cgi?id=1511462
# https://bugzilla.redhat.com/show_bug.cgi?id=1514033
Requires(pre): 389-ds-base >= 1.3.7.9-1
Requires: fontawesome-fonts Requires: fontawesome-fonts
Requires: open-sans-fonts Requires: open-sans-fonts
Requires: openssl Requires: openssl

View File

@ -235,7 +235,7 @@ class ca_add(LDAPCreate):
def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options):
ca_enabled_check(self.api) ca_enabled_check(self.api)
if not ldap.can_add(dn[1:]): if not ldap.can_add(dn[1:], 'ipaca'):
raise errors.ACIError( raise errors.ACIError(
info=_("Insufficient 'add' privilege for entry '%s'.") % dn) info=_("Insufficient 'add' privilege for entry '%s'.") % dn)

View File

@ -330,18 +330,38 @@ class ldap2(CrudBackend, LDAPClient):
return False return False
def can_add(self, dn): def can_add(self, parent_dn, objectclass):
"""Returns True/False if the currently bound user has add permissions
on the entry.
""" """
assert isinstance(dn, DN) Returns True/False if the currently bound user has
attrs = self.get_effective_rights(dn, ["*"]) permission to add an entry with the given objectclass
if 'entrylevelrights' in attrs: immediately below the entry with the given DN.
entry_rights = attrs['entrylevelrights'][0]
if 'a' in entry_rights:
return True
return False For example, to check if an entry with objectclass=ipaca
can be added under cn=cas,cn=ca,{basedn}, you should call
``can_add(DN('cn=cas,...'), 'ipaca')``.
"""
assert isinstance(parent_dn, DN)
# the rules for how to request the template entry, and
# the expectations about how 389 constructs the template
# entry, are described here:
#
# https://pagure.io/389-ds-base/issue/49278#comment-480856
#
try:
entry = self.get_entries(
parent_dn,
_ldap.SCOPE_ONELEVEL,
# rdn value of template entry is: template_<objcls>_objectclass
'(cn=template_{}_objectclass)'.format(objectclass),
# request tempalate entry with given objectclass
['cn@{}'.format(objectclass)],
get_effective_rights=True,
)[0]
return 'a' in entry['entrylevelrights'][0]
except errors.NotFound:
return False
def modify_password(self, dn, new_pass, old_pass='', otp='', skip_bind=False): def modify_password(self, dn, new_pass, old_pass='', otp='', skip_bind=False):
"""Set user password.""" """Set user password."""