[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Mon Mar 20 01:26:01 UTC 2023


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 <josephsutton at 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 <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): Mon Mar 20 01:25:07 UTC 2023 on atb-devel-224

commit 2e8e93fdd196f885b1811457e3a6d2d9c5c63f05
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fa901e7346d36ae64a7ceab5dcf76bc210a67c93
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 47ef49fd91f050ce4a79a8471b3e66c808f48752
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ca8b8d1d4af0a2445efef723eaa4160399e87162
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Mar 16 16:47:15 2023 +1300

    s4:kdc: Fix typo
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit dfaae871fd2da8e817601e5c6315b5259b594416
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 218db60ea9254b68a1011cc30248121ee10a8320
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6fd5afd0424404871694fa2b1c87b2e6f56de89b
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit eb74be91bbde618ed32910af0c768c554c72c184
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 19c871bf6e0a0e52674aae3af1080d6295f9f138
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3c5296d9aea38521e6df8834a856d510106300a8
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ed0b850e3dc13dba1f7291d8ed45e93fd1cb9c94
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0f244bd1145f9cd72c930bcf91a8497ba1a26a09
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Tue Mar 7 16:40:37 2023 +1300

    selftest: Clean up socket when finished
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit dfe759c1fd911eb475ed46fe5d66f5cf4eb9055c
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Mar 15 11:31:43 2023 +1300

    selftest: Don't use invalid escape sequences
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 5c8fbeb61e6e5ce99a5b000bfe37a74ff456d449
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fd64bae7b4ea788c3fe8b00d288431bc66dfe104
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1b5c57c305958fcef755dd22753bdd22b613a3ac
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a85d26fd741add9d9f2ea20fdbfb271ab0ceadea
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 223ef8b785068ab7bed1224b1b0ff73bc8f90df7
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e1a573a6595363e05a3baef5ffe625317aaef9de
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9d7594729207fc2a1139d2fa1a3f7a17c8df096f
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ee43e004e9efd594e12acce16b1798d9a4e37eff
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 883d26428486b7b041b327e6d28b551d856059c1
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7a5562f2824f115dbdef777a7c268439f81eff9d
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 04b6f769d160d9d4e0e5bc7a961d473de2e0689b
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a9f127e6e2762872140deec69149f3e91440600a
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3a6e2a283c3985bbcb74b776d6ba597323813bbd
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9a2f6cdc00d3e11498a11dd705807dc18deaac27
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit addfef3d582102805a38d5ad67ad8b11dee1bf04
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 12a1fabd121b2d54d94ed971c3af0c6c3b3d59c7
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f90a46765a008cfaa333159b25661ee83637a5dd
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7e7c692adbce9f82828f0754a3fa79602b84337b
Author: Joseph Sutton <josephsutton at 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 <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at 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



More information about the samba-cvs mailing list