]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
tests/krb5: Add a test for PK-INIT with a revoked certificate
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Mon, 3 Jul 2023 02:31:03 +0000 (14:31 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 19 Jul 2023 01:47:34 +0000 (01:47 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9612

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/krb5/pkinit_tests.py
selftest/knownfail_heimdal_kdc
selftest/knownfail_mit_kdc_1_20
selftest/target/Samba.pm
selftest/target/Samba4.pm

index d7df72962aad9460cb1348081e4f087546df2290..15166499adc5b954b6dac089d339a83a3a79c8f5 100755 (executable)
@@ -40,6 +40,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest
 from samba.tests.krb5.raw_testcase import PkInit
 from samba.tests.krb5.rfc4120_constants import (
     DES_EDE3_CBC,
+    KDC_ERR_CLIENT_NOT_TRUSTED,
     KDC_ERR_ETYPE_NOSUPP,
     KDC_ERR_MODIFIED,
     KDC_ERR_PREAUTH_EXPIRED,
@@ -550,6 +551,40 @@ class PkInitTests(KDCBaseTest):
                          freshness_token=b'',
                          expect_error=KDC_ERR_MODIFIED)
 
+    def test_pkinit_revoked(self):
+        """Test PK-INIT with a revoked certificate."""
+        client_creds = self._get_creds()
+        target_creds = self.get_service_creds()
+
+        ca_cert, ca_private_key = self.get_ca_cert_and_private_key()
+
+        certificate = self.create_certificate(client_creds,
+                                              ca_cert,
+                                              ca_private_key)
+
+        # The initial public-key PK-INIT request should succeed.
+        self._pkinit_req(client_creds, target_creds,
+                         certificate=certificate)
+
+        # The initial Diffie-Hellman PK-INIT request should succeed.
+        self._pkinit_req(client_creds, target_creds,
+                         certificate=certificate,
+                         using_pkinit=PkInit.DIFFIE_HELLMAN)
+
+        # Revoke the client’s certificate.
+        self.revoke_certificate(certificate, ca_cert, ca_private_key)
+
+        # The subsequent public-key PK-INIT request should fail.
+        self._pkinit_req(client_creds, target_creds,
+                         certificate=certificate,
+                         expect_error=KDC_ERR_CLIENT_NOT_TRUSTED)
+
+        # The subsequent Diffie-Hellman PK-INIT request should also fail.
+        self._pkinit_req(client_creds, target_creds,
+                         certificate=certificate,
+                         using_pkinit=PkInit.DIFFIE_HELLMAN,
+                         expect_error=KDC_ERR_CLIENT_NOT_TRUSTED)
+
     def _as_req(self,
                 creds,
                 target_creds,
@@ -851,6 +886,63 @@ class PkInitTests(KDCBaseTest):
 
         return certificate
 
+    def revoke_certificate(self, certificate,
+                           ca_cert,
+                           ca_private_key,
+                           crl_signature=None):
+        if crl_signature is None:
+            crl_signature = hashes.SHA256
+
+        # Read the existing certificate revocation list.
+        crl_path = samba.tests.env_get_var_value('KRB5_CRL_FILE')
+        with open(crl_path, 'rb') as crl_file:
+            crl_data = crl_file.read()
+
+        try:
+            # Get the list of existing revoked certificates.
+            revoked_certs = x509.load_pem_x509_crl(crl_data, default_backend())
+            extensions = revoked_certs.extensions
+        except ValueError:
+            # We couldn’t parse the file. Let’s just create a new CRL from
+            # scratch.
+            revoked_certs = []
+            extensions = []
+
+        # Create a new CRL.
+        builder = x509.CertificateRevocationListBuilder()
+        builder = builder.issuer_name(ca_cert.issuer)
+        builder = builder.last_update(datetime.today())
+        one_day = timedelta(1, 0, 0)
+        builder = builder.next_update(datetime.today() + one_day)
+
+        # Add the existing revoked certificates.
+        for revoked_cert in revoked_certs:
+            builder = builder.add_revoked_certificate(revoked_cert)
+
+        # Add the serial number of the certificate that we’re revoking.
+        revoked_cert = x509.RevokedCertificateBuilder().serial_number(
+            certificate.serial_number
+        ).revocation_date(
+            datetime.today()
+        ).build(default_backend())
+        builder = builder.add_revoked_certificate(revoked_cert)
+
+        # Copy over any extensions from the existing certificate.
+        for extension in extensions:
+            builder = builder.add_extension(extension.value,
+                                            extension.critical)
+
+        # Sign the CRL with the CA’s private key.
+        crl = builder.sign(
+            private_key=ca_private_key, algorithm=crl_signature(),
+            backend=default_backend(),
+        )
+
+        # Write the CRL back out to the file.
+        crl_data = crl.public_bytes(serialization.Encoding.PEM)
+        with open(crl_path, 'wb') as crl_file:
+            crl_file.write(crl_data)
+
     def _pkinit_req(self,
                     creds,
                     target_creds,
index 8c4c7f73ff5a7e3018069936e36f339d6aadaa4e..ba225236c2ef2f6917dd88b98969b94b7b821a71 100644 (file)
@@ -67,6 +67,7 @@
 # PK-INIT tests
 #
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_no_des3.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_revoked.ad_dc
 #
 # Windows 2000 PK-INIT tests
 #
index 14d522416d033abbc4ee4e9dfed9241e157e0ab2..2fcc2ecf0723aa8c7afacb387e71ebfcbe94a306 100644 (file)
@@ -87,6 +87,7 @@
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_no_supported_cms_types.ad_dc
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_no_supported_cms_types_dh.ad_dc
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_rc4.ad_dc
+^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_revoked.ad_dc
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_service.ad_dc
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_service_dh.ad_dc
 ^samba.tests.krb5.pkinit_tests.samba.tests.krb5.pkinit_tests.PkInitTests.test_pkinit_sha256_certificate_signature.ad_dc
index 334665a6ff2c0b2ac070c9003c9c2cb1542b5a58..b959db493cad312a2b2e2bae34d57c2c531ca485 100644 (file)
@@ -196,6 +196,7 @@ sub prepare_keyblobs($)
 
        my $cadir = "$ENV{SRCDIR_ABS}/selftest/manage-ca/CA-samba.example.com";
        my $cacert = "$cadir/Public/CA-samba.example.com-cert.pem";
+       # A file containing a CRL with no revocations.
        my $cacrl_pem = "$cadir/Public/CA-samba.example.com-crl.pem";
        my $dcdnsname = "$ctx->{hostname}.$ctx->{dnsname}";
        my $dcdir = "$cadir/DCs/$dcdnsname";
@@ -382,6 +383,7 @@ sub mk_krb5_conf($$)
        enable-pkinit = true
        pkinit_identity = FILE:$ctx->{tlsdir}/kdc.pem,$ctx->{tlsdir}/key.pem
        pkinit_anchors = FILE:$ctx->{tlsdir}/ca.pem
+       pkinit_revoke = FILE:$ctx->{tlsdir}/crl.pem
 
 ";
                }
@@ -963,6 +965,7 @@ my @exported_envvars = (
        "UNACCEPTABLE_PASSWORD",
        "LOCK_DIR",
        "SMBD_TEST_LOG",
+       "KRB5_CRL_FILE",
 
        # nss_wrapper
        "NSS_WRAPPER_PASSWD",
index 8506dd5c0037eda32149910ef3a8e4978d4614d7..0bd77e906d5a9eb4a5c7804bbda1e319a23b592f 100755 (executable)
@@ -938,6 +938,7 @@ nogroup:x:65534:nobody
                 GID_RFC2307TEST => $gid_rfc2307test,
                 SERVER_ROLE => $ctx->{server_role},
                RESOLV_CONF => $ctx->{resolv_conf},
+               KRB5_CRL_FILE => $crlfile,
        };
 
        if (defined($ctx->{use_resolv_wrapper})) {