From: Joseph Sutton Date: Mon, 6 Nov 2023 22:10:59 +0000 (+1300) Subject: tests/krb5: Add tests for AllowedToAuthenticateTo with SamLogon X-Git-Tag: talloc-2.4.2~818 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=beaec758c9ffed19f00e87cdd317f47c13ef7dd2;p=thirdparty%2Fsamba.git tests/krb5: Add tests for AllowedToAuthenticateTo with SamLogon Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/tests/krb5/conditional_ace_tests.py b/python/samba/tests/krb5/conditional_ace_tests.py index d43e6f9c141..88507cce164 100755 --- a/python/samba/tests/krb5/conditional_ace_tests.py +++ b/python/samba/tests/krb5/conditional_ace_tests.py @@ -31,7 +31,7 @@ from string import Formatter import ldb from samba import dsdb, ntstatus -from samba.dcerpc import claims, krb5pac, security +from samba.dcerpc import claims, krb5pac, netlogon, security from samba.ndr import ndr_pack, ndr_unpack from samba.sd_utils import escaped_claim_id @@ -89,6 +89,11 @@ class ConditionalAceBaseTests(AuthnPolicyBaseTests): cls._mach_creds = self.get_cached_creds( account_type=self.AccountType.COMPUTER) + # Create an account with which to perform SamLogon. + cls._mach_creds_ntlm = self._get_creds( + account_type=self.AccountType.USER, + ntlm=True) + # Create some new groups. group0_name = self.get_new_username() @@ -110,6 +115,13 @@ class ConditionalAceBaseTests(AuthnPolicyBaseTests): account_type=self.AccountType.COMPUTER, opts={'member_of': (group1_dn,)}) + cls._member_of_both_creds_ntlm = self.get_cached_creds( + account_type=self.AccountType.USER, + opts={ + 'member_of': (group0_dn, group1_dn), + 'kerberos_enabled': False, + }) + # Create some authentication silos. cls._unenforced_silo = self.create_authn_silo(enforced=False) cls._enforced_silo = self.create_authn_silo(enforced=True) @@ -135,6 +147,16 @@ class ConditionalAceBaseTests(AuthnPolicyBaseTests): 'msDS-AuthNPolicySiloMembers', expect_attr=False) + cls._member_of_enforced_silo_ntlm = self._get_creds( + account_type=self.AccountType.USER, + assigned_silo=self._enforced_silo, + ntlm=True, + cached=True) + self.add_to_group(str(self._member_of_enforced_silo_ntlm.get_dn()), + self._enforced_silo.dn, + 'msDS-AuthNPolicySiloMembers', + expect_attr=False) + # Create a couple of multi‐valued string claims for testing claim # value comparisons. @@ -5352,6 +5374,213 @@ class TgsReqServicePolicyTests(ConditionalAceBaseTests): client_policy=client_policy) +class SamLogonTests(ConditionalAceBaseTests): + # These tests show that although conditional ACEs work with SamLogon, + # claims do not appear to be used at all. + + def test_samlogon_allowed_to_computer_member_of(self): + # Create an authentication policy that applies to a computer and + # requires that the account should belong to both groups. + allowed = (f'O:SYD:(XA;;CR;;;WD;(Member_of ' + f'{{SID({self._group0_sid}), SID({self._group1_sid})}}))') + policy = self.create_authn_policy(enforced=True, + computer_allowed_to=allowed) + + # Create a computer account with the assigned policy. + target_creds = self._get_creds(account_type=self.AccountType.COMPUTER, + assigned_policy=policy) + + # When the account is a member of both groups, network SamLogon + # succeeds. + self._test_samlogon(creds=self._member_of_both_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonNetworkInformation) + + self.check_samlogon_network_log(self._member_of_both_creds_ntlm, + server_policy=policy) + + # Interactive SamLogon also succeeds. + self._test_samlogon(creds=self._member_of_both_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonInteractiveInformation) + + self.check_samlogon_interactive_log(self._member_of_both_creds_ntlm, + server_policy=policy) + + # When the account is a member of neither group, network SamLogon + # fails. + self._test_samlogon( + creds=self._mach_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonNetworkInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_network_log( + self._mach_creds_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + # Interactive SamLogon also fails. + self._test_samlogon( + creds=self._mach_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonInteractiveInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_interactive_log( + self._mach_creds_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + def test_samlogon_allowed_to_service_member_of(self): + # Create an authentication policy that applies to a managed service and + # requires that the account should belong to both groups. + allowed = (f'O:SYD:(XA;;CR;;;WD;(Member_of ' + f'{{SID({self._group0_sid}), SID({self._group1_sid})}}))') + policy = self.create_authn_policy(enforced=True, + 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) + + # When the account is a member of both groups, network SamLogon + # succeeds. + self._test_samlogon(creds=self._member_of_both_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonNetworkInformation) + + self.check_samlogon_network_log(self._member_of_both_creds_ntlm, + server_policy=policy) + + # Interactive SamLogon also succeeds. + self._test_samlogon(creds=self._member_of_both_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonInteractiveInformation) + + self.check_samlogon_interactive_log(self._member_of_both_creds_ntlm, + server_policy=policy) + + # When the account is a member of neither group, network SamLogon + # fails. + self._test_samlogon( + creds=self._mach_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonNetworkInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_network_log( + self._mach_creds_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + # Interactive SamLogon also fails. + self._test_samlogon( + creds=self._mach_creds_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonInteractiveInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_interactive_log( + self._mach_creds_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + def test_samlogon_allowed_to_computer_silo(self): + # Create an authentication policy that applies to a computer and + # requires that the account belong to the enforced silo. + allowed = (f'O:SYD:(XA;;CR;;;WD;' + f'(@User.ad://ext/AuthenticationSilo == ' + f'"{self._enforced_silo}"))') + policy = self.create_authn_policy(enforced=True, + computer_allowed_to=allowed) + + # Create a computer account with the assigned policy. + target_creds = self._get_creds(account_type=self.AccountType.COMPUTER, + assigned_policy=policy) + + # Even though the account is a member of the silo, its claims are + # ignored, and network SamLogon fails. + self._test_samlogon( + creds=self._member_of_enforced_silo_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonNetworkInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_network_log( + self._member_of_enforced_silo_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + # Interactive SamLogon also fails. + self._test_samlogon( + creds=self._member_of_enforced_silo_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonInteractiveInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_interactive_log( + self._member_of_enforced_silo_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + def test_samlogon_allowed_to_service_silo(self): + # Create an authentication policy that applies to a managed service and + # requires that the account belong to the enforced silo. + allowed = (f'O:SYD:(XA;;CR;;;WD;' + f'(@User.ad://ext/AuthenticationSilo == ' + f'"{self._enforced_silo}"))') + policy = self.create_authn_policy(enforced=True, + 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) + + # Even though the account is a member of the silo, its claims are + # ignored, and network SamLogon fails. + self._test_samlogon( + creds=self._member_of_enforced_silo_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonNetworkInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_network_log( + self._member_of_enforced_silo_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + # Interactive SamLogon also fails. + self._test_samlogon( + creds=self._member_of_enforced_silo_ntlm, + domain_joined_mach_creds=target_creds, + logon_type=netlogon.NetlogonInteractiveInformation, + expect_error=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED) + + self.check_samlogon_interactive_log( + self._member_of_enforced_silo_ntlm, + server_policy=policy, + server_policy_status=ntstatus.NT_STATUS_AUTHENTICATION_FIREWALL_FAILED, + event=AuditEvent.NTLM_SERVER_RESTRICTION, + reason=AuditReason.ACCESS_DENIED) + + if __name__ == '__main__': global_asn1_print = False global_hexdump = False