[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Mar 21 04:20:02 UTC 2024


The branch, master has been updated
       via  4f0ed9b0038 tests/krb5: Add tests for AllowedToAuthenticateTo with an AS-REQ
       via  eac23954156 s4:auth: Update error messages
       via  67af86d2ab8 auth:credentials: Remove unused include
       via  8b86174bd34 auth:credentials: Remove trailing line
       via  67457394e42 tests/krb5: Allow specifying SamDB to use when creating an account
       via  0bc8d1469b8 python:tests: Do not have current_time() and current_nt_time() implicitly include clock skew
       via  96ac8144b43 python: Correct time conversion function name
       via  cd44f8063b2 s4:libnet: Fix code spelling
       via  d8fa0dd62eb python: Type ‘format’ parameter as optional
       via  cd7b0720de7 python: Correctly qualify strptime()
       via  ed5f8af3299 python:tests: Fix code spelling
       via  2f25c23b7bb s4:auth: Allocate strings on shorter‐lived memory context
       via  398a555fc26 python:tests: Simplify expression
       via  86db3056177 python:tests: Use Managed Service Accounts well‐known GUID
       via  55bc523da7d s4:auth: Fix grammar in error message
      from  8f1a80147d8 pidl: add "return ENOTSUP" for int return type in s3 template

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


- Log -----------------------------------------------------------------
commit 4f0ed9b00389fa641a423b88ab5462b32dd7bbca
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue May 2 15:42:24 2023 +1200

    tests/krb5: Add tests for AllowedToAuthenticateTo with an AS-REQ
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15607
    
    Signed-off-by: Jo Sutton <josutton 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 Mar 21 04:19:18 UTC 2024 on atb-devel-224

commit eac2395415616595c6163768baa163a83a3cea5a
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 12 11:08:30 2024 +1300

    s4:auth: Update error messages
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 67af86d2ab8cb1c9f7a253652feb4897389c6e64
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 12 11:08:14 2024 +1300

    auth:credentials: Remove unused include
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8b86174bd3409a651fc4d8c8a5edc55b714502ed
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 12 11:07:56 2024 +1300

    auth:credentials: Remove trailing line
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 67457394e423598af7b8aa654628af9b7ecea5ee
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Fri Mar 8 16:34:49 2024 +1300

    tests/krb5: Allow specifying SamDB to use when creating an account
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0bc8d1469b89ddf4b3f6cd07e0941137e05dff9d
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Mon Mar 4 13:38:10 2024 +1300

    python:tests: Do not have current_time() and current_nt_time() implicitly include clock skew
    
    This is just too error‐prone.
    
    current_gkid() will still continue to return the next GKID if it’s
    within clock skew.
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 96ac8144b4311516bd4acf9be95a86b574f359f4
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Thu Mar 7 17:14:24 2024 +1300

    python: Correct time conversion function name
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cd44f8063b2f7ed6bbcd063e450ec99624308c61
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 5 12:37:11 2024 +1300

    s4:libnet: Fix code spelling
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d8fa0dd62eb158e6f4c2270267421c3a77be6680
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 5 12:32:16 2024 +1300

    python: Type ‘format’ parameter as optional
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cd7b0720de7b85903c5d4dfb74fb66bd29519f1d
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 5 12:31:27 2024 +1300

    python: Correctly qualify strptime()
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ed5f8af3299143e020a72916c37a3d54a71f1ccc
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Mon Mar 4 13:38:29 2024 +1300

    python:tests: Fix code spelling
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2f25c23b7bb4f935e3b9ebf77fa1309de1e2df48
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Thu Mar 14 15:14:55 2024 +1300

    s4:auth: Allocate strings on shorter‐lived memory context
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 398a555fc26b386668c83320ce9898816c717f41
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Wed Mar 13 10:12:33 2024 +1300

    python:tests: Simplify expression
    
    ‘not keytab_bytes’ is shorter and equivalent.
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 86db3056177115a2b443a8b4c6ff8b2b6086d2c8
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 12 16:24:59 2024 +1300

    python:tests: Use Managed Service Accounts well‐known GUID
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 55bc523da7d516a4ed43eafb0f22170ea59d9e32
Author: Jo Sutton <josutton at catalyst.net.nz>
Date:   Tue Mar 12 16:02:45 2024 +1300

    s4:auth: Fix grammar in error message
    
    Signed-off-by: Jo Sutton <josutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 auth/credentials/credentials_gmsa.c           |   2 -
 python/samba/nt_time.py                       |   8 +-
 python/samba/tests/dckeytab.py                |  11 +-
 python/samba/tests/gkdi.py                    |  35 ++-
 python/samba/tests/krb5/authn_policy_tests.py | 372 ++++++++++++++++++++++++++
 python/samba/tests/krb5/kdc_base_test.py      |  12 +-
 selftest/knownfail_mit_kdc                    |   8 +
 source4/auth/kerberos/kerberos_util.c         |   8 +-
 source4/auth/kerberos/srv_keytab.c            |   6 +-
 source4/libnet/libnet_become_dc.c             |  10 +-
 10 files changed, 434 insertions(+), 38 deletions(-)


Changeset truncated at 500 lines:

diff --git a/auth/credentials/credentials_gmsa.c b/auth/credentials/credentials_gmsa.c
index f1c794ba093..86422624f1e 100644
--- a/auth/credentials/credentials_gmsa.c
+++ b/auth/credentials/credentials_gmsa.c
@@ -20,7 +20,6 @@
 */
 
 #include "includes.h"
-#include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
 #include "librpc/gen_ndr/ndr_gmsa.h" /* for struct MANAGEDPASSWORD_BLOB */
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_internal.h"
@@ -127,4 +126,3 @@ NTSTATUS cli_credentials_set_gmsa_passwords(struct cli_credentials *creds,
 	TALLOC_FREE(frame);
 	return NT_STATUS_OK;
 }
-
diff --git a/python/samba/nt_time.py b/python/samba/nt_time.py
index 496dde576b4..ff6903c8e68 100644
--- a/python/samba/nt_time.py
+++ b/python/samba/nt_time.py
@@ -18,7 +18,7 @@
 #
 
 import datetime
-from typing import NewType
+from typing import NewType, Optional
 import re
 
 
@@ -56,7 +56,7 @@ def datetime_from_nt_time(nt_time: NtTime) -> datetime.datetime:
     return NT_EPOCH + time_since_epoch
 
 
-def nt_time_delta_from_datetime(dt: datetime.timedelta) -> NtTimeDelta:
+def nt_time_delta_from_timedelta(dt: datetime.timedelta) -> NtTimeDelta:
     return NtTimeDelta(round(dt.total_seconds() * NT_TICKS_PER_SEC))
 
 
@@ -88,7 +88,7 @@ def nt_time_from_string(s: str) -> NtTime:
             dt = datetime.datetime.now(datetime.timezone.utc)
         elif re.match(r'^\d{14}\.0Z$', s):
             # "20230127223641.0Z"
-            dt = datetime.strptime(s, '%Y%m%d%H%M%S.0Z')
+            dt = datetime.datetime.strptime(s, '%Y%m%d%H%M%S.0Z')
         else:
             dt = datetime.datetime.fromisoformat(s)
     except ValueError:
@@ -107,7 +107,7 @@ def nt_time_from_string(s: str) -> NtTime:
     return nt_time_from_datetime(dt)
 
 
-def string_from_nt_time(nttime: NtTime, format:str=None) -> str:
+def string_from_nt_time(nttime: NtTime, format: Optional[str] = None) -> str:
     """Format an NtTime date as a string.
 
     If format is not provided, an ISO 8601 string is used.
diff --git a/python/samba/tests/dckeytab.py b/python/samba/tests/dckeytab.py
index f87b95d9dc5..978e3753cc7 100644
--- a/python/samba/tests/dckeytab.py
+++ b/python/samba/tests/dckeytab.py
@@ -22,7 +22,7 @@ import string
 from samba.net import Net
 from samba import enable_net_export_keytab
 
-from samba import credentials, ntstatus, NTSTATUSError, tests
+from samba import credentials, dsdb, ntstatus, NTSTATUSError, tests
 from samba.dcerpc import krb5ccache, security
 from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT
 from samba.ndr import ndr_unpack, ndr_pack
@@ -76,7 +76,7 @@ class DCKeytabTests(TestCaseInTempDir):
             keytab_as_set.add(entry_as_tuple)
 
             keytab_bytes = multiple_entry.further_entry
-            if keytab_bytes is None or len(keytab_bytes) == 0:
+            if not keytab_bytes:
                 break
 
         return keytab_as_set
@@ -345,7 +345,10 @@ class DCKeytabTests(TestCaseInTempDir):
         # Create gMSA account
         gmsa_username = "GMSA_K5KeytabTest$"
         gmsa_principal = f"{gmsa_username}@{self.samdb.domain_dns_name().upper()}"
-        gmsa_base_dn = f"CN=Managed Service Accounts,{self.samdb.domain_dn()}"
+        gmsa_base_dn = self.samdb.get_wellknown_dn(
+            self.samdb.get_default_basedn(),
+            dsdb.DS_GUID_MANAGED_SERVICE_ACCOUNTS_CONTAINER,
+        )
         gmsa_user_dn = f"CN={gmsa_username},{gmsa_base_dn}"
 
         msg = self.samdb.search(base="", scope=SCOPE_BASE, attrs=["tokenGroups"])[0]
@@ -430,7 +433,7 @@ class DCKeytabTests(TestCaseInTempDir):
         while True:
             local_keys[local_keytab.entry.enctype] = local_keytab.entry.key.data
             keytab_bytes = local_keytab.further_entry
-            if keytab_bytes is None or len(keytab_bytes) == 0:
+            if not keytab_bytes:
                 break
             local_keytab = ndr_unpack(krb5ccache.MULTIPLE_KEYTAB_ENTRIES, keytab_bytes)
 
diff --git a/python/samba/tests/gkdi.py b/python/samba/tests/gkdi.py
index 30ddd78025a..03ed8d0141e 100644
--- a/python/samba/tests/gkdi.py
+++ b/python/samba/tests/gkdi.py
@@ -91,17 +91,21 @@ class GkdiBaseTest(TestCase):
 
     @staticmethod
     def current_time(offset: Optional[datetime.timedelta] = None) -> datetime.datetime:
-        if offset is None:
-            # Allow for clock skew.
-            offset = timedelta_from_nt_time_delta(MAX_CLOCK_SKEW)
-
         current_time = datetime.datetime.now(tz=datetime.timezone.utc)
-        return current_time + offset
+
+        if offset is not None:
+            current_time += offset
+
+        return current_time
 
     def current_nt_time(self, offset: Optional[datetime.timedelta] = None) -> NtTime:
         return nt_time_from_datetime(self.current_time(offset))
 
     def current_gkid(self, offset: Optional[datetime.timedelta] = None) -> Gkid:
+        if offset is None:
+            # Allow for clock skew.
+            offset = timedelta_from_nt_time_delta(MAX_CLOCK_SKEW)
+
         return Gkid.from_nt_time(self.current_nt_time(offset))
 
     def gkdi_connect(
@@ -515,13 +519,18 @@ class GkdiBaseTest(TestCase):
         # which exists so that the samba-tool tests can borrow that
         # function.
 
-        root_key_guid, root_key_dn = create_root_key(samdb,
-                                                     domain_dn,
-                                                     current_nt_time=self.current_nt_time(),
-                                                     use_start_time=use_start_time,
-                                                     hash_algorithm=hash_algorithm,
-                                                     guid=guid,
-                                                     data=data)
+        root_key_guid, root_key_dn = create_root_key(
+            samdb,
+            domain_dn,
+            current_nt_time=self.current_nt_time(
+                # Allow for clock skew.
+                timedelta_from_nt_time_delta(MAX_CLOCK_SKEW)
+            ),
+            use_start_time=use_start_time,
+            hash_algorithm=hash_algorithm,
+            guid=guid,
+            data=data,
+        )
 
         if guid is not None:
             # A test may request that a root key have a specific GUID so that
@@ -589,7 +598,7 @@ def create_root_key(
     elif isinstance(use_start_time, int):
         use_start_nt_time = use_start_time
     else:
-        raise ValueError("use_start_time should be a datatime or int")
+        raise ValueError("use_start_time should be a datetime or int")
 
     kdf_parameters = None
     if hash_algorithm is not None:
diff --git a/python/samba/tests/krb5/authn_policy_tests.py b/python/samba/tests/krb5/authn_policy_tests.py
index b36fb0a8d38..455ad36d479 100755
--- a/python/samba/tests/krb5/authn_policy_tests.py
+++ b/python/samba/tests/krb5/authn_policy_tests.py
@@ -294,6 +294,115 @@ class AuthnPolicyBaseTests(AuthLogTestBase, KdcTgsBaseTests):
                                      opts=opts,
                                      use_cache=cached)
 
+    def _fast_as_req(self,
+                     client_creds,
+                     target_creds,
+                     armor_tgt,
+                     expected_error=0,
+                     expect_status=None,
+                     expected_status=None,
+                     expected_groups=None,
+                     expect_device_info=None,
+                     expected_device_groups=None,
+                     expect_device_claims=None,
+                     expected_device_claims=None):
+        client_username = client_creds.get_username()
+        client_realm = client_creds.get_realm()
+        client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
+                                                 names=[client_username])
+
+        target_name = target_creds.get_username()
+        target_sname = self.PrincipalName_create(
+            name_type=NT_PRINCIPAL, names=[target_name])
+        target_realm = target_creds.get_realm()
+        target_decryption_key = self.TicketDecryptionKey_from_creds(
+            target_creds)
+        target_etypes = target_creds.tgs_supported_enctypes
+
+        authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
+        armor_key = self.generate_armor_key(authenticator_subkey,
+                                            armor_tgt.session_key)
+
+        preauth_key = self.PasswordKey_from_creds(client_creds,
+                                                  kcrypto.Enctype.AES256)
+
+        client_challenge_key = (
+            self.generate_client_challenge_key(armor_key, preauth_key))
+        fast_padata = [self.get_challenge_pa_data(client_challenge_key)]
+
+        def _generate_fast_padata(kdc_exchange_dict,
+                                  _callback_dict,
+                                  req_body):
+            return list(fast_padata), req_body
+
+        etypes = kcrypto.Enctype.AES256, kcrypto.Enctype.RC4
+
+        if expected_error:
+            check_error_fn = self.generic_check_kdc_error
+            check_rep_fn = None
+        else:
+            check_error_fn = None
+            check_rep_fn = self.generic_check_kdc_rep
+
+        pac_options = '1'  # claims support
+
+        samdb = self.get_samdb()
+        domain_sid_str = samdb.get_domain_sid()
+
+        if expected_groups is not None:
+            expected_groups = self.map_sids(expected_groups, None, domain_sid_str)
+
+        if expected_device_groups is not None:
+            expected_device_groups = self.map_sids(expected_device_groups, None, domain_sid_str)
+
+        kdc_exchange_dict = self.as_exchange_dict(
+            creds=client_creds,
+            expected_crealm=client_realm,
+            expected_cname=client_cname,
+            expected_srealm=target_realm,
+            expected_sname=target_sname,
+            expected_supported_etypes=target_etypes,
+            ticket_decryption_key=target_decryption_key,
+            generate_fast_fn=self.generate_simple_fast,
+            generate_fast_armor_fn=self.generate_ap_req,
+            generate_fast_padata_fn=_generate_fast_padata,
+            fast_armor_type=FX_FAST_ARMOR_AP_REQUEST,
+            check_error_fn=check_error_fn,
+            check_rep_fn=check_rep_fn,
+            check_kdc_private_fn=self.generic_check_kdc_private,
+            expected_error_mode=expected_error,
+            expected_salt=client_creds.get_salt(),
+            expect_status=expect_status,
+            expected_status=expected_status,
+            expected_groups=expected_groups,
+            expect_device_info=expect_device_info,
+            expected_device_domain_sid=domain_sid_str,
+            expected_device_groups=expected_device_groups,
+            expect_device_claims=expect_device_claims,
+            expected_device_claims=expected_device_claims,
+            authenticator_subkey=authenticator_subkey,
+            preauth_key=preauth_key,
+            armor_key=armor_key,
+            armor_tgt=armor_tgt,
+            armor_subkey=authenticator_subkey,
+            kdc_options='0',
+            pac_options=pac_options,
+            # PA-DATA types are not important for these tests.
+            check_patypes=False)
+
+        rep = self._generic_kdc_exchange(
+            kdc_exchange_dict,
+            cname=client_cname,
+            realm=client_realm,
+            sname=target_sname,
+            etypes=etypes)
+        if expected_error:
+            self.check_error_rep(rep, expected_error)
+            return None
+        else:
+            self.check_as_reply(rep)
+            return kdc_exchange_dict['rep_ticket_creds']
+
     @staticmethod
     def audit_type(msg):
         return AuditType(msg['type'])
@@ -6531,6 +6640,269 @@ class AuthnPolicyTests(AuthnPolicyBaseTests):
 
         self.check_tgs_log(client_creds, target_creds, policy=policy)
 
+    def test_authn_policy_allowed_to_computer_allow_as_req(self):
+        # Create a machine account with which to perform FAST.
+        mach_creds = self.get_cached_creds(
+            account_type=self.AccountType.COMPUTER)
+        mach_tgt = self.get_tgt(mach_creds)
+
+        # Create a user account.
+        client_creds = self.get_cached_creds(
+            account_type=self.AccountType.USER)
+
+        # Create an authentication policy that applies to a computer and
+        # explicitly allows the user account to obtain a service ticket.
+        allowed = f'O:SYD:(A;;CR;;;{client_creds.get_sid()})'
+        denied = 'O:SYD:(D;;CR;;;WD)'
+        policy = self.create_authn_policy(enforced=True,
+                                          user_allowed_to=denied,
+                                          computer_allowed_to=allowed,
+                                          service_allowed_to=denied)
+
+        # Create a computer account with the assigned policy.
+        target_creds = self._get_creds(account_type=self.AccountType.COMPUTER,
+                                       assigned_policy=policy)
+
+        # Show that obtaining a service ticket with an AS-REQ is allowed.
+        self._fast_as_req(client_creds, target_creds, mach_tgt)
+
+        self.check_as_log(client_creds,
+                          server_policy=policy)
+
+    def test_authn_policy_allowed_to_computer_deny_as_req(self):
+        # Create a machine account with which to perform FAST.
+        mach_creds = self.get_cached_creds(
+            account_type=self.AccountType.COMPUTER)
+        mach_tgt = self.get_tgt(mach_creds)
+
+        # Create a user account.
+        client_creds = self.get_cached_creds(
+            account_type=self.AccountType.USER)
+
+        # Create an authentication policy that applies to a computer and
+        # explicitly denies the user account to obtain a service ticket.
+        denied = f'O:SYD:(D;;CR;;;{client_creds.get_sid()})'
+        allowed = 'O:SYD:(A;;CR;;;WD)'
+        policy = self.create_authn_policy(enforced=True,
+                                          user_allowed_to=allowed,
+                                          computer_allowed_to=denied,
+                                          service_allowed_to=allowed)
+
+        # Create a computer account with the assigned policy.
+        target_creds = self._get_creds(account_type=self.AccountType.COMPUTER,
+                                       assigned_policy=policy)
+
+        # Show that obtaining a service ticket with an AS-REQ is denied.
+        self._fast_as_req(
+            client_creds, target_creds, mach_tgt,
+            expected_error=KDC_ERR_POLICY,
+            # We aren’t particular about whether or not we get an NTSTATUS.
+            expect_status=None,
+            expected_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED)
+
+        self.check_as_log(
+            client_creds,
+            server_policy=policy,
+            server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED,
+            event=AuditEvent.KERBEROS_SERVER_RESTRICTION,
+            reason=AuditReason.ACCESS_DENIED,
+            status=ntstatus.NT_STATUS_INVALID_WORKSTATION)
+
+    def test_authn_policy_allowed_to_user_allow_as_req(self):
+        # Create a machine account with which to perform FAST.
+        mach_creds = self.get_cached_creds(
+            account_type=self.AccountType.COMPUTER)
+        mach_tgt = self.get_tgt(mach_creds)
+
+        # Create a user account.
+        client_creds = self.get_cached_creds(
+            account_type=self.AccountType.USER)
+
+        # Create an authentication policy that applies to a user and explicitly
+        # allows the user account to obtain a service ticket.
+        allowed = f'O:SYD:(A;;CR;;;{client_creds.get_sid()})'
+        denied = 'O:SYD:(D;;CR;;;WD)'
+        policy = self.create_authn_policy(enforced=True,
+                                          user_allowed_to=allowed,
+                                          computer_allowed_to=denied,
+                                          service_allowed_to=denied)
+
+        # Create a user account with the assigned policy.
+        target_creds = self._get_creds(account_type=self.AccountType.USER,
+                                       assigned_policy=policy,
+                                       spn='host/{account}')
+
+        # Show that obtaining a service ticket with an AS-REQ is allowed.
+        self._fast_as_req(client_creds, target_creds, mach_tgt)
+
+        self.check_as_log(client_creds,
+                          server_policy=policy)
+
+    def test_authn_policy_allowed_to_user_deny_as_req(self):
+        # Create a machine account with which to perform FAST.
+        mach_creds = self.get_cached_creds(
+            account_type=self.AccountType.COMPUTER)
+        mach_tgt = self.get_tgt(mach_creds)
+
+        # Create a user account.
+        client_creds = self.get_cached_creds(
+            account_type=self.AccountType.USER)
+
+        # Create an authentication policy that applies to a user and
+        # explicitly denies the user account to obtain a service ticket.
+        denied = f'O:SYD:(D;;CR;;;{client_creds.get_sid()})'
+        allowed = 'O:SYD:(A;;CR;;;WD)'
+        policy = self.create_authn_policy(enforced=True,
+                                          user_allowed_to=denied,
+                                          computer_allowed_to=allowed,
+                                          service_allowed_to=allowed)
+
+        # Create a user account with the assigned policy.
+        target_creds = self._get_creds(account_type=self.AccountType.USER,
+                                       assigned_policy=policy,
+                                       spn='host/{account}')
+
+        # Show that obtaining a service ticket with an AS-REQ is denied.
+        self._fast_as_req(
+            client_creds, target_creds, mach_tgt,
+            expected_error=KDC_ERR_POLICY,
+            # We aren’t particular about whether or not we get an NTSTATUS.
+            expect_status=None,
+            expected_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED)
+
+        self.check_as_log(
+            client_creds,
+            server_policy=policy,
+            server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED,
+            event=AuditEvent.KERBEROS_SERVER_RESTRICTION,
+            reason=AuditReason.ACCESS_DENIED,
+            status=ntstatus.NT_STATUS_INVALID_WORKSTATION)
+
+    def test_authn_policy_allowed_to_service_allow_as_req(self):
+        # Create a machine account with which to perform FAST.
+        mach_creds = self.get_cached_creds(
+            account_type=self.AccountType.COMPUTER)
+        mach_tgt = self.get_tgt(mach_creds)
+
+        # Create a user account.
+        client_creds = self.get_cached_creds(
+            account_type=self.AccountType.USER)
+
+        # Create an authentication policy that applies to a managed service and
+        # explicitly allows the user account to obtain a service ticket.
+        allowed = f'O:SYD:(A;;CR;;;{client_creds.get_sid()})'
+        denied = 'O:SYD:(D;;CR;;;WD)'
+        policy = self.create_authn_policy(enforced=True,
+                                          user_allowed_to=denied,
+                                          computer_allowed_to=denied,
+                                          service_allowed_to=allowed)
+
+        # Create a managed service account with the assigned policy.
+        target_creds = self._get_creds(
+            account_type=self.AccountType.MANAGED_SERVICE,
+            assigned_policy=policy)
+
+        # Show that obtaining a service ticket with an AS-REQ is allowed.
+        self._fast_as_req(client_creds, target_creds, mach_tgt)
+
+        self.check_as_log(client_creds,
+                          server_policy=policy)
+
+    def test_authn_policy_allowed_to_service_deny_as_req(self):
+        # Create a machine account with which to perform FAST.
+        mach_creds = self.get_cached_creds(
+            account_type=self.AccountType.COMPUTER)
+        mach_tgt = self.get_tgt(mach_creds)
+
+        # Create a user account.
+        client_creds = self.get_cached_creds(
+            account_type=self.AccountType.USER)
+
+        # Create an authentication policy that applies to a managed service and
+        # explicitly denies the user account to obtain a service ticket.
+        denied = f'O:SYD:(D;;CR;;;{client_creds.get_sid()})'
+        allowed = 'O:SYD:(A;;CR;;;WD)'
+        policy = self.create_authn_policy(enforced=True,
+                                          user_allowed_to=allowed,
+                                          computer_allowed_to=allowed,
+                                          service_allowed_to=denied)
+
+        # Create a managed service account with the assigned policy.
+        target_creds = self._get_creds(
+            account_type=self.AccountType.MANAGED_SERVICE,
+            assigned_policy=policy)
+
+        # Show that obtaining a service ticket with an AS-REQ is denied.
+        self._fast_as_req(
+            client_creds, target_creds, mach_tgt,
+            expected_error=KDC_ERR_POLICY,
+            # We aren’t particular about whether or not we get an NTSTATUS.
+            expect_status=None,
+            expected_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED)
+
+        self.check_as_log(
+            client_creds,
+            server_policy=policy,
+            server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED,
+            event=AuditEvent.KERBEROS_SERVER_RESTRICTION,
+            reason=AuditReason.ACCESS_DENIED,
+            status=ntstatus.NT_STATUS_INVALID_WORKSTATION)
+
+    def test_authn_policy_allowed_to_computer_allow_as_req_no_fast(self):
+        # Create a user account.


-- 
Samba Shared Repository



More information about the samba-cvs mailing list