From 295ac6385c33d28502396ffeb9e7a5297b63a005 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: May 22 2024 08:03:38 +0000 Subject: privilege: use context.principal only when it is defined In server-like context we use LDAPI connection with auto-binding to LDAP object based on the UID of the process connecting to LDAPI UNIX domain socket. This means context.principal is not set and we cannot use it. In principal_has_privilege() we can take None principal object as a sign that currently bound LDAP DN has to be checked for the privilege. This allows to match any type of account to the privilege, with exception of the cn=Directory Manager which is never added to privileges explicitly. cn=Directory Manager will be allowed any privilege because it already can write to any LDAP entry. Fixes: https://pagure.io/freeipa/issue/9583 Signed-off-by: Alexander Bokovoy Reviewed-By: Thomas Woerner Reviewed-By: Rob Crittenden Reviewed-By: Rafael Guterres Jeffman --- diff --git a/ipaserver/plugins/privilege.py b/ipaserver/plugins/privilege.py index e7dbdb9..47f27f1 100644 --- a/ipaserver/plugins/privilege.py +++ b/ipaserver/plugins/privilege.py @@ -84,13 +84,24 @@ def validate_permission_to_privilege(api, permission): def principal_has_privilege(api, principal, privilege): + """ + Validate that the principal is a member of the specified privilege. + If principal is None, use currently bound LDAP DN for validation. + cn=Directory Manager is explicitly allowed + """ privilege_dn = api.Object.privilege.get_dn(privilege) ldap = api.Backend.ldap2 + if principal is None: + dn_or_princ = DN(ldap.conn.whoami_s()[4:]) + if dn_or_princ == DN('cn=Directory Manager'): + return True + else: + dn_or_princ = principal # First try: Check if there is a principal that has the needed # privilege. filter = ldap.make_filter({ - 'krbprincipalname': principal, + 'krbprincipalname': dn_or_princ, 'memberof': privilege_dn}, rules=ldap.MATCH_ALL) try: @@ -99,6 +110,10 @@ def principal_has_privilege(api, principal, privilege): except errors.NotFound: pass + # Do not run ID override check for the user that has no Kerberos principal + if principal is None: + return False + # Second try: Check if there is an idoverride for the principal as # ipaOriginalUid that has the needed privilege. filter = ldap.make_filter(