[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu May 18 05:50:02 UTC 2023


The branch, master has been updated
       via  303d2109f63 s4:kdc: Check lifetime of correct ticket
       via  99f31cabf5f third_party/heimdal: Import lorikeet-heimdal-202305172147 (commit dedb12e3db6e3e5b87869e77f1f1d2ee1f0d32a0)
       via  53c47698f01 tests/krb5: Add tests presenting short-lived ticket in various scenarios
       via  9b1bd267f01 tests/krb5: Rename modify_requester_sid_time() to modify_lifetime()
       via  748fa19a26a tests/krb5: Change ‘sid’ parameter into optional ‘requester_sid’ parameter
       via  787b701e68f tests/krb5: Use consistent time between get_KerberosTime() calls
       via  e1109fbfef9 tests/krb5: Move modify_requester_sid_time() to RawKerberosTest
       via  0e176d856fe s4:kdc: Remove manual addition of error data
       via  637fd961bd3 s4:kdc: Add NTSTATUS e-data to KDC reply
       via  90436389b81 third_party/heimdal: Import lorikeet-heimdal-202305170245 (commit 9c903d03c31ec96af79e2723e3ae41890dd83122)
       via  041f70055cf s4:kdc: Add function to attach an NTSTATUS code to a Kerberos request structure
       via  28cffae4b2c s4:kdc: Use more suitable type for final_ret
       via  d211d700ab9 tests/krb5: Set expected_status even if expect_status is not true
       via  4a3f764f7fa tests/krb5: Be less particular about getting NTSTATUS codes for KDC TGS tests
       via  9d3c3f06ab6 tests/krb5: Be less particular about expected status codes for S4U tests
       via  7266924b3d6 s4:kdc: Use talloc_get_type_abort()
      from  6ee5c80ea96 s4:kdc: Add support for constructed claims (for authentication silos)

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 303d2109f637b553c550183e9406b468ee7e2837
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Tue Apr 18 14:28:01 2023 +1200

    s4:kdc: Check lifetime of correct ticket
    
    The ticket returned by kdc_request_get_ticket() is the main TGT
    presented in a TGS-REQ. If we’re verifying a FAST armor ticket or a
    user-to-user ticket, make sure we check the lifetime of that ticket
    instead. To do this we need to pass the appropriate ticket into the
    plugin function.
    
    NOTE: This commit finally works again!
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu May 18 05:49:31 UTC 2023 on atb-devel-224

commit 99f31cabf5fe3ce7afe01148f311f45e4740794e
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 18 09:54:12 2023 +1200

    third_party/heimdal: Import lorikeet-heimdal-202305172147 (commit dedb12e3db6e3e5b87869e77f1f1d2ee1f0d32a0)
    
    NOTE: THIS COMMIT WON’T COMPILE/WORK ON ITS OWN!
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 53c47698f01b9b948cbb565c1cc808d9cfd423f8
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 18 10:59:53 2023 +1200

    tests/krb5: Add tests presenting short-lived ticket in various scenarios
    
    With the Heimdal KDC, we erroneously accept short-lived FAST and
    user-to-user tickets.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9b1bd267f01e49f134663f42329c606f5483a3cb
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 18 11:07:36 2023 +1200

    tests/krb5: Rename modify_requester_sid_time() to modify_lifetime()
    
    ...now that the requester SID parameter is optional.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 748fa19a26ae61888c5951cc0163a214f751589f
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 18 11:05:56 2023 +1200

    tests/krb5: Change ‘sid’ parameter into optional ‘requester_sid’ parameter
    
    This is so callers can modify the lifetime of a ticket without
    necessarily changing the requester SID.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 787b701e68fc031f28045150d2b603e6a15f644e
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 18 11:03:40 2023 +1200

    tests/krb5: Use consistent time between get_KerberosTime() calls
    
    Otherwise get_KerberosTime() calls time.time() itself, the value of
    which can change between calls.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e1109fbfef9ab840b3c6cf1e626fb99de7771cd4
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu May 18 11:01:47 2023 +1200

    tests/krb5: Move modify_requester_sid_time() to RawKerberosTest
    
    We shall make use of it in KdcTgsTests.
    
    Also move add_requester_sid(), which this function depends upon.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0e176d856fea22973efe6db3ebea3b1fce36d87f
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 15:49:09 2023 +1200

    s4:kdc: Remove manual addition of error data
    
    This is now handled by the hdb_samba4_set_ntstatus() call above.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 637fd961bd359c3ca30e21ebae731ead5cfbc673
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 15:47:18 2023 +1200

    s4:kdc: Add NTSTATUS e-data to KDC reply
    
    If an NTSTATUS code has been set in the KDC request structure, encode it
    as KERB-ERROR-DATA and add it to the KDC reply.
    
    hdb_samba4_set_ntstatus() adds the NTSTATUS code to the request
    structure.
    
    hdb_samba4_get_ntstatus() gets that status code back from the request
    structure.
    
    hdb_samba4_set_edata_from_ntstatus() encodes the status code and adds it
    to the reply.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 90436389b8118d6c31e5e307036cc84796e60b1e
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 16:13:40 2023 +1200

    third_party/heimdal: Import lorikeet-heimdal-202305170245 (commit 9c903d03c31ec96af79e2723e3ae41890dd83122)
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 041f70055cf0e14ac3ccd7fb8b4b49c62c9f3014
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Dec 1 15:35:56 2022 +1300

    s4:kdc: Add function to attach an NTSTATUS code to a Kerberos request structure
    
    Our KDC plugin can use this to store NTSTATUS codes that can be added to
    the final KDC reply later.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 28cffae4b2cbb5221a10f20bdef24af487ca22f4
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 15:38:09 2023 +1200

    s4:kdc: Use more suitable type for final_ret
    
    This now matches the return type of the function.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d211d700ab9cb9724d491d08bcf8be4c4f6ffbfd
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 16:43:12 2023 +1200

    tests/krb5: Set expected_status even if expect_status is not true
    
    We might get an NTSTATUS code even if we aren’t explicitly saying that
    we expect one.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 4a3f764f7fa1a9038997302df01fb91af7725e2c
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 16:42:08 2023 +1200

    tests/krb5: Be less particular about getting NTSTATUS codes for KDC TGS tests
    
    Samba currently doesn’t return a status code in these error cases.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9d3c3f06ab62372a9e2f0b43d6b919838a65e8c7
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 15:28:24 2023 +1200

    tests/krb5: Be less particular about expected status codes for S4U tests
    
    Samba doesn’t return a status code for these error cases, so lower our
    expectations of getting them.
    
    We don’t have to add ‘'expect_status': None’ to all these test cases,
    but this makes it clear at a glance that ‘expected_status’ isn’t
    actually being checked, and gives us the opportunity to change this
    aspect of each individual test in the future.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7266924b3d6bdf0b2e915de0dbd82ba978bde4b8
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed May 17 15:05:44 2023 +1200

    s4:kdc: Use talloc_get_type_abort()
    
    We dereference this pointer immediately after this call, so we should be
    sure it is not NULL.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 python/samba/tests/krb5/kdc_tgs_tests.py         |  42 +++++-
 python/samba/tests/krb5/kpasswd_tests.py         |  92 +------------
 python/samba/tests/krb5/lockout_tests.py         |   5 +-
 python/samba/tests/krb5/raw_testcase.py          |  82 ++++++++++++
 python/samba/tests/krb5/s4u_tests.py             |  67 +++++++++-
 selftest/knownfail_heimdal_kdc                   |   8 --
 selftest/knownfail_mit_kdc                       |   9 ++
 source4/kdc/hdb-samba4.c                         | 163 ++++++++++++++++++++++-
 source4/kdc/kdc-glue.h                           |   4 +
 source4/kdc/wdc-samba4.c                         |  50 ++-----
 source4/selftest/tests.py                        |   2 +-
 third_party/heimdal/kdc/fast.c                   |  75 ++++++++---
 third_party/heimdal/kdc/kdc-plugin.c             |   6 +-
 third_party/heimdal/kdc/kdc-plugin.h             |   1 +
 third_party/heimdal/kdc/kerberos5.c              |  39 ++++--
 third_party/heimdal/kdc/krb5tgs.c                |   2 +-
 third_party/heimdal/kdc/libkdc-exports.def       |   1 +
 third_party/heimdal/kdc/process.c                |   2 +
 third_party/heimdal/kdc/version-script.map       |   1 +
 third_party/heimdal/lib/asn1/krb5.asn1           |  15 ++-
 third_party/heimdal/lib/asn1/libasn1-exports.def |   6 +
 third_party/heimdal/lib/base/heimbase-svc.h      |   1 +
 22 files changed, 500 insertions(+), 173 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py
index b0c1394b76e..171623cc5d7 100755
--- a/python/samba/tests/krb5/kdc_tgs_tests.py
+++ b/python/samba/tests/krb5/kdc_tgs_tests.py
@@ -47,6 +47,7 @@ from samba.tests.krb5.rfc4120_constants import (
     KDC_ERR_PREAUTH_REQUIRED,
     KDC_ERR_C_PRINCIPAL_UNKNOWN,
     KDC_ERR_S_PRINCIPAL_UNKNOWN,
+    KDC_ERR_TKT_EXPIRED,
     KDC_ERR_TGT_REVOKED,
     KRB_ERR_TKT_NYV,
     KDC_ERR_WRONG_REALM,
@@ -1623,7 +1624,9 @@ class KdcTgsTests(KdcTgsBaseTests):
         self._run_tgs(tgt, creds, expected_error=(KDC_ERR_GENERIC,
                                            KDC_ERR_BADKEYVER),
                       expect_edata=True,
-                      expect_status=self.expect_nt_status,
+                      # We aren’t particular about whether or not we get an
+                      # NTSTATUS.
+                      expect_status=None,
                       expected_status=ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES)
 
     def test_renew_rc4(self):
@@ -1650,7 +1653,9 @@ class KdcTgsTests(KdcTgsBaseTests):
         self._s4u2self(tgt, creds, expected_error=(KDC_ERR_GENERIC,
                                                    KDC_ERR_BADKEYVER),
                        expect_edata=True,
-                       expect_status=self.expect_nt_status,
+                       # We aren’t particular about whether or not we get an
+                       # NTSTATUS.
+                       expect_status=None,
                        expected_status=ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES)
 
     def test_user2user_rc4(self):
@@ -1664,6 +1669,39 @@ class KdcTgsTests(KdcTgsBaseTests):
         self._fast(tgt, creds, expected_error=KDC_ERR_GENERIC,
                    expect_edata=self.expect_padata_outer)
 
+    # Test with a TGT that has the lifetime of a kpasswd ticket (two minutes).
+    def test_tgs_kpasswd(self):
+        creds = self._get_creds()
+        tgt = self.modify_lifetime(self._get_tgt(creds), lifetime=2 * 60)
+        self._run_tgs(tgt, creds, expected_error=KDC_ERR_TKT_EXPIRED)
+
+    def test_renew_kpasswd(self):
+        creds = self._get_creds()
+        tgt = self._get_tgt(creds, renewable=True)
+        tgt = self.modify_lifetime(tgt, lifetime=2 * 60)
+        self._renew_tgt(tgt, creds, expected_error=KDC_ERR_TKT_EXPIRED)
+
+    def test_validate_kpasswd(self):
+        creds = self._get_creds()
+        tgt = self._get_tgt(creds, invalid=True)
+        tgt = self.modify_lifetime(tgt, lifetime=2 * 60)
+        self._validate_tgt(tgt, creds, expected_error=KDC_ERR_TKT_EXPIRED)
+
+    def test_s4u2self_kpasswd(self):
+        creds = self._get_creds()
+        tgt = self.modify_lifetime(self._get_tgt(creds), lifetime=2 * 60)
+        self._s4u2self(tgt, creds, expected_error=KDC_ERR_TKT_EXPIRED)
+
+    def test_user2user_kpasswd(self):
+        creds = self._get_creds()
+        tgt = self.modify_lifetime(self._get_tgt(creds), lifetime=2 * 60)
+        self._user2user(tgt, creds, expected_error=KDC_ERR_TKT_EXPIRED)
+
+    def test_fast_kpasswd(self):
+        creds = self._get_creds()
+        tgt = self.modify_lifetime(self._get_tgt(creds), lifetime=2 * 60)
+        self._fast(tgt, creds, expected_error=KDC_ERR_TKT_EXPIRED)
+
     # Test user-to-user with incorrect service principal names.
     def test_user2user_matching_sname_host(self):
         creds = self._get_creds()
diff --git a/python/samba/tests/krb5/kpasswd_tests.py b/python/samba/tests/krb5/kpasswd_tests.py
index 9abd925cb80..647ccbffa02 100755
--- a/python/samba/tests/krb5/kpasswd_tests.py
+++ b/python/samba/tests/krb5/kpasswd_tests.py
@@ -25,7 +25,7 @@ os.environ['PYTHONUNBUFFERED'] = '1'
 
 from functools import partial
 
-from samba import generate_random_password, unix2nttime
+from samba import generate_random_password
 from samba.dcerpc import krb5pac, security
 from samba.sd_utils import SDUtils
 
@@ -106,26 +106,6 @@ class KpasswdTests(KDCBaseTest):
 
         return endtime - starttime
 
-    def add_requester_sid(self, pac, sid):
-        pac_buffers = pac.buffers
-
-        buffer_types = [pac_buffer.type for pac_buffer in pac_buffers]
-        self.assertNotIn(krb5pac.PAC_TYPE_REQUESTER_SID, buffer_types)
-
-        requester_sid = krb5pac.PAC_REQUESTER_SID()
-        requester_sid.sid = security.dom_sid(sid)
-
-        requester_sid_buffer = krb5pac.PAC_BUFFER()
-        requester_sid_buffer.type = krb5pac.PAC_TYPE_REQUESTER_SID
-        requester_sid_buffer.info = requester_sid
-
-        pac_buffers.append(requester_sid_buffer)
-
-        pac.buffers = pac_buffers
-        pac.num_buffers += 1
-
-        return pac
-
     # Test setting a password with kpasswd.
     def test_kpasswd_set(self):
         # Create an account for testing.
@@ -641,64 +621,6 @@ class KpasswdTests(KDCBaseTest):
                                expect_error=(KDC_ERR_TGT_REVOKED,
                                              KDC_ERR_TKT_EXPIRED))
 
-    def modify_requester_sid_time(self, ticket, sid, lifetime):
-        # Get the krbtgt key.
-        krbtgt_creds = self.get_krbtgt_creds()
-
-        krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
-        checksum_keys = {
-            krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key,
-        }
-
-        # Set authtime and starttime to an hour in the past, to show that they
-        # do not affect ticket rejection.
-        start_time = self.get_KerberosTime(offset=-60 * 60)
-
-        # Set the endtime of the ticket relative to our current time, so that
-        # the ticket has 'lifetime' seconds remaining to live.
-        end_time = self.get_KerberosTime(offset=lifetime)
-
-        # Modify the times in the ticket.
-        def modify_ticket_times(enc_part):
-            enc_part['authtime'] = start_time
-            if 'starttime' in enc_part:
-                enc_part['starttime'] = start_time
-
-            enc_part['endtime'] = end_time
-
-            return enc_part
-
-        # We have to set the times in both the ticket and the PAC, otherwise
-        # Heimdal will complain.
-        def modify_pac_time(pac):
-            pac_buffers = pac.buffers
-
-            for pac_buffer in pac_buffers:
-                if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME:
-                    logon_time = self.get_EpochFromKerberosTime(start_time)
-                    pac_buffer.info.logon_time = unix2nttime(logon_time)
-                    break
-            else:
-                self.fail('failed to find LOGON_NAME PAC buffer')
-
-            pac.buffers = pac_buffers
-
-            return pac
-
-        # Add a requester SID to show that the KDC will then accept this
-        # kpasswd ticket as if it were a TGT.
-        def modify_pac_fn(pac):
-            pac = self.add_requester_sid(pac, sid=sid)
-            pac = modify_pac_time(pac)
-            return pac
-
-        # Do the actual modification.
-        return self.modified_ticket(ticket,
-                                    new_ticket_key=krbtgt_key,
-                                    modify_fn=modify_ticket_times,
-                                    modify_pac_fn=modify_pac_fn,
-                                    checksum_keys=checksum_keys)
-
     # Ensure we cannot perform a TGS-REQ with a kpasswd ticket containing a
     # requester SID and having a remaining lifetime of two minutes.
     def test_kpasswd_ticket_requester_sid_tgs(self):
@@ -722,9 +644,9 @@ class KpasswdTests(KDCBaseTest):
 
         # Modify the ticket to add a requester SID and give it two minutes to
         # live.
-        ticket = self.modify_requester_sid_time(ticket,
-                                                sid=user_sid,
-                                                lifetime=2 * 60)
+        ticket = self.modify_lifetime(ticket,
+                                      lifetime=2 * 60,
+                                      requester_sid=user_sid)
 
         # Try to use that ticket to get a service ticket.
         service_creds = self.get_service_creds()
@@ -756,9 +678,9 @@ class KpasswdTests(KDCBaseTest):
 
         # Modify the ticket to add a requester SID and give it two minutes and
         # ten seconds to live.
-        ticket = self.modify_requester_sid_time(ticket,
-                                                sid=user_sid,
-                                                lifetime=2 * 60 + 10)
+        ticket = self.modify_lifetime(ticket,
+                                      lifetime=2 * 60 + 10,
+                                      requester_sid=user_sid)
 
         # Try to use that ticket to get a service ticket.
         service_creds = self.get_service_creds()
diff --git a/python/samba/tests/krb5/lockout_tests.py b/python/samba/tests/krb5/lockout_tests.py
index 4140e4f8825..25be0ce36dc 100755
--- a/python/samba/tests/krb5/lockout_tests.py
+++ b/python/samba/tests/krb5/lockout_tests.py
@@ -147,12 +147,13 @@ def connect_kdc(pipe,
             error_code = rep.get('error-code')
             if error_code == KDC_ERR_CLIENT_REVOKED:
                 # The account was locked out.
+                kdc_exchange_dict['expected_status'] = (
+                    ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT)
+
                 if expect_status:
                     # Expect to get a LOCKED_OUT NTSTATUS code.
                     kdc_exchange_dict['expect_edata'] = True
                     kdc_exchange_dict['expect_status'] = True
-                    kdc_exchange_dict['expected_status'] = (
-                        ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT)
 
             elif error_code == KDC_ERR_PREAUTH_FAILED:
                 # Just a wrong password: the account wasn’t locked out. Don’t
diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py
index 4677151e5c0..e9e882334b4 100644
--- a/python/samba/tests/krb5/raw_testcase.py
+++ b/python/samba/tests/krb5/raw_testcase.py
@@ -37,6 +37,7 @@ from pyasn1.codec.ber.encoder import BitStringEncoder
 
 from pyasn1.error import PyAsn1Error
 
+from samba import unix2nttime
 from samba.credentials import Credentials
 from samba.dcerpc import claims, krb5pac, netlogon, samr, security
 from samba.gensec import FEATURE_SEAL
@@ -4954,6 +4955,87 @@ class RawKerberosTest(TestCaseInTempDir):
 
         return krbtgt_sname
 
+    def add_requester_sid(self, pac, sid):
+        pac_buffers = pac.buffers
+
+        buffer_types = [pac_buffer.type for pac_buffer in pac_buffers]
+        self.assertNotIn(krb5pac.PAC_TYPE_REQUESTER_SID, buffer_types)
+
+        requester_sid = krb5pac.PAC_REQUESTER_SID()
+        requester_sid.sid = security.dom_sid(sid)
+
+        requester_sid_buffer = krb5pac.PAC_BUFFER()
+        requester_sid_buffer.type = krb5pac.PAC_TYPE_REQUESTER_SID
+        requester_sid_buffer.info = requester_sid
+
+        pac_buffers.append(requester_sid_buffer)
+
+        pac.buffers = pac_buffers
+        pac.num_buffers += 1
+
+        return pac
+
+    def modify_lifetime(self, ticket, lifetime, requester_sid=None):
+        # Get the krbtgt key.
+        krbtgt_creds = self.get_krbtgt_creds()
+
+        krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
+        checksum_keys = {
+            krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key,
+        }
+
+        current_time = time.time()
+
+        # Set authtime and starttime to an hour in the past, to show that they
+        # do not affect ticket rejection.
+        start_time = self.get_KerberosTime(epoch=current_time, offset=-60 * 60)
+
+        # Set the endtime of the ticket relative to our current time, so that
+        # the ticket has 'lifetime' seconds remaining to live.
+        end_time = self.get_KerberosTime(epoch=current_time, offset=lifetime)
+
+        # Modify the times in the ticket.
+        def modify_ticket_times(enc_part):
+            enc_part['authtime'] = start_time
+            if 'starttime' in enc_part:
+                enc_part['starttime'] = start_time
+
+            enc_part['endtime'] = end_time
+
+            return enc_part
+
+        # We have to set the times in both the ticket and the PAC, otherwise
+        # Heimdal will complain.
+        def modify_pac_time(pac):
+            pac_buffers = pac.buffers
+
+            for pac_buffer in pac_buffers:
+                if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME:
+                    logon_time = self.get_EpochFromKerberosTime(start_time)
+                    pac_buffer.info.logon_time = unix2nttime(logon_time)
+                    break
+            else:
+                self.fail('failed to find LOGON_NAME PAC buffer')
+
+            pac.buffers = pac_buffers
+
+            return pac
+
+        def modify_pac_fn(pac):
+            if requester_sid is not None:
+                # Add a requester SID to show that the KDC will then accept
+                # this kpasswd ticket as if it were a TGT.
+                pac = self.add_requester_sid(pac, sid=requester_sid)
+            pac = modify_pac_time(pac)
+            return pac
+
+        # Do the actual modification.
+        return self.modified_ticket(ticket,
+                                    new_ticket_key=krbtgt_key,
+                                    modify_fn=modify_ticket_times,
+                                    modify_pac_fn=modify_pac_fn,
+                                    checksum_keys=checksum_keys)
+
     def _test_as_exchange(self,
                           cname,
                           realm,
diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py
index fa1d2141fd4..d3e0d6233e4 100755
--- a/python/samba/tests/krb5/s4u_tests.py
+++ b/python/samba/tests/krb5/s4u_tests.py
@@ -267,6 +267,7 @@ class S4UKerberosTests(KDCBaseTest):
             unexpected_flags = krb5_asn1.TicketFlags(unexpected_flags)
 
         expected_error_mode = kdc_dict.pop('expected_error_mode', 0)
+        expect_status = kdc_dict.pop('expect_status', None)
         expected_status = kdc_dict.pop('expected_status', None)
         if expected_error_mode:
             check_error_fn = self.generic_check_kdc_error
@@ -275,6 +276,7 @@ class S4UKerberosTests(KDCBaseTest):
             check_error_fn = None
             check_rep_fn = self.generic_check_kdc_rep
 
+            self.assertIsNone(expect_status)
             self.assertIsNone(expected_status)
 
         kdc_options = kdc_dict.pop('kdc_options', '0')
@@ -303,8 +305,6 @@ class S4UKerberosTests(KDCBaseTest):
 
             return [pa_s4u], req_body
 
-        expect_status = self.expect_nt_status and expected_status is not None
-
         kdc_exchange_dict = self.tgs_exchange_dict(
             expected_crealm=realm,
             expected_cname=client_cname,
@@ -710,6 +710,7 @@ class S4UKerberosTests(KDCBaseTest):
         service2_etypes = service2_creds.tgs_supported_enctypes
 
         expected_error_mode = kdc_dict.pop('expected_error_mode')
+        expect_status = kdc_dict.pop('expect_status', None)
         expected_status = kdc_dict.pop('expected_status', None)
         if expected_error_mode:
             check_error_fn = self.generic_check_kdc_error
@@ -718,6 +719,7 @@ class S4UKerberosTests(KDCBaseTest):
             check_error_fn = None
             check_rep_fn = self.generic_check_kdc_rep
 
+            self.assertIsNone(expect_status)
             self.assertIsNone(expected_status)
 
         expect_edata = kdc_dict.pop('expect_edata', None)
@@ -736,8 +738,6 @@ class S4UKerberosTests(KDCBaseTest):
         transited_service = f'host/{service1_name}@{service1_realm}'
         expected_transited_services.append(transited_service)
 
-        expect_status = self.expect_nt_status and expected_status is not None
-
         kdc_exchange_dict = self.tgs_exchange_dict(
             expected_crealm=client_realm,
             expected_cname=client_cname,
@@ -873,6 +873,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_BADOPTION,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED,
                 'allow_delegation': False
             })
@@ -935,6 +937,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_BADOPTION,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_ACCOUNT_RESTRICTION,
                 'allow_delegation': True,
                 'modify_client_tkt_fn': functools.partial(
@@ -1000,6 +1004,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_BADOPTION,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NOT_FOUND,
                 'allow_rbcd': False,
                 'pac_options': '0001'  # supports RBCD
@@ -1013,6 +1019,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_MODIFIED,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED,
                 'allow_rbcd': True,
                 'pac_options': '0001',  # supports RBCD
@@ -1027,6 +1035,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_MODIFIED,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NO_MATCH,
                 'allow_rbcd': True,
                 'pac_options': '0001',  # supports RBCD
@@ -1058,6 +1068,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_MODIFIED,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED,
                 'allow_rbcd': True,
                 'pac_options': '0001',  # supports RBCD
@@ -1075,6 +1087,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_MODIFIED,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NO_MATCH,
                 'allow_rbcd': True,
                 'pac_options': '0001',  # supports RBCD
@@ -1112,6 +1126,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_BADOPTION,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_ACCOUNT_RESTRICTION,
                 'allow_rbcd': True,
                 'pac_options': '0001',  # supports RBCD
@@ -1127,6 +1143,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_BADOPTION,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED,
                 'allow_rbcd': True,
                 'pac_options': '1'  # does not support RBCD
@@ -1141,6 +1159,8 @@ class S4UKerberosTests(KDCBaseTest):
         self._run_delegation_test(
             {
                 'expected_error_mode': KDC_ERR_BADOPTION,
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NO_MATCH,
                 'allow_rbcd': True,
                 'pac_options': '1',  # does not support RBCD
@@ -1171,6 +1191,8 @@ class S4UKerberosTests(KDCBaseTest):
             {
                 'expected_error_mode': (KDC_ERR_MODIFIED,
                                         KDC_ERR_BAD_INTEGRITY),
+                # We aren’t particular about whether or not we get an NTSTATUS.
+                'expect_status': None,
                 'expected_status': ntstatus.NT_STATUS_NOT_SUPPORTED,
                 'allow_rbcd': True,
                 'pac_options': '0001',  # supports RBCD
@@ -1207,6 +1229,9 @@ class S4UKerberosTests(KDCBaseTest):
                 self._run_delegation_test(
                     {
                         'expected_error_mode': KDC_ERR_GENERIC,
+                        # We aren’t particular about whether or not we get an
+                        # NTSTATUS.
+                        'expect_status': None,
                         'expected_status':
                             ntstatus.NT_STATUS_INSUFFICIENT_RESOURCES,
                         'allow_delegation': True,
@@ -1228,6 +1253,9 @@ class S4UKerberosTests(KDCBaseTest):
                 self._run_delegation_test(
                     {
                         'expected_error_mode': expected_error_mode,
+                        # We aren’t particular about whether or not we get an
+                        # NTSTATUS.
+                        'expect_status': None,
                         'expected_status':
                             ntstatus.NT_STATUS_NOT_SUPPORTED,
                         'allow_rbcd': True,
@@ -1246,6 +1274,9 @@ class S4UKerberosTests(KDCBaseTest):
                 self._run_delegation_test(


-- 
Samba Shared Repository



More information about the samba-cvs mailing list