Blame SOURCES/0002-Add-checks-to-prevent-adding-auth-indicators-to-inte_rhbz#1979625.patch

b1d427
From a5d2857297cfcf87ed8973df96e89ebcef22850d Mon Sep 17 00:00:00 2001
b1d427
From: Antonio Torres <antorres@redhat.com>
b1d427
Date: Mon, 8 Mar 2021 18:15:50 +0100
b1d427
Subject: [PATCH] Add checks to prevent adding auth indicators to internal IPA
b1d427
 services
b1d427
b1d427
Authentication indicators should not be enforced against internal
b1d427
IPA services, since not all users of those services are able to produce
b1d427
Kerberos tickets with all the auth indicator options. This includes
b1d427
host, ldap, HTTP and cifs in IPA server and cifs in IPA clients.
b1d427
If a client that is being promoted to replica has an auth indicator
b1d427
in its host principal then the promotion is aborted.
b1d427
b1d427
Fixes: https://pagure.io/freeipa/issue/8206
b1d427
Signed-off-by: Antonio Torres <antorres@redhat.com>
b1d427
---
b1d427
 ipaserver/install/server/replicainstall.py | 13 ++++++++++++
b1d427
 ipaserver/plugins/host.py                  |  5 ++++-
b1d427
 ipaserver/plugins/service.py               | 24 ++++++++++++++++++++++
b1d427
 3 files changed, 41 insertions(+), 1 deletion(-)
b1d427
b1d427
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
b1d427
index 73967a224..f1fb91036 100644
b1d427
--- a/ipaserver/install/server/replicainstall.py
b1d427
+++ b/ipaserver/install/server/replicainstall.py
b1d427
@@ -770,6 +770,15 @@ def promotion_check_ipa_domain(master_ldap_conn, basedn):
b1d427
         ))
b1d427
 
b1d427
 
b1d427
+def promotion_check_host_principal_auth_ind(conn, hostdn):
b1d427
+    entry = conn.get_entry(hostdn, ['krbprincipalauthind'])
b1d427
+    if 'krbprincipalauthind' in entry:
b1d427
+        raise RuntimeError(
b1d427
+            "Client cannot be promoted to a replica if the host principal "
b1d427
+            "has an authentication indicator set."
b1d427
+        )
b1d427
+
b1d427
+
b1d427
 @common_cleanup
b1d427
 @preserve_enrollment_state
b1d427
 def promote_check(installer):
b1d427
@@ -956,6 +965,10 @@ def promote_check(installer):
b1d427
                                      config.master_host_name, None)
b1d427
 
b1d427
         promotion_check_ipa_domain(conn, remote_api.env.basedn)
b1d427
+        hostdn = DN(('fqdn', api.env.host),
b1d427
+                    api.env.container_host,
b1d427
+                    api.env.basedn)
b1d427
+        promotion_check_host_principal_auth_ind(conn, hostdn)
b1d427
 
b1d427
         # Make sure that domain fulfills minimal domain level
b1d427
         # requirement
b1d427
diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py
b1d427
index eb1f8ef04..41fa933e2 100644
b1d427
--- a/ipaserver/plugins/host.py
b1d427
+++ b/ipaserver/plugins/host.py
b1d427
@@ -38,7 +38,7 @@ from .baseldap import (LDAPQuery, LDAPObject, LDAPCreate,
b1d427
                                      LDAPAddAttributeViaOption,
b1d427
                                      LDAPRemoveAttributeViaOption)
b1d427
 from .service import (
b1d427
-    validate_realm, normalize_principal,
b1d427
+    validate_realm, validate_auth_indicator, normalize_principal,
b1d427
     set_certificate_attrs, ticket_flags_params, update_krbticketflags,
b1d427
     set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap,
b1d427
     rename_ipaallowedtoperform_to_ldap, revoke_certs)
b1d427
@@ -735,6 +735,8 @@ class host_add(LDAPCreate):
b1d427
         update_krbticketflags(ldap, entry_attrs, attrs_list, options, False)
b1d427
         if 'krbticketflags' in entry_attrs:
b1d427
             entry_attrs['objectclass'].append('krbticketpolicyaux')
b1d427
+        validate_auth_indicator(entry_attrs)
b1d427
+
b1d427
         return dn
b1d427
 
b1d427
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
b1d427
@@ -993,6 +995,7 @@ class host_mod(LDAPUpdate):
b1d427
             if 'krbprincipalaux' not in (item.lower() for item in
b1d427
                                          entry_attrs['objectclass']):
b1d427
                 entry_attrs['objectclass'].append('krbprincipalaux')
b1d427
+            validate_auth_indicator(entry_attrs)
b1d427
 
b1d427
         add_sshpubkey_to_attrs_pre(self.context, attrs_list)
b1d427
 
