The branch, master has been updated via 3e2eb1b0236 s4:kdc: Add client claims blob if it is present via 2e8e93fdd19 s4:kdc: Refactor PAC handling via fa901e7346d s4:kdc: Avoid copying data if not needed via 47ef49fd91f s4:kdc: Don't pass a NULL pointer into krb5_pac_add_buffer() via ca8b8d1d4af s4:kdc: Fix typo via dfaae871fd2 s4:kdc: Make some parameters const via 218db60ea92 s4:kdc: Comment parameter names via 6fd5afd0424 s4:kdc: Replace 'is_untrusted' with 'is_trusted' via eb74be91bbd auth: Clear EXTRA_SIDS flag if no Extra SIDs are present via 19c871bf6e0 dsdb periodic: DNS: Add missing newlines to debug messages via 3c5296d9aea winbindd: Show warning message on tc connection errors too via ed0b850e3dc wafsamba: Remove unused configure check via 0f244bd1145 selftest: Clean up socket when finished via dfe759c1fd9 selftest: Don't use invalid escape sequences via 5c8fbeb61e6 tests/krb5: Test that denied attributes are still issued in claims via fd64bae7b4e tests/krb5: Add functions to fetch the schemaIDGUID of an attribute or class via 1b5c57c3059 tests/krb5: Check that test parameters are not going unseen via a85d26fd741 tests/krb5: Test that claims are generated even if PAC-OPTIONS are not set via 223ef8b7850 tests/krb5: Test that RODC-issued device groups are regenerated via e1a573a6595 tests/krb5: Test that RODC-issued claims are regenerated via 9d759472920 tests/krb5: Add tests for RODC-issued armor tickets via ee43e004e9e tests/krb5: Add tests for constrained delegation with RODC-issued tickets via 883d2642848 tests/krb5: Add remove_client_claims_tgt_from_rodc() via 7a5562f2824 tests/krb5: Let ticket_with_sids() create RODC-issued tickets via 04b6f769d16 tests/krb5: Add signed_by_rodc() via a9f127e6e27 tests/krb5: Move issued_by_rodc() to base class via 3a6e2a283c3 tests/krb5: Fix additional_details account creation caching via 9a2f6cdc00d tests/krb5: Add simple resource-based constrained delegation test via addfef3d582 tests/krb5: Only add AES enctype bits at domain functional level 2008 and above via 12a1fabd121 tests/krb5: Cache drsuapi connection via f90a46765a0 tests/krb5: Generate full ticket signatures with trailing RODC id via 7e7c692adbc python:ndr: Use f-string to format exception message from 795bab56291 lib:ldb: Correctly cast pointers for assert_string_equal()
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 3e2eb1b02366c380f1ca4d112f10e2663c1b2fef Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Mar 17 09:04:51 2023 +1300 s4:kdc: Add client claims blob if it is present Until we support claims we just return an empty blob, that matches what Windows is doing without defined claims. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Mon Mar 20 01:25:07 UTC 2023 on atb-devel-224 commit 2e8e93fdd196f885b1811457e3a6d2d9c5c63f05 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Mar 17 08:02:24 2023 +1300 s4:kdc: Refactor PAC handling It's getting unwieldy adding new PAC buffer types when each one has to have its own handling. It also makes the possibility of mistakes more likely. Add a new container, 'struct pac_blobs', containing the types of PAC buffers in a given PAC, with an index for quick access to the types we support specifically. We can add new blobs (overriding existing ones) by calling pac_blobs_add_blob(), and override certain blobs that must be present with pac_blobs_replace_existing(). This removes the need to have a complicated 'switch' statement with different logic for each PAC buffer type, or a dozen index variables. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit fa901e7346d36ae64a7ceab5dcf76bc210a67c93 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Mar 17 09:16:17 2023 +1300 s4:kdc: Avoid copying data if not needed krb5_pac_add_buffer() makes its own copy of the data we pass in. We don't need to make yet another copy. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 47ef49fd91f050ce4a79a8471b3e66c808f48752 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Mar 17 09:25:52 2023 +1300 s4:kdc: Don't pass a NULL pointer into krb5_pac_add_buffer() Heimdal contains an assertion that the data pointer is not NULL. We need to pass in a pointer to some dummy data instead. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ca8b8d1d4af0a2445efef723eaa4160399e87162 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 16:47:15 2023 +1300 s4:kdc: Fix typo Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit dfaae871fd2da8e817601e5c6315b5259b594416 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Mar 17 08:07:52 2023 +1300 s4:kdc: Make some parameters const As these parameters are not assigned to, make them const. Const specifiers for non-pointer types, such as in 'const krb5_principal', don't do anything in function declarations. Remove them. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 218db60ea9254b68a1011cc30248121ee10a8320 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 16:07:35 2023 +1300 s4:kdc: Comment parameter names Make it clear what these parameters actually are. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6fd5afd0424404871694fa2b1c87b2e6f56de89b Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 14:29:15 2023 +1300 s4:kdc: Replace 'is_untrusted' with 'is_trusted' A double negative is just confusing and prone to error. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit eb74be91bbde618ed32910af0c768c554c72c184 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon Feb 27 15:56:40 2023 +1300 auth: Clear EXTRA_SIDS flag if no Extra SIDs are present Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 19c871bf6e0a0e52674aae3af1080d6295f9f138 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Mar 7 10:38:27 2023 +1300 dsdb periodic: DNS: Add missing newlines to debug messages Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3c5296d9aea38521e6df8834a856d510106300a8 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Mar 7 11:13:41 2023 +1300 winbindd: Show warning message on tc connection errors too Some of these conditions could never be hit. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ed0b850e3dc13dba1f7291d8ed45e93fd1cb9c94 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Nov 2 14:57:03 2022 +1300 wafsamba: Remove unused configure check This check would trigger compiler warnings due to the extra argument passed to eprintf(). HAVE__VA_ARGS__MACRO isn't used anywhere, so we can remove the check. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 0f244bd1145f9cd72c930bcf91a8497ba1a26a09 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Mar 7 16:40:37 2023 +1300 selftest: Clean up socket when finished Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit dfe759c1fd911eb475ed46fe5d66f5cf4eb9055c Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Mar 15 11:31:43 2023 +1300 selftest: Don't use invalid escape sequences Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5c8fbeb61e6e5ce99a5b000bfe37a74ff456d449 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:25:24 2023 +1300 tests/krb5: Test that denied attributes are still issued in claims Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit fd64bae7b4ea788c3fe8b00d288431bc66dfe104 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:27:22 2023 +1300 tests/krb5: Add functions to fetch the schemaIDGUID of an attribute or class Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 1b5c57c305958fcef755dd22753bdd22b613a3ac Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:14:46 2023 +1300 tests/krb5: Check that test parameters are not going unseen Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a85d26fd741add9d9f2ea20fdbfb271ab0ceadea Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:18:49 2023 +1300 tests/krb5: Test that claims are generated even if PAC-OPTIONS are not set Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 223ef8b785068ab7bed1224b1b0ff73bc8f90df7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:30:39 2023 +1300 tests/krb5: Test that RODC-issued device groups are regenerated Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e1a573a6595363e05a3baef5ffe625317aaef9de Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:30:56 2023 +1300 tests/krb5: Test that RODC-issued claims are regenerated Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 9d7594729207fc2a1139d2fa1a3f7a17c8df096f Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:06:19 2023 +1300 tests/krb5: Add tests for RODC-issued armor tickets Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit ee43e004e9efd594e12acce16b1798d9a4e37eff Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:32:49 2023 +1300 tests/krb5: Add tests for constrained delegation with RODC-issued tickets This works as long as both tickets are issued by the same RODC. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 883d26428486b7b041b327e6d28b551d856059c1 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:24:42 2023 +1300 tests/krb5: Add remove_client_claims_tgt_from_rodc() This method removes the PAC_CLIENT_CLAIMS_INFO buffer *and* makes it appear as if a ticket were issued by an RODC. Because that's more efficient than decrypting and modifying the ticket twice. View with 'git show -b'. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7a5562f2824f115dbdef777a7c268439f81eff9d Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:29:37 2023 +1300 tests/krb5: Let ticket_with_sids() create RODC-issued tickets Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 04b6f769d160d9d4e0e5bc7a961d473de2e0689b Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:22:31 2023 +1300 tests/krb5: Add signed_by_rodc() This can be used to modify a service ticket to appear as if it were signed by an RODC krbtgt. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a9f127e6e2762872140deec69149f3e91440600a Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:23:40 2023 +1300 tests/krb5: Move issued_by_rodc() to base class Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3a6e2a283c3985bbcb74b776d6ba597323813bbd Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:13:21 2023 +1300 tests/krb5: Fix additional_details account creation caching In Python, maps are not hashable and hence cannot be used as cache keys. To get around this, we were converting the account details map to a tuple of (key, value) pairs with the following expression: ((k, v) for k, v in details.items()) However, this was actually creating a lazily-evaluated generator object. The hash of this object was based on its address in memory, not on its contents, which meant that account options with the same details could have different hash values if the generators occupied different memory addresses, or (less likely) that account options with different details could hash to the same value if the second generator happened to inhabit the same memory address as the first one. The result was that account caching didn't work as intended. Attempt to fix that by using a frozenset instead of a generator object, and making sure that all our values are tuples (and thus hashable). Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 9a2f6cdc00d3e11498a11dd705807dc18deaac27 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 11:28:04 2023 +1300 tests/krb5: Add simple resource-based constrained delegation test Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit addfef3d582102805a38d5ad67ad8b11dee1bf04 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Mar 16 12:15:46 2023 +1300 tests/krb5: Only add AES enctype bits at domain functional level 2008 and above At lower levels we should not expect these bits to be present. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 12a1fabd121b2d54d94ed971c3af0c6c3b3d59c7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Mar 7 15:28:21 2023 +1300 tests/krb5: Cache drsuapi connection We call get_keys() a lot, and it's more efficient if we aren't creating a new connection for every new account we create. To allow us to maintain a single cached connection, remove the samdb parameter from get_keys() and get_secrets(). No-one was using it anyway. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f90a46765a008cfaa333159b25661ee83637a5dd Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Mar 14 11:53:45 2023 +1300 tests/krb5: Generate full ticket signatures with trailing RODC id This matches the use of make_rodc_zeroed_checksum() in the preceeding loop, and means that RODC-signed service tickets no longer fail to decrypt. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7e7c692adbce9f82828f0754a3fa79602b84337b Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Mar 14 11:50:17 2023 +1300 python:ndr: Use f-string to format exception message If 'object' happened to be a tuple, we would get one of the following errors: TypeError: not enough arguments for format string TypeError: not all arguments converted during string formatting Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: auth/auth_sam_reply.c | 1 + buildtools/wafsamba/wscript | 5 - librpc/idl/krb5pac.idl | 8 + python/samba/ndr.py | 2 +- python/samba/tests/krb5/claims_tests.py | 530 +++++++++++++++-- python/samba/tests/krb5/device_tests.py | 76 ++- python/samba/tests/krb5/fast_tests.py | 44 ++ python/samba/tests/krb5/kdc_base_test.py | 121 +++- python/samba/tests/krb5/kpasswd_tests.py | 13 - python/samba/tests/krb5/nt_hash_tests.py | 1 - python/samba/tests/krb5/protected_users_tests.py | 2 +- python/samba/tests/krb5/raw_testcase.py | 2 +- python/samba/tests/krb5/s4u_tests.py | 54 ++ python/samba/tests/krb5/spn_tests.py | 2 +- selftest/knownfail_heimdal_kdc | 16 + selftest/knownfail_mit_kdc | 17 + selftest/knownfail_mit_kdc_pre_1_20 | 2 + selftest/subunithelper.py | 2 +- selftest/target/dns_hub.py | 1 + source3/winbindd/winbindd_dual_srv.c | 12 +- source4/dsdb/kcc/kcc_periodic.c | 10 +- source4/kdc/mit_samba.c | 26 +- source4/kdc/pac-glue.c | 712 ++++++++++++----------- source4/kdc/pac-glue.h | 26 +- source4/kdc/wdc-samba4.c | 14 +- 25 files changed, 1210 insertions(+), 489 deletions(-) Changeset truncated at 500 lines: diff --git a/auth/auth_sam_reply.c b/auth/auth_sam_reply.c index 2a35723e355..8e0089eb8d1 100644 --- a/auth/auth_sam_reply.c +++ b/auth/auth_sam_reply.c @@ -399,6 +399,7 @@ NTSTATUS auth_convert_user_info_dc_saminfo6(TALLOC_CTX *mem_ctx, if (sam6->sidcount) { sam6->base.user_flags |= NETLOGON_EXTRA_SIDS; } else { + sam6->base.user_flags &= ~NETLOGON_EXTRA_SIDS; TALLOC_FREE(sam6->sids); } diff --git a/buildtools/wafsamba/wscript b/buildtools/wafsamba/wscript index 93af81f1eca..9ee158b1f39 100644 --- a/buildtools/wafsamba/wscript +++ b/buildtools/wafsamba/wscript @@ -710,11 +710,6 @@ struct foo bar = { .y = 'X', .x = 1 }; define="HAVE_VA_COPY", msg="Checking for va_copy") - conf.CHECK_CODE(''' - #define eprintf(...) fprintf(stderr, __VA_ARGS__) - eprintf("bla", "bar") - ''', define='HAVE__VA_ARGS__MACRO') - conf.env.enable_fuzzing = False conf.env.enable_libfuzzer = Options.options.enable_libfuzzer diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl index 57c37656eb6..6655e2ff5b7 100644 --- a/librpc/idl/krb5pac.idl +++ b/librpc/idl/krb5pac.idl @@ -168,8 +168,16 @@ interface krb5pac PAC_TYPE_ATTRIBUTES_INFO = 17, PAC_TYPE_REQUESTER_SID = 18, PAC_TYPE_FULL_CHECKSUM = 19 + /* + * Note! when adding new types, adjust the value of PAC_TYPE_END + * to equal one more than the highest supported type. + */ } PAC_TYPE; + const uint32 PAC_TYPE_BEGIN = 1; + const uint32 PAC_TYPE_END = 20; + const uint32 PAC_TYPE_COUNT = PAC_TYPE_END - PAC_TYPE_BEGIN; + typedef struct { [flag(NDR_REMAINING)] DATA_BLOB remaining; } DATA_BLOB_REM; diff --git a/python/samba/ndr.py b/python/samba/ndr.py index 35b2414e8ae..314e57b7f8e 100644 --- a/python/samba/ndr.py +++ b/python/samba/ndr.py @@ -52,7 +52,7 @@ def ndr_unpack(cls, data, allow_remaining=False): def ndr_print(object): ndr_print = getattr(object, "__ndr_print__", None) if ndr_print is None: - raise TypeError("%r is not a NDR object" % object) + raise TypeError(f"{object} is not a NDR object") return ndr_print() diff --git a/python/samba/tests/krb5/claims_tests.py b/python/samba/tests/krb5/claims_tests.py index 78c78476e0c..5cdd1f4a361 100755 --- a/python/samba/tests/krb5/claims_tests.py +++ b/python/samba/tests/krb5/claims_tests.py @@ -27,6 +27,7 @@ import re import ldb from samba.dcerpc import claims, krb5pac, security +from samba.ndr import ndr_pack from samba.tests import DynamicTestCase, env_get_var_value from samba.tests.krb5 import kcrypto @@ -47,16 +48,19 @@ global_asn1_print = False global_hexdump = False -class UnorderedList(list): +class UnorderedList(tuple): def __eq__(self, other): if not isinstance(other, UnorderedList): raise AssertionError('unexpected comparison attempt') return sorted(self) == sorted(other) + def __hash__(self): + return hash(tuple(sorted(self))) + # Use this to assert that each element of a list belongs to a set() of # acceptable elements. -class OneOf(list): +class OneOf(tuple): def __eq__(self, other): if not isinstance(other, OneOf): raise AssertionError('unexpected comparison attempt') @@ -129,6 +133,7 @@ class ClaimsTests(KDCBaseTest): details = {} mod_msg = ldb.Message() + security_desc = None for claim in all_claims: # Make a copy to avoid modifying the original. @@ -173,6 +178,22 @@ class ClaimsTests(KDCBaseTest): 'conflicting values set for attribute') details[attribute] = transformed_values + readable = claim.pop('readable', True) + if not readable: + if security_desc is None: + security_desc = security.descriptor() + + # Deny all read property access to the attribute. + ace = security.ace() + ace.type = security.SEC_ACE_TYPE_ACCESS_DENIED_OBJECT + ace.access_mask = security.SEC_ADS_READ_PROP + ace.trustee = security.dom_sid(security.SID_WORLD) + ace.object.flags |= security.SEC_ACE_OBJECT_TYPE_PRESENT + ace.object.type = self.get_schema_id_guid_from_attribute( + attribute) + + security_desc.dacl_add(ace) + if expected_values is None: expected_values = values @@ -199,31 +220,48 @@ class ClaimsTests(KDCBaseTest): self.create_claim(claim_id, **claim) - details = ((k, v) for k, v in details.items()) + if security_desc is not None: + self.assertNotIn('nTSecurityDescriptor', details) + details['nTSecurityDescriptor'] = ndr_pack(security_desc) return details, mod_msg, expected_claims, unexpected_claims - def remove_client_claims(self, ticket): - def modify_pac_fn(pac): - pac_buffers = pac.buffers - for pac_buffer in pac_buffers: - if pac_buffer.type == krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO: - pac.num_buffers -= 1 - pac_buffers.remove(pac_buffer) - - break - else: - self.fail('expected client claims in PAC') + def modify_pac_remove_client_claims(self, pac): + pac_buffers = pac.buffers + for pac_buffer in pac_buffers: + if pac_buffer.type == krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO: + pac.num_buffers -= 1 + pac_buffers.remove(pac_buffer) + + break + else: + self.fail('expected client claims in PAC') - pac.buffers = pac_buffers + pac.buffers = pac_buffers - return pac + return pac + def remove_client_claims(self, ticket): return self.modified_ticket( ticket, - modify_pac_fn=modify_pac_fn, + modify_pac_fn=self.modify_pac_remove_client_claims, checksum_keys=self.get_krbtgt_checksum_key()) + def remove_client_claims_tgt_from_rodc(self, ticket): + rodc_krbtgt_creds = self.get_mock_rodc_krbtgt_creds() + rodc_krbtgt_key = self.TicketDecryptionKey_from_creds( + rodc_krbtgt_creds) + + checksum_keys = { + krb5pac.PAC_TYPE_KDC_CHECKSUM: rodc_krbtgt_key + } + + return self.modified_ticket( + ticket, + new_ticket_key=rodc_krbtgt_key, + modify_pac_fn=self.modify_pac_remove_client_claims, + checksum_keys=checksum_keys) + def test_tgs_claims(self): self.run_tgs_test(remove_claims=False, to_krbtgt=False) @@ -242,6 +280,30 @@ class ClaimsTests(KDCBaseTest): def test_delegation_claims_remove_claims(self): self.run_delegation_test(remove_claims=True) + def test_rodc_issued_claims_modify(self): + self.run_rodc_tgs_test(remove_claims=False, delete_claim=False) + + def test_rodc_issued_claims_delete(self): + self.run_rodc_tgs_test(remove_claims=False, delete_claim=True) + + def test_rodc_issued_claims_remove_claims_modify(self): + self.run_rodc_tgs_test(remove_claims=True, delete_claim=False) + + def test_rodc_issued_claims_remove_claims_delete(self): + self.run_rodc_tgs_test(remove_claims=True, delete_claim=True) + + def test_rodc_issued_device_claims_modify(self): + self.run_device_rodc_tgs_test(remove_claims=False, delete_claim=False) + + def test_rodc_issued_device_claims_delete(self): + self.run_device_rodc_tgs_test(remove_claims=False, delete_claim=True) + + def test_rodc_issued_device_claims_remove_claims_modify(self): + self.run_device_rodc_tgs_test(remove_claims=True, delete_claim=False) + + def test_rodc_issued_device_claims_remove_claims_delete(self): + self.run_device_rodc_tgs_test(remove_claims=True, delete_claim=True) + # Create a user account with an applicable claim for the 'middleName' # attribute. After obtaining a TGT, from which we optionally remove the # claims, change the middleName attribute values for the account in the @@ -270,7 +332,7 @@ class ClaimsTests(KDCBaseTest): claim_id: { 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, 'type': claims.CLAIM_TYPE_STRING, - 'values': ['foo'], + 'values': ('foo',), }, } @@ -354,14 +416,14 @@ class ClaimsTests(KDCBaseTest): claim_id: { 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, 'type': claims.CLAIM_TYPE_STRING, - 'values': ['user_old'], + 'values': ('user_old',), }, } expected_claims_mach = { claim_id: { 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, 'type': claims.CLAIM_TYPE_STRING, - 'values': ['mach_old'], + 'values': ('mach_old',), }, } @@ -463,6 +525,234 @@ class ClaimsTests(KDCBaseTest): additional_tickets=additional_tickets) self.check_reply(rep, KRB_TGS_REP) + def run_rodc_tgs_test(self, remove_claims, delete_claim): + samdb = self.get_samdb() + # Create a user account permitted to replicate to the RODC. + user_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + opts={ + # Set the value of the claim attribute. + 'additional_details': (('middleName', 'foo'),), + 'allowed_replication_mock': True, + 'revealed_to_mock_rodc': True, + }, + use_cache=False) + user_dn = user_creds.get_dn() + + # Create a claim that applies to the user. + claim_id = self.get_new_username() + self.create_claim(claim_id, + enabled=True, + attribute='middleName', + single_valued=True, + source_type='AD', + for_classes=['user'], + value_type=claims.CLAIM_TYPE_STRING) + + expected_claims = { + claim_id: { + 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, + 'type': claims.CLAIM_TYPE_STRING, + 'values': ('foo',), + }, + } + + # Get a TGT for the user. + tgt = self.get_tgt(user_creds, expect_pac=True, + expect_client_claims=True, + expected_client_claims=expected_claims) + + # Modify the TGT to be issued by an RODC. Optionally remove the client + # claims. + if remove_claims: + tgt = self.remove_client_claims_tgt_from_rodc(tgt) + else: + tgt = self.issued_by_rodc(tgt) + + # Modify or delete the value of the attribute used for the claim. Modify + # our test expectations accordingly. + msg = ldb.Message(user_dn) + if delete_claim: + msg['middleName'] = ldb.MessageElement([], + ldb.FLAG_MOD_DELETE, + 'middleName') + expected_claims = None + unexpected_claims = {claim_id} + else: + msg['middleName'] = ldb.MessageElement('bar', + ldb.FLAG_MOD_REPLACE, + 'middleName') + expected_claims = { + claim_id: { + 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, + 'type': claims.CLAIM_TYPE_STRING, + 'values': ('bar',), + }, + } + unexpected_claims = None + samdb.modify(msg) + + target_creds = self.get_service_creds() + + # Get a service ticket for the user. The claim value should have + # changed, indicating that the client claims have been regenerated or + # removed, depending on whether the corresponding attribute is still + # present on the account. + self.get_service_ticket( + tgt, target_creds, + expect_pac=True, + # Expect the CLIENT_CLAIMS_INFO PAC buffer. It may be empty. + expect_client_claims=True, + expected_client_claims=expected_claims, + unexpected_client_claims=unexpected_claims) + + def run_device_rodc_tgs_test(self, remove_claims, delete_claim): + samdb = self.get_samdb() + + # Create the user account. + user_creds = self.get_cached_creds( + account_type=self.AccountType.USER) + user_name = user_creds.get_username() + + # Create a machine account permitted to replicate to the RODC. + mach_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + opts={ + # Set the value of the claim attribute. + 'additional_details': (('middleName', 'foo'),), + 'allowed_replication_mock': True, + 'revealed_to_mock_rodc': True, + }, + use_cache=False) + mach_dn = mach_creds.get_dn() + + # Create a claim that applies to the computer. + claim_id = self.get_new_username() + self.create_claim(claim_id, + enabled=True, + attribute='middleName', + single_valued=True, + source_type='AD', + for_classes=['computer'], + value_type=claims.CLAIM_TYPE_STRING) + + expected_claims = { + claim_id: { + 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, + 'type': claims.CLAIM_TYPE_STRING, + 'values': ('foo',), + }, + } + + # Get a TGT for the user. + user_tgt = self.get_tgt(user_creds) + + # Get a TGT for the computer. + mach_tgt = self.get_tgt(mach_creds, expect_pac=True, + expect_client_claims=True, + expected_client_claims=expected_claims) + + # Modify the computer's TGT to be issued by an RODC. Optionally remove + # the client claims. + if remove_claims: + mach_tgt = self.remove_client_claims_tgt_from_rodc(mach_tgt) + else: + mach_tgt = self.issued_by_rodc(mach_tgt) + + # Modify or delete the value of the attribute used for the claim. Modify + # our test expectations accordingly. + msg = ldb.Message(mach_dn) + if delete_claim: + msg['middleName'] = ldb.MessageElement([], + ldb.FLAG_MOD_DELETE, + 'middleName') + expected_claims = None + unexpected_claims = {claim_id} + else: + msg['middleName'] = ldb.MessageElement('bar', + ldb.FLAG_MOD_REPLACE, + 'middleName') + expected_claims = { + claim_id: { + 'source_type': claims.CLAIMS_SOURCE_TYPE_AD, + 'type': claims.CLAIM_TYPE_STRING, + 'values': ('bar',), + }, + } + unexpected_claims = None + samdb.modify(msg) + + subkey = self.RandomKey(user_tgt.session_key.etype) + + armor_subkey = self.RandomKey(subkey.etype) + explicit_armor_key = self.generate_armor_key(armor_subkey, + mach_tgt.session_key) + armor_key = kcrypto.cf2(explicit_armor_key.key, + subkey.key, + b'explicitarmor', + b'tgsarmor') + armor_key = Krb5EncryptionKey(armor_key, None) + + target_creds = self.get_service_creds() + target_name = target_creds.get_username() + if target_name[-1] == '$': + target_name = target_name[:-1] + + sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', target_name]) + srealm = target_creds.get_realm() + + decryption_key = self.TicketDecryptionKey_from_creds( + target_creds) + + target_supported_etypes = target_creds.tgs_supported_enctypes + + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + kdc_options = '0' + pac_options = '1' # claims support + + # Perform a TGS-REQ for the user. The device claim value should have + # changed, indicating that the computer's client claims have been + # regenerated or removed, depending on whether the corresponding + # attribute is still present on the account. + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=user_tgt.crealm, + expected_cname=user_tgt.cname, + expected_srealm=srealm, + expected_sname=sname, + expected_account_name=user_name, + ticket_decryption_key=decryption_key, + generate_fast_fn=self.generate_simple_fast, + generate_fast_armor_fn=self.generate_ap_req, + check_rep_fn=self.generic_check_kdc_rep, + check_kdc_private_fn=self.generic_check_kdc_private, + tgt=user_tgt, + armor_key=armor_key, + armor_tgt=mach_tgt, + armor_subkey=armor_subkey, + pac_options=pac_options, + authenticator_subkey=subkey, + kdc_options=kdc_options, + expect_pac=True, + expected_supported_etypes=target_supported_etypes, + # Expect the DEVICE_CLAIMS_INFO PAC buffer. It may be empty. + expect_device_claims=True, + expected_device_claims=expected_claims, + unexpected_device_claims=unexpected_claims) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=srealm, + sname=sname, + etypes=etypes) + self.check_reply(rep, KRB_TGS_REP) + + @staticmethod + def freeze(m): + return frozenset((k, v) for k, v in m.items()) + @classmethod def setUpDynamicTestCases(cls): FILTER = env_get_var_value('FILTER', allow_missing=True) @@ -498,16 +788,25 @@ class ClaimsTests(KDCBaseTest): self.fail(f'Unknown class "{account_class}"') all_claims = case.pop('claims') - (details, _, + (details, mod_msg, expected_claims, unexpected_claims) = self.setup_claims(all_claims) - creds = self.get_cached_creds(account_type=account_type, - opts={ - 'additional_details': details, - }) + self.assertFalse(mod_msg, + 'mid-test modifications not supported in this test') + creds = self.get_cached_creds( + account_type=account_type, + opts={ -- Samba Shared Repository