Blame SOURCES/0006-fix-iPAddress-cert-issuance-for-1-host-service_rhbz#1846352.patch

91acb2
From 128500198d3782a76616cf1d971d5aeb17e8c1da Mon Sep 17 00:00:00 2001
91acb2
From: Fraser Tweedale <ftweedal@redhat.com>
91acb2
Date: Thu, 11 Jun 2020 22:42:38 +1000
91acb2
Subject: [PATCH] fix iPAddress cert issuance for >1 host/service
91acb2
91acb2
The 'cert_request' command accumulates DNS names from the CSR,
91acb2
before checking that all IP addresses in the CSR are reachable from
91acb2
those DNS names.  Before adding a DNS name to the set, we check that
91acb2
that it corresponds to the FQDN of a known host/service principal
91acb2
(including principal aliases).  When a DNS name maps to a
91acb2
"alternative" principal (i.e.  not the one given via the 'principal'
91acb2
argument), this check was not being performed correctly.
91acb2
Specifically, we were looking for the 'krbprincipalname' field on
91acb2
the RPC response object directly, instead of its 'result' field.
91acb2
91acb2
To resolve the issue, dereference the RPC response to its 'result'
91acb2
field before invoking the '_dns_name_matches_principal' subroutine.
91acb2
91acb2
Fixes: https://pagure.io/freeipa/issue/8368
91acb2
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
91acb2
---
91acb2
 ipaserver/plugins/cert.py                     |  6 +-
91acb2
 .../test_cert_request_ip_address.py           | 62 +++++++++++++++++--
91acb2
 2 files changed, 61 insertions(+), 7 deletions(-)
91acb2
91acb2
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
91acb2
index d353bc3ea..fe7ea34f5 100644
91acb2
--- a/ipaserver/plugins/cert.py
91acb2
+++ b/ipaserver/plugins/cert.py
91acb2
@@ -827,13 +827,13 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
91acb2
                 try:
91acb2
                     if principal_type == HOST:
91acb2
                         alt_principal_obj = api.Command['host_show'](
91acb2
-                            name, all=True)
91acb2
+                            name, all=True)['result']
91acb2
                     elif principal_type == KRBTGT:
91acb2
                         alt_principal = kerberos.Principal(
91acb2
                             (u'host', name), principal.realm)
91acb2
                     elif principal_type == SERVICE:
91acb2
                         alt_principal_obj = api.Command['service_show'](
91acb2
-                            alt_principal, all=True)
91acb2
+                            alt_principal, all=True)['result']
91acb2
                 except errors.NotFound:
91acb2
                     # We don't want to issue any certificates referencing
91acb2
                     # machines we don't know about. Nothing is stored in this
91acb2
@@ -866,7 +866,7 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
91acb2
                         pass
91acb2
 
91acb2
                     # Now check write access and caacl
91acb2
-                    altdn = alt_principal_obj['result']['dn']
91acb2
+                    altdn = alt_principal_obj['dn']
91acb2
                     if not ldap.can_write(altdn, "usercertificate"):