b1d427
diff --git a/ipaserver/plugins/service.py b/ipaserver/plugins/service.py
b1d427
index 1c9347804..cfbbff3c6 100644
b1d427
--- a/ipaserver/plugins/service.py
b1d427
+++ b/ipaserver/plugins/service.py
b1d427
@@ -201,6 +201,28 @@ def validate_realm(ugettext, principal):
b1d427
         raise errors.RealmMismatch()
b1d427
 
b1d427
 
b1d427
+def validate_auth_indicator(entry):
b1d427
+    new_value = entry.get('krbprincipalauthind', None)
b1d427
+    if not new_value:
b1d427
+        return
b1d427
+    # The following services are considered internal IPA services
b1d427
+    # and shouldn't be allowed to have auth indicators.
b1d427
+    # https://pagure.io/freeipa/issue/8206
b1d427
+    pkey = api.Object['service'].get_primary_key_from_dn(entry.dn)
b1d427
+    principal = kerberos.Principal(pkey)
b1d427
+    server = api.Command.server_find(principal.hostname)['result']
b1d427
+    if server:
b1d427
+        prefixes = ("host", "cifs", "ldap", "HTTP")
b1d427
+    else:
b1d427
+        prefixes = ("cifs",)
b1d427
+    if principal.service_name in prefixes:
b1d427
+        raise errors.ValidationError(
b1d427
+            name='krbprincipalauthind',
b1d427
+            error=_('authentication indicators not allowed '
b1d427
+                    'in service "%s"' % principal.service_name)
b1d427
+        )
b1d427
+
b1d427
+
b1d427
 def normalize_principal(value):
b1d427
     """
b1d427
     Ensure that the name in the principal is lower-case. The realm is
b1d427
@@ -652,6 +674,7 @@ class service_add(LDAPCreate):
b1d427
                     hostname)
b1d427
 
b1d427
         self.obj.validate_ipakrbauthzdata(entry_attrs)
b1d427
+        validate_auth_indicator(entry_attrs)
b1d427
 
b1d427
         if not options.get('force', False):
b1d427
             # We know the host exists if we've gotten this far but we
b1d427
@@ -846,6 +869,7 @@ class service_mod(LDAPUpdate):
b1d427
         assert isinstance(dn, DN)
b1d427
 
b1d427
         self.obj.validate_ipakrbauthzdata(entry_attrs)
b1d427
+        validate_auth_indicator(entry_attrs)
b1d427
 
b1d427
         # verify certificates
b1d427
         certs = entry_attrs.get('usercertificate') or []
b1d427
-- 
b1d427
2.31.1
b1d427
b1d427
From 28484c3dee225662e41acc691bfe6b1c1cee99c8 Mon Sep 17 00:00:00 2001
b1d427
From: Antonio Torres <antorres@redhat.com>
b1d427
Date: Mon, 8 Mar 2021 18:20:35 +0100
b1d427
Subject: [PATCH] ipatests: ensure auth indicators can't be added to internal
b1d427
 IPA services
b1d427
b1d427
Authentication indicators should not be added to internal IPA services,
b1d427
since this can lead to a broken IPA setup. In case a client with
b1d427
an auth indicator set in its host principal, promoting it to a replica
b1d427
should fail.
b1d427
b1d427
Related: https://pagure.io/freeipa/issue/8206
b1d427
Signed-off-by: Antonio Torres <antorres@redhat.com>
b1d427
---
b1d427
 .../test_replica_promotion.py                 | 38 +++++++++++++++++++
b1d427
 ipatests/test_xmlrpc/test_host_plugin.py      | 10 +++++
b1d427
 ipatests/test_xmlrpc/test_service_plugin.py   | 21 ++++++++++
b1d427
 3 files changed, 69 insertions(+)
b1d427
b1d427
diff --git a/ipatests/test_integration/test_replica_promotion.py b/ipatests/test_integration/test_replica_promotion.py
b1d427
index 0a137dbdc..b9c56f775 100644
b1d427
--- a/ipatests/test_integration/test_replica_promotion.py
b1d427
+++ b/ipatests/test_integration/test_replica_promotion.py
b1d427
@@ -101,6 +101,44 @@ class TestReplicaPromotionLevel1(ReplicaPromotionBase):
b1d427
         assert result.returncode == 1
b1d427
         assert expected_err in result.stderr_text
b1d427
 
b1d427
+    @replicas_cleanup
b1d427
+    def test_install_with_host_auth_ind_set(self):
b1d427
+        """ A client shouldn't be able to be promoted if it has
b1d427
+        any auth indicator set in the host principal.
b1d427
+        https://pagure.io/freeipa/issue/8206
b1d427
+        """
b1d427
+
b1d427
+        client = self.replicas[0]
b1d427
+        # Configure firewall first
b1d427
+        Firewall(client).enable_services(["freeipa-ldap",
b1d427
+                                          "freeipa-ldaps"])
b1d427
+
b1d427
+        client.run_command(['ipa-client-install', '-U',
b1d427
+                            '--domain', self.master.domain.name,
b1d427
+                            '--realm', self.master.domain.realm,
b1d427
+                            '-p', 'admin',
b1d427
+                            '-w', self.master.config.admin_password,
b1d427
+                            '--server', self.master.hostname,
b1d427
+                            '--force-join'])
b1d427
+
b1d427
+        tasks.kinit_admin(client)
b1d427
+
b1d427
+        client.run_command(['ipa', 'host-mod', '--auth-ind=otp',
b1d427
+                            client.hostname])
b1d427
+
b1d427
+        res = client.run_command(['ipa-replica-install', '-U', '-w',
b1d427
+                                  self.master.config.dirman_password],
b1d427
+                                 raiseonerr=False)
b1d427
+
b1d427
+        client.run_command(['ipa', 'host-mod', '--auth-ind=',
b1d427
+                            client.hostname])
b1d427
+
b1d427
+        expected_err = ("Client cannot be promoted to a replica if the host "
b1d427
+                        "principal has an authentication indicator set.")
b1d427
+        assert res.returncode == 1
b1d427
+        assert expected_err in res.stderr_text
b1d427
+
b1d427
+
b1d427
     @replicas_cleanup
b1d427
     def test_one_command_installation(self):
b1d427
         """
