The branch, master has been updated via f1a83798f01 third_party/heimdal: Import lorikeet-heimdal-202402132018 (commit 66d4c120376f60ce0d02f4c23956df8e4d6007f2) via beaeeaff501 s4:rpc_server: Make some arrays static via 3b85345c4c5 lib:util: Fix printing hex‐escaped characters via 7e855f8d89c lib:util: Correctly determine whether a character needs to be escaped via 18208dbef72 s4:rpc_server: Remove trailing whitespace via 4b0f3f3d100 python: Fail the test if we don’t receive an NTSTATUSError via 3e342e2d37a tests/krb5: Move assertLocalSamDB() into RawKerberosTest via df475fbc2f8 tests/krb5: type hinting via 69c3044a726 python/tests: Use TestCaseInTempDir rather than "private dir" for exported keytab via a1d7af24853 python/tests: Convert dckeytab test to use new NDR keytab parser via 2e230f728ec python/tests: Add test for new krb5 keytab parser via e6ef2fc2240 librpc/idl: Check protocol version number in Kerberos ccache parser via ecaaff57e45 librpc/idl: Add a parser for a FILE: format keytab via 9a5cc120421 python/samba/samdb: Only do caching of well known DNs in dbcheck from 5a0fce58650 source4/torture: Add SEC_STD_DELETE to enable proper cleanup
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f1a83798f0102f7d35295a6c0d4db0580a791579 Author: Jo Sutton <josut...@catalyst.net.nz> Date: Wed Feb 14 09:37:13 2024 +1300 third_party/heimdal: Import lorikeet-heimdal-202402132018 (commit 66d4c120376f60ce0d02f4c23956df8e4d6007f2) Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Tue Feb 27 02:19:31 UTC 2024 on atb-devel-224 commit beaeeaff501b22fdfb3928d788597398fcbbbe29 Author: Jo Sutton <josut...@catalyst.net.nz> Date: Tue Feb 20 16:46:07 2024 +1300 s4:rpc_server: Make some arrays static Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3b85345c4c5bc7fa7196c8802a6be60e0e4a043f Author: Jo Sutton <josut...@catalyst.net.nz> Date: Tue Feb 20 16:35:43 2024 +1300 lib:util: Fix printing hex‐escaped characters A signed char, passed to snprintf(), will be promoted to an ‘int’, and then interpreted (according to the format string) as an ‘unsigned int’. Any negative values passed in will thus be interpreted as large unsigned values, too large to be represented in the two characters allocated for them. In practice, they will always be represented as ‘\xFF’. Cast these characters to ‘unsigned char’, and use the appropriate length modifier for that type. Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7e855f8d89cb0b3491d31c93da608417c38c6b00 Author: Jo Sutton <josut...@catalyst.net.nz> Date: Tue Feb 20 16:30:15 2024 +1300 lib:util: Correctly determine whether a character needs to be escaped The condition ‘c > 0x1F’ is clearly meant to test whether a character is a control code or not. While it works for ASCII characters, when ‘char’ is signed it fails for codepoints above 0x7f, which get represented as negative values. Make this calculation work as it was (presumably) intended by casting to ‘unsigned char’. Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 18208dbef721babf21533e5058f388d3b98d372e Author: Jo Sutton <josut...@catalyst.net.nz> Date: Tue Feb 20 14:43:33 2024 +1300 s4:rpc_server: Remove trailing whitespace Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 4b0f3f3d100dcdf5a5bf9947a2baa574af76ad30 Author: Jo Sutton <josut...@catalyst.net.nz> Date: Tue Feb 20 12:27:36 2024 +1300 python: Fail the test if we don’t receive an NTSTATUSError Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3e342e2d37aed612cab59f543dddd3870f5208a6 Author: Jo Sutton <josut...@catalyst.net.nz> Date: Thu Feb 15 13:45:10 2024 +1300 tests/krb5: Move assertLocalSamDB() into RawKerberosTest Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit df475fbc2f8e19e37674ece59cdb8daa0aece072 Author: Jo Sutton <josut...@catalyst.net.nz> Date: Fri Dec 8 14:05:45 2023 +1300 tests/krb5: type hinting Signed-off-by: Jo Sutton <josut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 69c3044a7265c83d053b2690de772eb4ff9d86ca Author: Andrew Bartlett <abart...@samba.org> Date: Wed Feb 21 14:29:44 2024 +1300 python/tests: Use TestCaseInTempDir rather than "private dir" for exported keytab Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit a1d7af2485365b188f1364d6a8388c9cc30e8107 Author: Andrew Bartlett <abart...@samba.org> Date: Wed Feb 21 14:14:24 2024 +1300 python/tests: Convert dckeytab test to use new NDR keytab parser This is much nicer than reading strings out of the binary file. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit 2e230f728ec8026997183ad50ff6371961c9a9ea Author: Andrew Bartlett <abart...@samba.org> Date: Wed Feb 21 10:22:12 2024 +1300 python/tests: Add test for new krb5 keytab parser Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit e6ef2fc22404b91e063edcb9e87e33786d201485 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Feb 27 13:56:50 2024 +1300 librpc/idl: Check protocol version number in Kerberos ccache parser The ccache file format version is checked by the switch in OPTIONAL_HEADER. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit ecaaff57e45bf70754026c54cfba02cd9ca98df1 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Feb 20 20:12:37 2024 +1300 librpc/idl: Add a parser for a FILE: format keytab This will let us examine keytab entries exported for gMSA accounts and ensure they are the values we expect. This will in particular help test our KDC via the "samba-tool domain exportkeytab" as this is a thin wrapper around the relevant code. Additionally, we can use this to test the new client-side keytab generation in "samba-tool domain exportkeytab" for gMSA accounts. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit 9a5cc120421e5d8b60897a9d49e2eef820eff598 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Feb 23 15:32:06 2024 +1300 python/samba/samdb: Only do caching of well known DNs in dbcheck The fact that get_wellknown_dn() returned a cached DN that could not be modified safely was unexpected, particularly given that other similar routines did not do that. The use case given at the time this was written by Matthieu Patou in 6122acad0f1a7bc23b6f58862c16968e13da979d was dbcheck, so move the cache there, and name it clearly. dbcheck is the only case that uses this rotuine in an inner loop. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: lib/util/util_str_escape.c | 6 +- librpc/idl/krb5ccache.idl | 42 +- python/samba/dbchecker.py | 33 +- python/samba/samdb.py | 15 +- python/samba/tests/auth_log_netlogon_bad_creds.py | 4 + python/samba/tests/blackbox/ndrdump.py | 18 + python/samba/tests/dckeytab.py | 43 +- python/samba/tests/krb5/kdc_base_test.py | 14 +- python/samba/tests/krb5/lockout_tests.py | 8 - python/samba/tests/krb5/raw_testcase.py | 8 + source4/librpc/tests/secrets.keytab | Bin 0 -> 827 bytes source4/librpc/tests/secrets.keytab.txt | 67 +++ source4/rpc_server/netlogon/dcerpc_netlogon.c | 65 +-- third_party/heimdal/appl/gssmask/gssmask.c | 2 +- third_party/heimdal/appl/test/Makefile.am | 22 +- third_party/heimdal/appl/test/auditdns.c | 506 +++++++++++++++++++++ third_party/heimdal/cf/make-proto.pl | 4 +- third_party/heimdal/configure.ac | 37 +- third_party/heimdal/kadmin/kadm_conn.c | 11 +- .../heimdal/kdc/altsecid_gss_preauth_authorizer.c | 7 + third_party/heimdal/kdc/hprop.c | 5 + third_party/heimdal/kdc/kdc-tester.c | 4 +- third_party/heimdal/kdc/kdc.8 | 22 +- third_party/heimdal/kdc/kerberos5.c | 3 +- third_party/heimdal/kuser/Makefile.am | 1 + third_party/heimdal/kuser/kinit.c | 4 +- third_party/heimdal/lib/gssapi/Makefile.am | 5 +- third_party/heimdal/lib/hdb/Makefile.am | 5 + third_party/heimdal/lib/hdb/hdb-mitdb.c | 10 +- third_party/heimdal/lib/hdb/hdb.c | 2 +- third_party/heimdal/lib/hx509/req.c | 2 +- third_party/heimdal/lib/kadm5/init_c.c | 5 + third_party/heimdal/lib/kadm5/ipropd_slave.c | 8 +- third_party/heimdal/lib/kadm5/log.c | 2 +- third_party/heimdal/lib/krb5/addr_families.c | 5 + third_party/heimdal/lib/krb5/expand_hostname.c | 3 +- third_party/heimdal/lib/krb5/get_addrs.c | 8 + third_party/heimdal/lib/krb5/get_cred.c | 10 +- third_party/heimdal/lib/krb5/get_for_creds.c | 11 +- third_party/heimdal/lib/krb5/get_host_realm.c | 8 + third_party/heimdal/lib/krb5/init_creds_pw.c | 28 +- third_party/heimdal/lib/krb5/krb5.conf.5 | 25 + third_party/heimdal/lib/krb5/krbhst.c | 31 +- third_party/heimdal/lib/krb5/send_to_kdc.c | 24 +- third_party/heimdal/lib/krb5/sock_principal.c | 8 + third_party/heimdal/lib/krb5/verify_krb5_conf.c | 6 + third_party/heimdal/lib/roken/roken-common.h | 8 + third_party/heimdal/lib/roken/syslogc.c | 2 +- third_party/heimdal/lib/roken/test-mini_inetd.c | 2 +- third_party/heimdal/lib/roken/version-script.map | 1 + third_party/heimdal/tests/bin/setup-env.in | 1 + third_party/heimdal/tests/db/Makefile.am | 2 + third_party/heimdal/tests/db/check-aliases.in | 57 +-- third_party/heimdal/tests/gss/Makefile.am | 18 +- third_party/heimdal/tests/gss/check-basic.in | 32 +- third_party/heimdal/tests/gss/check-context.in | 59 ++- third_party/heimdal/tests/gss/check-gssmask.in | 57 ++- third_party/heimdal/tests/gss/check-negoex.in | 2 - .../tests/gss/{check-basic.in => check-nodns.in} | 39 +- third_party/heimdal/tests/gss/check-ntlm.in | 37 +- third_party/heimdal/tests/gss/check-spnego.in | 37 +- .../tests/gss/{krb5.conf.in => krb5-nodns.conf.in} | 3 +- third_party/heimdal/tests/java/check-kinit.in | 26 +- third_party/heimdal/tests/kdc/Makefile.am | 2 + third_party/heimdal/tests/kdc/check-bx509.in | 9 +- third_party/heimdal/tests/kdc/check-canon.in | 59 +-- third_party/heimdal/tests/kdc/check-cc.in | 30 +- third_party/heimdal/tests/kdc/check-delegation.in | 56 +-- third_party/heimdal/tests/kdc/check-des.in | 42 +- third_party/heimdal/tests/kdc/check-digest.in | 32 +- third_party/heimdal/tests/kdc/check-fast.in | 26 +- third_party/heimdal/tests/kdc/check-hdb-mitdb.in | 12 +- third_party/heimdal/tests/kdc/check-httpkadmind.in | 3 +- third_party/heimdal/tests/kdc/check-iprop.in | 23 +- third_party/heimdal/tests/kdc/check-kadmin.in | 46 +- third_party/heimdal/tests/kdc/check-kdc.in | 331 ++++++-------- third_party/heimdal/tests/kdc/check-keys.in | 14 +- third_party/heimdal/tests/kdc/check-kinit.in | 10 +- third_party/heimdal/tests/kdc/check-kpasswdd.in | 41 +- third_party/heimdal/tests/kdc/check-pkinit.in | 38 +- third_party/heimdal/tests/kdc/check-referral.in | 85 ++-- third_party/heimdal/tests/kdc/check-tester.in | 17 +- third_party/heimdal/tests/kdc/check-uu.in | 26 +- third_party/heimdal/tests/ldap/check-ldap.in | 16 +- third_party/heimdal/tests/plugin/check-pac.in | 9 +- 85 files changed, 1664 insertions(+), 803 deletions(-) create mode 100644 source4/librpc/tests/secrets.keytab create mode 100644 source4/librpc/tests/secrets.keytab.txt create mode 100644 third_party/heimdal/appl/test/auditdns.c copy third_party/heimdal/tests/gss/{check-basic.in => check-nodns.in} (88%) copy third_party/heimdal/tests/gss/{krb5.conf.in => krb5-nodns.conf.in} (97%) Changeset truncated at 500 lines: diff --git a/lib/util/util_str_escape.c b/lib/util/util_str_escape.c index 750d64bfa57..8f1f34912ee 100644 --- a/lib/util/util_str_escape.c +++ b/lib/util/util_str_escape.c @@ -26,7 +26,7 @@ * Calculate the encoded length of a character for log_escape * */ -static size_t encoded_length(char c) +static size_t encoded_length(unsigned char c) { if (c != '\\' && c > 0x1F) { return 1; @@ -79,7 +79,7 @@ char *log_escape(TALLOC_CTX *frame, const char *in) c = in; e = encoded; while (*c) { - if (*c != '\\' && *c > 0x1F) { + if (*c != '\\' && (unsigned char)(*c) > 0x1F) { *e++ = *c++; } else { switch (*c) { @@ -116,7 +116,7 @@ char *log_escape(TALLOC_CTX *frame, const char *in) *e++ = '\\'; break; default: - snprintf(e, 5, "\\x%02X", *c); + snprintf(e, 5, "\\x%02hhX", (unsigned char)(*c)); e += 4; } c++; diff --git a/librpc/idl/krb5ccache.idl b/librpc/idl/krb5ccache.idl index 1f0cfa752a9..f85931cca69 100644 --- a/librpc/idl/krb5ccache.idl +++ b/librpc/idl/krb5ccache.idl @@ -1,6 +1,9 @@ /* krb5 credentials cache (version 3 or 4) specification: https://web.mit.edu/kerberos/krb5-devel/doc/formats/ccache_file_format.html + + krb5 keytab (version 2) + specification: https://web.mit.edu/kerberos/krb5-devel/doc/formats/keytab_file_format.html */ #include "idl_types.h" @@ -100,7 +103,7 @@ interface krb5ccache /* Public structures. */ typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { - [value(5)] uint8 pvno; + [value(5),range(5,5)] uint8 pvno; [value(4)] uint8 version; [switch_is(version)] OPTIONAL_HEADER optional_header; PRINCIPAL principal; @@ -112,4 +115,41 @@ interface krb5ccache CREDENTIAL cred; [flag(NDR_REMAINING)] DATA_BLOB further_creds; } MULTIPLE_CREDENTIALS; + + typedef struct { + uint16 length; + uint8 data[length]; + } KEYTAB_KEYBLOCK; + + typedef struct { + uint16 component_count; + [flag(STR_SIZE2|STR_NOTERM|STR_UTF8)] string realm; + [flag(STR_SIZE2|STR_NOTERM|STR_UTF8)] string components[component_count]; + uint32 name_type; + } KEYTAB_PRINCIPAL; + + typedef struct { + KEYTAB_PRINCIPAL principal; + uint32 timestamp; + uint8 key_version; + uint16 enctype; + KEYTAB_KEYBLOCK key; + uint32 full_key_version; /* We assume modern Heimdal or MIT 1.14 or later */ + } KEYTAB_ENTRY; + + /* + * This parser assumes a fresh keytab without negative lengths + * to indicate holes generated by MIT krb5 1.14 + */ + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + [value(5),range(5,5)] uint8 pvno; + [value(2),range(2,2)] uint8 version; + [subcontext(4)] KEYTAB_ENTRY entry; + [flag(NDR_REMAINING)] DATA_BLOB further_entry; + } KEYTAB; + + typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct { + [subcontext(4)] KEYTAB_ENTRY entry; + [flag(NDR_REMAINING)] DATA_BLOB further_entry; + } MULTIPLE_KEYTAB_ENTRIES; } diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index e07afdc239b..53d0030e941 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -56,6 +56,8 @@ def dump_attr_values(vals): class dbcheck(object): """check a SAM database for errors""" + hash_well_known = {} + def __init__(self, samdb, samdb_schema=None, verbose=False, fix=False, yes=False, quiet=False, in_transaction=False, quick_membership_checks=False, @@ -130,9 +132,9 @@ class dbcheck(object): self.link_id_cache = {} self.name_map = {} try: - base_dn = "CN=DnsAdmins,%s" % samdb.get_wellknown_dn( - samdb.get_default_basedn(), - dsdb.DS_GUID_USERS_CONTAINER) + base_dn = "CN=DnsAdmins,%s" % self.get_wellknown_dn_cached( + samdb.get_default_basedn(), + dsdb.DS_GUID_USERS_CONTAINER) res = samdb.search(base=base_dn, scope=ldb.SCOPE_BASE, attrs=["objectSid"]) dnsadmins_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) @@ -171,8 +173,8 @@ class dbcheck(object): for nc in self.ncs: try: - dn = self.samdb.get_wellknown_dn(ldb.Dn(self.samdb, nc.decode('utf8')), - dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER) + dn = self.get_wellknown_dn_cached(ldb.Dn(self.samdb, nc.decode('utf8')), + dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER) self.deleted_objects_containers.append(dn) except KeyError: self.ncs_lacking_deleted_containers.append(ldb.Dn(self.samdb, nc.decode('utf8'))) @@ -243,6 +245,21 @@ class dbcheck(object): if enum != ldb.ERR_NO_SUCH_OBJECT: raise + def get_wellknown_dn_cached(self, nc_root, wkguid): + h_nc = self.hash_well_known.get(str(nc_root)) + dn = None + if h_nc is not None: + dn = h_nc.get(wkguid) + if dn is None: + dn = self.samdb.get_wellknown_dn(nc_root, wkguid) + if dn is None: + return dn + if h_nc is None: + self.hash_well_known[str(nc_root)] = {} + h_nc = self.hash_well_known[str(nc_root)] + h_nc[wkguid] = dn + return dn + def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=None, attrs=None): """perform a database check, returning the number of errors found""" @@ -945,7 +962,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) self.samdb.transaction_start() try: nc_root = self.samdb.get_nc_root(obj.dn) - lost_and_found = self.samdb.get_wellknown_dn(nc_root, dsdb.DS_GUID_LOSTANDFOUND_CONTAINER) + lost_and_found = self.get_wellknown_dn_cached(nc_root, dsdb.DS_GUID_LOSTANDFOUND_CONTAINER) new_dn = ldb.Dn(self.samdb, str(obj.dn)) new_dn.remove_base_components(len(new_dn) - 1) if self.do_rename(obj.dn, new_dn, lost_and_found, ["show_deleted:0", "relax:0"], @@ -2369,8 +2386,8 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) nc_dn = self.samdb.get_nc_root(obj.dn) try: - deleted_objects_dn = self.samdb.get_wellknown_dn(nc_dn, - samba.dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER) + deleted_objects_dn = self.get_wellknown_dn_cached(nc_dn, + samba.dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER) except KeyError: # We have no deleted objects DN for schema, and we check for this above for the other # NCs diff --git a/python/samba/samdb.py b/python/samba/samdb.py index 9bbec435062..769ae65d9c4 100644 --- a/python/samba/samdb.py +++ b/python/samba/samdb.py @@ -53,7 +53,6 @@ class SamDB(samba.Ldb): """The SAM database.""" hash_oid_name = {} - hash_well_known = {} class _CleanUpOnError: def __init__(self, samdb, dn): @@ -1220,19 +1219,7 @@ schemaUpdateNow: 1 return dsdb._dsdb_get_nc_root(self, dn) def get_wellknown_dn(self, nc_root, wkguid): - h_nc = self.hash_well_known.get(str(nc_root)) - dn = None - if h_nc is not None: - dn = h_nc.get(wkguid) - if dn is None: - dn = dsdb._dsdb_get_wellknown_dn(self, nc_root, wkguid) - if dn is None: - return dn - if h_nc is None: - self.hash_well_known[str(nc_root)] = {} - h_nc = self.hash_well_known[str(nc_root)] - h_nc[wkguid] = dn - return dn + return dsdb._dsdb_get_wellknown_dn(self, nc_root, wkguid) def set_minPwdAge(self, value): if not isinstance(value, bytes): diff --git a/python/samba/tests/auth_log_netlogon_bad_creds.py b/python/samba/tests/auth_log_netlogon_bad_creds.py index e97ca851d11..9894d9bfd03 100644 --- a/python/samba/tests/auth_log_netlogon_bad_creds.py +++ b/python/samba/tests/auth_log_netlogon_bad_creds.py @@ -159,6 +159,8 @@ class AuthLogTestsNetLogonBadCreds(samba.tests.auth_log_base.AuthLogTestBase): 0) except NTSTATUSError: pass + else: + self.fail() self.waitForMessages(isLastExpectedMessage) def test_netlogon_password_HMAC_MD5(self): @@ -187,4 +189,6 @@ class AuthLogTestsNetLogonBadCreds(samba.tests.auth_log_base.AuthLogTestBase): NETLOGON_NEG_STRONG_KEYS) except NTSTATUSError: pass + else: + self.fail() self.waitForMessages(isLastExpectedMessage) diff --git a/python/samba/tests/blackbox/ndrdump.py b/python/samba/tests/blackbox/ndrdump.py index 99aa7c181f2..47aedaa1e00 100644 --- a/python/samba/tests/blackbox/ndrdump.py +++ b/python/samba/tests/blackbox/ndrdump.py @@ -561,3 +561,21 @@ dump OK self.fail(e) self.assertEqual(actual, expected) + + def test_ndrdump_keyetab(self): + with open(self.data_path( + 'secrets.keytab.txt')) as f: + expected = f.read() + data_path = self.data_path( + 'secrets.keytab') + + # We don't do a validate on this as the parser deliberately + # ignores some extra data written by Heimdal, but not MIT. + try: + actual = self.check_output( + 'ndrdump krb5ccache KEYTAB struct ' + + data_path) + except BlackboxProcessError as e: + self.fail(e) + + self.assertEqual(actual, expected.encode('utf-8')) diff --git a/python/samba/tests/dckeytab.py b/python/samba/tests/dckeytab.py index 28ab18614d3..1cc51bdd432 100644 --- a/python/samba/tests/dckeytab.py +++ b/python/samba/tests/dckeytab.py @@ -23,42 +23,43 @@ from samba.net import Net from samba import enable_net_export_keytab from samba import tests +from samba.dcerpc import krb5ccache +from samba.ndr import ndr_unpack from samba.param import LoadParm - +from samba.tests import TestCaseInTempDir enable_net_export_keytab() -def open_bytes(filename): - if sys.version_info[0] == 3: - return open(filename, errors='ignore') - else: - return open(filename, 'rb') - - -class DCKeytabTests(tests.TestCase): +class DCKeytabTests(TestCaseInTempDir): def setUp(self): super().setUp() self.lp = LoadParm() self.lp.load_default() self.creds = self.insta_creds(template=self.get_credentials()) - self.ktfile = os.path.join(self.lp.get('private dir'), 'test.keytab') + self.ktfile = os.path.join(self.tempdir, 'test.keytab') self.principal = self.creds.get_principal() def tearDown(self): super().tearDown() - os.remove(self.ktfile) def test_export_keytab(self): net = Net(None, self.lp) net.export_keytab(keytab=self.ktfile, principal=self.principal) - assert os.path.exists(self.ktfile), 'keytab was not created' - with open_bytes(self.ktfile) as bytes_kt: - result = '' - for c in bytes_kt.read(): - if c in string.printable: - result += c - principal_parts = self.principal.split('@') - assert principal_parts[0] in result and \ - principal_parts[1] in result, \ - 'Principal not found in generated keytab' + self.assertTrue(os.path.exists(self.ktfile), 'keytab was not created') + + # Parse the first entry in the keytab + with open(self.ktfile, 'rb') as bytes_kt: + keytab_bytes = bytes_kt.read() + + self.rm_files('test.keytab') + + keytab = ndr_unpack(krb5ccache.KEYTAB, keytab_bytes) + + # Confirm that the principal is as expected + + principal_parts = self.principal.split('@') + + self.assertEqual(keytab.entry.principal.component_count, 1) + self.assertEqual(keytab.entry.principal.realm, principal_parts[1]) + self.assertEqual(keytab.entry.principal.components[0], principal_parts[0]) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 373c73ecb9a..110a405f9cb 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -30,6 +30,7 @@ from functools import partial import numbers import secrets import tempfile +from typing import Optional from collections import namedtuple import ldb @@ -91,6 +92,7 @@ from samba.join import DCJoinContext from samba.ndr import ndr_pack, ndr_unpack from samba import net from samba.netcmd.domain.models import AuthenticationPolicy, AuthenticationSilo +from samba.param import LoadParm from samba.samdb import SamDB, dsdb_Dn rc4_bit = security.KERB_ENCTYPE_RC4_HMAC_MD5 @@ -356,13 +358,13 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): # current test finishes. self.test_accounts = [] - def get_lp(self): + def get_lp(self) -> LoadParm: if self._lp is None: type(self)._lp = self.get_loadparm() return self._lp - def get_samdb(self): + def get_samdb(self) -> SamDB: if self._ldb is None: creds = self.get_admin_creds() lp = self.get_lp() @@ -375,7 +377,7 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): return self._ldb - def get_rodc_samdb(self): + def get_rodc_samdb(self) -> SamDB: if self._rodc_ldb is None: creds = self.get_admin_creds() lp = self.get_lp() @@ -1967,9 +1969,9 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): return pac def get_cached_creds(self, *, - account_type, - opts=None, - use_cache=True): + account_type: AccountType, + opts: Optional[dict]=None, + use_cache=True) -> KerberosCredentials: if opts is None: opts = {} diff --git a/python/samba/tests/krb5/lockout_tests.py b/python/samba/tests/krb5/lockout_tests.py index d91eb1df79d..584e95ba199 100755 --- a/python/samba/tests/krb5/lockout_tests.py +++ b/python/samba/tests/krb5/lockout_tests.py @@ -584,14 +584,6 @@ class LockoutTests(KDCBaseTest): # Set it temporarily to '0'. samdb.set_minPwdAge('0') - def assertLocalSamDB(self, samdb): - if samdb.url.startswith('tdb://'): - return - if samdb.url.startswith('mdb://'): - return - - self.fail(f'connection to {samdb.url} is not local!') - def wait_for_ready(self, pipe, future): if pipe.poll(timeout=5): return diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 90d286a66be..85daacf88ce 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -1374,6 +1374,14 @@ class RawKerberosTest(TestCase): self.assertCountEqual(expected, got, fail_msg) + def assertLocalSamDB(self, samdb): + if samdb.url.startswith('tdb://'): + return + if samdb.url.startswith('mdb://'): + return + + self.fail(f'connection to {samdb.url} is not local!') + def get_KerberosTimeWithUsec(self, epoch=None, offset=None): if epoch is None: epoch = time.time() diff --git a/source4/librpc/tests/secrets.keytab b/source4/librpc/tests/secrets.keytab new file mode 100644 index 00000000000..f8fd5408b92 Binary files /dev/null and b/source4/librpc/tests/secrets.keytab differ diff --git a/source4/librpc/tests/secrets.keytab.txt b/source4/librpc/tests/secrets.keytab.txt new file mode 100644 index 00000000000..47973acdece --- /dev/null +++ b/source4/librpc/tests/secrets.keytab.txt @@ -0,0 +1,67 @@ +pull returned Success + KEYTAB: struct KEYTAB + pvno : 0x05 (5) + version : 0x02 (2) + entry: struct KEYTAB_ENTRY + principal: struct KEYTAB_PRINCIPAL + component_count : 0x0002 (2) + realm : 'ADDOM.SAMBA.EXAMPLE.COM' + components: ARRAY(2) + components : 'HOST' + components : 'addc' + name_type : 0x00000001 (1) + timestamp : 0x65d3c99c (1708378524) + key_version : 0x01 (1) + enctype : 0x0012 (18) + key: struct KEYTAB_KEYBLOCK + length : 0x0020 (32) + data : acfa2fae41b4c901c50a223dd3722d154f8c380d52a307d68f8de1ba817182da + full_key_version : 0x00000001 (1) + further_entry : DATA_BLOB length=729 +[0000] 00 00 00 74 00 02 00 17 41 44 44 4F 4D 2E 53 41 ...t.... ADDOM.SA +[0010] 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 MBA.EXAM PLE.COM. +[0020] 04 48 4F 53 54 00 1C 61 64 64 63 2E 61 64 64 6F .HOST..a ddc.addo +[0030] 6D 2E 73 61 6D 62 61 2E 65 78 61 6D 70 6C 65 2E m.samba. example. +[0040] 63 6F 6D 00 00 00 01 65 D3 C9 9C 01 00 12 00 20 com....e ....... +[0050] AC FA 2F AE 41 B4 C9 01 C5 0A 22 3D D3 72 2D 15 ../.A... .."=.r-. +[0060] 4F 8C 38 0D 52 A3 07 D6 8F 8D E1 BA 81 71 82 DA O.8.R... .....q.. +[0070] 00 00 00 01 00 00 00 00 00 00 00 57 00 01 00 17 ........ ...W.... +[0080] 41 44 44 4F 4D 2E 53 41 4D 42 41 2E 45 58 41 4D ADDOM.SA MBA.EXAM +[0090] 50 4C 45 2E 43 4F 4D 00 05 41 44 44 43 24 00 00 PLE.COM. .ADDC$.. +[00A0] 00 01 65 D3 C9 9C 01 00 12 00 20 AC FA 2F AE 41 ..e..... .. ../.A +[00B0] B4 C9 01 C5 0A 22 3D D3 72 2D 15 4F 8C 38 0D 52 ....."=. r-.O.8.R +[00C0] A3 07 D6 8F 8D E1 BA 81 71 82 DA 00 00 00 01 00 ........ q....... +[00D0] 00 00 00 00 00 00 4C 00 02 00 17 41 44 44 4F 4D ......L. ...ADDOM +[00E0] 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 .SAMBA.E XAMPLE.C +[00F0] 4F 4D 00 04 48 4F 53 54 00 04 61 64 64 63 00 00 OM..HOST ..addc.. +[0100] 00 01 65 D3 C9 9C 01 00 11 00 10 74 D5 31 8D 99 ..e..... ...t.1.. +[0110] 0A 4C B7 83 0A FC CD 11 4B 59 CF 00 00 00 01 00 .L...... KY...... +[0120] 00 00 00 00 00 00 64 00 02 00 17 41 44 44 4F 4D ......d. ...ADDOM +[0130] 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C 45 2E 43 .SAMBA.E XAMPLE.C +[0140] 4F 4D 00 04 48 4F 53 54 00 1C 61 64 64 63 2E 61 OM..HOST ..addc.a +[0150] 64 64 6F 6D 2E 73 61 6D 62 61 2E 65 78 61 6D 70 ddom.sam ba.examp +[0160] 6C 65 2E 63 6F 6D 00 00 00 01 65 D3 C9 9C 01 00 le.com.. ..e..... +[0170] 11 00 10 74 D5 31 8D 99 0A 4C B7 83 0A FC CD 11 ...t.1.. .L...... +[0180] 4B 59 CF 00 00 00 01 00 00 00 00 00 00 00 47 00 KY...... ......G. +[0190] 01 00 17 41 44 44 4F 4D 2E 53 41 4D 42 41 2E 45 ...ADDOM .SAMBA.E +[01A0] 58 41 4D 50 4C 45 2E 43 4F 4D 00 05 41 44 44 43 XAMPLE.C OM..ADDC +[01B0] 24 00 00 00 01 65 D3 C9 9C 01 00 11 00 10 74 D5 $....e.. ......t. +[01C0] 31 8D 99 0A 4C B7 83 0A FC CD 11 4B 59 CF 00 00 1...L... ...KY... +[01D0] 00 01 00 00 00 00 00 00 00 4C 00 02 00 17 41 44 ........ .L....AD +[01E0] 44 4F 4D 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C DOM.SAMB A.EXAMPL +[01F0] 45 2E 43 4F 4D 00 04 48 4F 53 54 00 04 61 64 64 E.COM..H OST..add +[0200] 63 00 00 00 01 65 D3 C9 9C 01 00 17 00 10 CD 71 c....e.. .......q +[0210] BA D5 2E 21 23 B3 D0 0F 9E 8D 89 7B AD 81 00 00 ...!#... ...{.... +[0220] 00 01 00 00 00 00 00 00 00 64 00 02 00 17 41 44 ........ .d....AD +[0230] 44 4F 4D 2E 53 41 4D 42 41 2E 45 58 41 4D 50 4C DOM.SAMB A.EXAMPL +[0240] 45 2E 43 4F 4D 00 04 48 4F 53 54 00 1C 61 64 64 E.COM..H OST..add +[0250] 63 2E 61 64 64 6F 6D 2E 73 61 6D 62 61 2E 65 78 c.addom. samba.ex +[0260] 61 6D 70 6C 65 2E 63 6F 6D 00 00 00 01 65 D3 C9 ample.co m....e.. +[0270] 9C 01 00 17 00 10 CD 71 BA D5 2E 21 23 B3 D0 0F .......q ...!#... +[0280] 9E 8D 89 7B AD 81 00 00 00 01 00 00 00 00 00 00 ...{.... ........ +[0290] 00 47 00 01 00 17 41 44 44 4F 4D 2E 53 41 4D 42 .G....AD DOM.SAMB +[02A0] 41 2E 45 58 41 4D 50 4C 45 2E 43 4F 4D 00 05 41 A.EXAMPL E.COM..A +[02B0] 44 44 43 24 00 00 00 01 65 D3 C9 9C 01 00 17 00 DDC$.... e....... +[02C0] 10 CD 71 BA D5 2E 21 23 B3 D0 0F 9E 8D 89 7B AD ..q...!# ......{. +[02D0] 81 00 00 00 01 00 00 00 00 ........ . +dump OK diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 2c7fecca1a0..729812acfd9 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c -- Samba Shared Repository