91acb2
                         raise errors.ACIError(info=_(
91acb2
                             "Insufficient privilege to create a certificate "
91acb2
diff --git a/ipatests/test_xmlrpc/test_cert_request_ip_address.py b/ipatests/test_xmlrpc/test_cert_request_ip_address.py
91acb2
index bf4de05bf..c0475d30d 100644
91acb2
--- a/ipatests/test_xmlrpc/test_cert_request_ip_address.py
91acb2
+++ b/ipatests/test_xmlrpc/test_cert_request_ip_address.py
91acb2
@@ -28,10 +28,16 @@ from ipatests.test_xmlrpc.tracker.host_plugin import HostTracker
91acb2
 from ipatests.test_xmlrpc.tracker.user_plugin import UserTracker
91acb2
 from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
91acb2
 
91acb2
-host_fqdn = f'iptest.{api.env.domain}'
91acb2
+host_shortname = 'iptest'
91acb2
+host_fqdn = f'{host_shortname}.{api.env.domain}'
91acb2
 host_princ = f'host/{host_fqdn}'
91acb2
 host_ptr = f'{host_fqdn}.'
91acb2
 
91acb2
+host2_shortname = 'iptest2'
91acb2
+host2_fqdn = f'{host2_shortname}.{api.env.domain}'
91acb2
+host2_princ = f'host/{host2_fqdn}'
91acb2
+host2_ptr = f'{host2_fqdn}.'
91acb2
+
91acb2
 other_fqdn = f'other.{api.env.domain}'
91acb2
 other_ptr = f'{other_fqdn}.'
91acb2
 
91acb2
@@ -39,6 +45,10 @@ ipv4_address = '169.254.0.42'
91acb2
 ipv4_revzone_s = '0.254.169.in-addr.arpa.'
91acb2
 ipv4_revrec_s = '42'
91acb2
 
91acb2
+host2_ipv4_address = '169.254.0.43'
91acb2
+host2_ipv4_revzone_s = '0.254.169.in-addr.arpa.'
91acb2
+host2_ipv4_revrec_s = '43'
91acb2
+
91acb2
 ipv6_address = 'fe80::8f18:bdab:4299:95fa'
91acb2
 ipv6_revzone_s = '0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.'
91acb2
 ipv6_revrec_s = 'a.f.5.9.9.9.2.4.b.a.d.b.8.1.f.8'
91acb2
@@ -46,7 +56,13 @@ ipv6_revrec_s = 'a.f.5.9.9.9.2.4.b.a.d.b.8.1.f.8'
91acb2
 
91acb2
 @pytest.fixture(scope='class')
91acb2
 def host(request, xmlrpc_setup):
91acb2
-    tr = HostTracker('iptest')
91acb2
+    tr = HostTracker(host_shortname)
91acb2
+    return tr.make_fixture(request)
91acb2
+
91acb2
+
91acb2
+@pytest.fixture(scope='class')
91acb2
+def host2(request, xmlrpc_setup):
91acb2
+    tr = HostTracker(host2_shortname)
91acb2
     return tr.make_fixture(request)
91acb2
 
91acb2
 
91acb2
@@ -88,6 +104,12 @@ def ipv6_revzone(host):
91acb2
     yield from _zone_setup(host, ipv6_revzone_s)
91acb2
 
91acb2
 
91acb2
+@pytest.fixture(scope='class')
91acb2
+def host2_ipv4_ptr(host2, ipv4_revzone):
91acb2
+    yield from _record_setup(
91acb2
+        host2, ipv4_revzone, host2_ipv4_revrec_s, ptrrecord=host2_ptr)
91acb2
+
91acb2
+
91acb2
 @pytest.fixture(scope='class')
91acb2
 def ipv4_ptr(host, ipv4_revzone):
91acb2
     yield from _record_setup(
91acb2
@@ -100,16 +122,22 @@ def ipv6_ptr(host, ipv6_revzone):
91acb2
         host, ipv6_revzone, ipv6_revrec_s, ptrrecord=host_ptr)
91acb2
 
91acb2
 
91acb2
+@pytest.fixture(scope='class')
91acb2
+def host2_ipv4_a(host2):
91acb2
+    yield from _record_setup(
91acb2
+        host2, api.env.domain, host2_shortname, arecord=host2_ipv4_address)
91acb2
+
91acb2
+
91acb2
 @pytest.fixture(scope='class')
91acb2
 def ipv4_a(host):
91acb2
     yield from _record_setup(
91acb2
-        host, api.env.domain, 'iptest', arecord=ipv4_address)
91acb2
+        host, api.env.domain, host_shortname, arecord=ipv4_address)
91acb2
 
91acb2
 
91acb2
 @pytest.fixture(scope='class')
91acb2
 def ipv6_aaaa(host):
91acb2
     yield from _record_setup(
91acb2
-        host, api.env.domain, 'iptest', aaaarecord=ipv6_address)
91acb2
+        host, api.env.domain, host_shortname, aaaarecord=ipv6_address)
91acb2
 
91acb2
 
91acb2
 @pytest.fixture(scope='class')
91acb2
@@ -210,6 +238,12 @@ csr_cname2 = csr([
91acb2
     x509.DNSName(f'cname2.{api.env.domain}'),
91acb2
     x509.IPAddress(ipaddress.ip_address(ipv4_address)),
91acb2
 ])
91acb2
+csr_two_dnsname_two_ip = csr([
91acb2
+    x509.DNSName(host_fqdn),
91acb2
+    x509.IPAddress(ipaddress.ip_address(ipv4_address)),
91acb2
+    x509.DNSName(host2_fqdn),
91acb2
+    x509.IPAddress(ipaddress.ip_address(host2_ipv4_address)),
91acb2
+])
91acb2
 
91acb2
 
91acb2
 @pytest.fixture
91acb2
@@ -449,3 +483,23 @@ class TestIPAddressCNAME(XMLRPC_test):
91acb2
     def test_two_levels(self, host, csr_cname2):
91acb2
         with pytest.raises(errors.ValidationError, match=PAT_FWD):
91acb2
             host.run_command('cert_request', csr_cname2, principal=host_princ)
91acb2
+
91acb2
+
91acb2
+@pytest.mark.tier1
91acb2
+class TestTwoHostsTwoIPAddresses(XMLRPC_test):
91acb2
+    """
91acb2
+    Test certificate issuance with CSR containing two hosts
91acb2
+    and two IP addresses (one for each host).
91acb2
+
91acb2
+    """
91acb2
+    def test_host_exists(
91acb2
+        self, host, host2, ipv4_a, ipv4_ptr, host2_ipv4_a, host2_ipv4_ptr,
91acb2
+    ):
91acb2
+        # for convenience, this test also establishes the DNS
91acb2
+        # record fixtures, which have class scope
91acb2
+        host.ensure_exists()
91acb2
+        host2.ensure_exists()
91acb2
+
91acb2
+    def test_issuance(self, host, csr_two_dnsname_two_ip):
91acb2
+        host.run_command(
91acb2
+            'cert_request', csr_two_dnsname_two_ip, principal=host_princ)
91acb2
-- 
91acb2
2.26.2
91acb2