b1d427
diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
b1d427
index c66bbc865..9cfde3565 100644
b1d427
--- a/ipatests/test_xmlrpc/test_host_plugin.py
b1d427
+++ b/ipatests/test_xmlrpc/test_host_plugin.py
b1d427
@@ -605,6 +605,16 @@ class TestProtectedMaster(XMLRPC_test):
b1d427
                 error=u'An IPA master host cannot be deleted or disabled')):
b1d427
             command()
b1d427
 
b1d427
+    def test_try_add_auth_ind_master(self, this_host):
b1d427
+        command = this_host.make_update_command({
b1d427
+            u'krbprincipalauthind': u'radius'})
b1d427
+        with raises_exact(errors.ValidationError(
b1d427
+            name='krbprincipalauthind',
b1d427
+            error=u'authentication indicators not allowed '
b1d427
+                'in service "host"'
b1d427
+        )):
b1d427
+            command()
b1d427
+
b1d427
 
b1d427
 @pytest.mark.tier1
b1d427
 class TestValidation(XMLRPC_test):
b1d427
diff --git a/ipatests/test_xmlrpc/test_service_plugin.py b/ipatests/test_xmlrpc/test_service_plugin.py
b1d427
index 4c845938c..ed634a045 100644
b1d427
--- a/ipatests/test_xmlrpc/test_service_plugin.py
b1d427
+++ b/ipatests/test_xmlrpc/test_service_plugin.py
b1d427
@@ -25,6 +25,7 @@ from ipalib import api, errors
b1d427
 from ipatests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid, fuzzy_hash
b1d427
 from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_digits, fuzzy_date, fuzzy_issuer
b1d427
 from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_hex, XMLRPC_test
b1d427
+from ipatests.test_xmlrpc.xmlrpc_test import raises_exact
b1d427
 from ipatests.test_xmlrpc import objectclasses
b1d427
 from ipatests.test_xmlrpc.testcert import get_testcert, subject_base
b1d427
 from ipatests.test_xmlrpc.test_user_plugin import get_user_result, get_group_dn
b1d427
@@ -1552,6 +1553,15 @@ def indicators_host(request):
b1d427
     return tracker.make_fixture(request)
b1d427
 
b1d427
 
b1d427
+@pytest.fixture(scope='function')
b1d427
+def this_host(request):
b1d427
+    """Fixture for the current master"""
b1d427
+    tracker = HostTracker(name=api.env.host.partition('.')[0],
b1d427
+                          fqdn=api.env.host)
b1d427
+    tracker.exists = True
b1d427
+    return tracker
b1d427
+
b1d427
+
b1d427
 @pytest.fixture(scope='function')
b1d427
 def indicators_service(request):
b1d427
     tracker = ServiceTracker(
b1d427
@@ -1587,6 +1597,17 @@ class TestAuthenticationIndicators(XMLRPC_test):
b1d427
             expected_updates={u'krbprincipalauthind': [u'radius']}
b1d427
         )
b1d427
 
b1d427
+    def test_update_indicator_internal_service(self, this_host):
b1d427
+        command = this_host.make_command('service_mod',
b1d427
+                                         'ldap/' + this_host.fqdn,
b1d427
+                                         **dict(krbprincipalauthind='otp'))
b1d427
+        with raises_exact(errors.ValidationError(
b1d427
+            name='krbprincipalauthind',
b1d427
+            error=u'authentication indicators not allowed '
b1d427
+                 'in service "ldap"'
b1d427
+        )):
b1d427
+            command()
b1d427
+
b1d427
 
b1d427
 @pytest.fixture(scope='function')
b1d427
 def managing_host(request):
b1d427
-- 
b1d427
2.31.1
b1d427