The branch, master has been updated via 5eeb441b771 dsdb: Allow special chars like "@" in samAccountName when generating the salt via 46039baa813 tests/krb5: Add tests for account salt calculation via 25bdf4c994e tests/krb5: Fix account salt calculation to match Windows via 889476d1754 tests/krb5: Allow specifying the UPN for test accounts via f4785ccfefe tests/krb5: Allow creating machine accounts without a trailing dollar via 7e39994ed34 tests/krb5: Allow specifying prefix or suffix for test account names via a5a6296e57c tests/krb5: Decrease length of test account prefix via 4dc3c68c9a2 selftest/Samba3: replace (winbindd => "yes", skip_wait => 1) with (winbindd => "offline") via d998f7f8df2 selftest/Samba3: remove unused close(USERMAP); calls via 5d8e794551b waf: Allow building with MIT KRB5 >= 1.20 via 459200caba0 selftest: Improve error handling and perl style when setting up users in Samba4.pm via 2c0658d408f selftest: Remove duplicate setup of $base_dn and $ldbmodify via d4a75eead05 pytest: s3_net_join: avoid name clash via 49306f74eb2 selftest: krb5 account creation: clarify account type as an enum via aacb18f9203 pytest: dynamic tests optionally add __doc__ via 6292f0597f2 selftest: Increase account lockout windows to make test more realiable via a169e013e66 pytest/rodc_rwdc: try to avoid race. from 7e961f3f7a8 HEIMDAL:kdc: Fix transit path validation CVE-2017-6594
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 5eeb441b771a1ffe1ba1c69b72e8795f525a58ed Author: Andrew Bartlett <abart...@samba.org> Date: Tue Oct 19 16:01:36 2021 +1300 dsdb: Allow special chars like "@" in samAccountName when generating the salt BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Wed Oct 20 12:54:54 UTC 2021 on sn-devel-184 commit 46039baa81377df10e5b134e4bb064ed246795e4 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Oct 20 12:46:36 2021 +1300 tests/krb5: Add tests for account salt calculation BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 25bdf4c994e4fdb74abbacb1e22237f3f2cc37fe Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Oct 20 12:45:47 2021 +1300 tests/krb5: Fix account salt calculation to match Windows BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 889476d1754f8ce2a41557ed3bf5242c1293584e Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Oct 20 12:45:08 2021 +1300 tests/krb5: Allow specifying the UPN for test accounts BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit f4785ccfefe7c89f84ad847ca3c12f604172b321 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Oct 20 12:44:19 2021 +1300 tests/krb5: Allow creating machine accounts without a trailing dollar BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 7e39994ed341883ac4c8c257220c19dbf70c7bc5 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Oct 20 12:41:39 2021 +1300 tests/krb5: Allow specifying prefix or suffix for test account names BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit a5a6296e57cab2b53617d997c37b4e92d4124cc7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Oct 20 12:39:05 2021 +1300 tests/krb5: Decrease length of test account prefix This allows us more room to test with different account names. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14874 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 4dc3c68c9a28f71888e3d6dd3b1f0bcdb8fa45de Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 5 16:42:00 2021 +0200 selftest/Samba3: replace (winbindd => "yes", skip_wait => 1) with (winbindd => "offline") This is much more flexible and concentrates the logic in a single place. We'll use winbindd => "offline" in other places soon. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14870 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d998f7f8df215866ab32e05be772e24fc0b2131c Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 8 18:04:55 2021 +0200 selftest/Samba3: remove unused close(USERMAP); calls BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5d8e794551b5df835f07e2bd8348fef746144601 Author: Andreas Schneider <a...@samba.org> Date: Mon Oct 4 13:02:35 2021 +0200 waf: Allow building with MIT KRB5 >= 1.20 gssrpc/xdr.h:105:1: error: function declaration isn’t a prototype [-Werror=strict-prototypes] 105 | typedef bool_t (*xdrproc_t)(); | ^~~~~~~ This can't be fixed, as the protoype is variadic. It can take up to three arguments. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14870 Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 459200caba04fd83ed650b9cdfe5b158cf9a149f Author: Andrew Bartlett <abart...@samba.org> Date: Mon Oct 18 11:55:14 2021 +1300 selftest: Improve error handling and perl style when setting up users in Samba4.pm This catches errors and avoids using global varibles (the old style file handles are global). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 2c0658d408f17af2abc223b0cb18d8d33e0ecd1a Author: Andrew Bartlett <abart...@samba.org> Date: Mon Oct 18 20:44:54 2021 +1300 selftest: Remove duplicate setup of $base_dn and $ldbmodify These are already set up to the same values above for the full DC and correct values for the (strange) s4member environment. By not setting $base_dn again we avoid an error once we start checking for them. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit d4a75eead058879b11c8a0901d7277052123d13b Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Aug 20 11:26:02 2021 +1200 pytest: s3_net_join: avoid name clash The net_join test uses "NetJoinTest" (and doesn't properly clean up), we must use a unique name for this test in s3_net_join.py. [abart...@samba.org The hilarious naming conventions come from a time when samba-tool was known as "net" in the s4 branch] BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 49306f74eb29a2192019fab9260f9d242f9d5fd9 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Fri Oct 8 15:40:09 2021 +1300 selftest: krb5 account creation: clarify account type as an enum This makes the code clearer with a symbolic constant rather than a True/False boolean. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit aacb18f920349e13b562c7c97901a0be7b273137 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Aug 6 11:08:10 2021 +1200 pytest: dynamic tests optionally add __doc__ BUG: https://bugzilla.samba.org/show_bug.cgi?id=14869 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 6292f0597f208d7953382341380921cf0fd0a8a8 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Mon Sep 20 16:27:40 2021 +1200 selftest: Increase account lockout windows to make test more realiable BUG: https://bugzilla.samba.org/show_bug.cgi?id=14868 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit a169e013e66bab15e594ce49b805edebfcd503cf Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Sep 8 17:01:26 2021 +1200 pytest/rodc_rwdc: try to avoid race. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14868 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: auth/credentials/credentials_krb5.c | 12 +- lib/krb5_wrap/krb5_samba.c | 192 +++++++++--- lib/krb5_wrap/krb5_samba.h | 13 +- python/samba/tests/__init__.py | 3 +- .../samba/tests/krb5/as_canonicalization_tests.py | 7 +- python/samba/tests/krb5/as_req_tests.py | 10 + python/samba/tests/krb5/kdc_base_test.py | 87 ++++-- python/samba/tests/krb5/kdc_tgs_tests.py | 7 +- .../krb5/ms_kile_client_principal_lookup_tests.py | 36 ++- python/samba/tests/krb5/raw_testcase.py | 20 +- python/samba/tests/krb5/rodc_tests.py | 4 +- python/samba/tests/krb5/s4u_tests.py | 35 ++- python/samba/tests/krb5/salt_tests.py | 327 +++++++++++++++++++++ python/samba/tests/krb5/test_ccache.py | 11 +- python/samba/tests/s3_net_join.py | 2 +- python/samba/tests/usage.py | 1 + selftest/knownfail.d/kdc-salt | 1 + selftest/target/Samba3.pm | 43 +-- selftest/target/Samba4.pm | 76 +++-- source3/passdb/machine_account_secrets.c | 10 +- source4/dsdb/samdb/ldb_modules/password_hash.c | 23 +- source4/dsdb/tests/python/rodc_rwdc.py | 8 +- source4/kdc/wscript_build | 1 + source4/selftest/tests.py | 8 + 24 files changed, 751 insertions(+), 186 deletions(-) create mode 100755 python/samba/tests/krb5/salt_tests.py create mode 100644 selftest/knownfail.d/kdc-salt Changeset truncated at 500 lines: diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index c03d80ac440..d2e7a76a69e 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -1200,12 +1200,12 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, break; } - ret = smb_krb5_salt_principal(realm, - username, /* sAMAccountName */ - upn, /* userPrincipalName */ - uac_flags, - mem_ctx, - &salt_principal); + ret = smb_krb5_salt_principal_str(realm, + username, /* sAMAccountName */ + upn, /* userPrincipalName */ + uac_flags, + mem_ctx, + &salt_principal); if (ret) { talloc_free(mem_ctx); return ret; diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index 20ce86c708d..63a6e951f80 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -456,19 +456,20 @@ int smb_krb5_get_pw_salt(krb5_context context, * * @see smb_krb5_salt_principal2data */ -int smb_krb5_salt_principal(const char *realm, +int smb_krb5_salt_principal(krb5_context krb5_ctx, + const char *realm, const char *sAMAccountName, const char *userPrincipalName, uint32_t uac_flags, - TALLOC_CTX *mem_ctx, - char **_salt_principal) + krb5_principal *salt_princ) { TALLOC_CTX *frame = talloc_stackframe(); char *upper_realm = NULL; const char *principal = NULL; int principal_len = 0; + krb5_error_code krb5_ret; - *_salt_principal = NULL; + *salt_princ = NULL; if (sAMAccountName == NULL) { TALLOC_FREE(frame); @@ -512,7 +513,6 @@ int smb_krb5_salt_principal(const char *realm, */ if (uac_flags & UF_TRUST_ACCOUNT_MASK) { int computer_len = 0; - char *tmp = NULL; computer_len = strlen(sAMAccountName); if (sAMAccountName[computer_len-1] == '$') { @@ -520,60 +520,186 @@ int smb_krb5_salt_principal(const char *realm, } if (uac_flags & UF_INTERDOMAIN_TRUST_ACCOUNT) { - principal = talloc_asprintf(frame, "krbtgt/%*.*s", - computer_len, computer_len, - sAMAccountName); - if (principal == NULL) { + const char *krbtgt = "krbtgt"; + krb5_ret = krb5_build_principal_ext(krb5_ctx, + salt_princ, + strlen(upper_realm), + upper_realm, + strlen(krbtgt), + krbtgt, + computer_len, + sAMAccountName, + 0); + if (krb5_ret != 0) { TALLOC_FREE(frame); - return ENOMEM; + return krb5_ret; } } else { - - tmp = talloc_asprintf(frame, "host/%*.*s.%s", - computer_len, computer_len, - sAMAccountName, realm); + const char *host = "host"; + char *tmp = NULL; + char *tmp_lower = NULL; + + tmp = talloc_asprintf(frame, "%*.*s.%s", + computer_len, + computer_len, + sAMAccountName, + realm); if (tmp == NULL) { TALLOC_FREE(frame); return ENOMEM; } - principal = strlower_talloc(frame, tmp); - TALLOC_FREE(tmp); - if (principal == NULL) { + tmp_lower = strlower_talloc(frame, tmp); + if (tmp_lower == NULL) { TALLOC_FREE(frame); return ENOMEM; } - } - principal_len = strlen(principal); + krb5_ret = krb5_build_principal_ext(krb5_ctx, + salt_princ, + strlen(upper_realm), + upper_realm, + strlen(host), + host, + strlen(tmp_lower), + tmp_lower, + 0); + if (krb5_ret != 0) { + TALLOC_FREE(frame); + return krb5_ret; + } + } } else if (userPrincipalName != NULL) { - char *p; + /* + * We parse the name not only to allow an easy + * replacement of the realm (no matter the realm in + * the UPN, the salt comes from the upper-case real + * realm, but also to correctly provide a salt when + * the UPN is host/foo.bar + * + * This can fail for a UPN of the form foo@bar@REALM + * (which is accepted by windows) however. + */ + krb5_ret = krb5_parse_name(krb5_ctx, + userPrincipalName, + salt_princ); - principal = userPrincipalName; - p = strchr(principal, '@'); - if (p != NULL) { - principal_len = PTR_DIFF(p, principal); - } else { - principal_len = strlen(principal); + if (krb5_ret != 0) { + TALLOC_FREE(frame); + return krb5_ret; + } + + /* + * No matter what realm (including none) in the UPN, + * the realm is replaced with our upper-case realm + */ + smb_krb5_principal_set_realm(krb5_ctx, + *salt_princ, + upper_realm); + if (krb5_ret != 0) { + krb5_free_principal(krb5_ctx, *salt_princ); + TALLOC_FREE(frame); + return krb5_ret; } } else { principal = sAMAccountName; principal_len = strlen(principal); - } - *_salt_principal = talloc_asprintf(mem_ctx, "%*.*s@%s", - principal_len, principal_len, - principal, upper_realm); - if (*_salt_principal == NULL) { - TALLOC_FREE(frame); - return ENOMEM; + krb5_ret = krb5_build_principal_ext(krb5_ctx, + salt_princ, + strlen(upper_realm), + upper_realm, + principal_len, + principal, + 0); + if (krb5_ret != 0) { + TALLOC_FREE(frame); + return krb5_ret; + } } TALLOC_FREE(frame); return 0; } +/** + * @brief This constructs the salt principal used by active directory + * + * Most Kerberos encryption types require a salt in order to + * calculate the long term private key for user/computer object + * based on a password. + * + * The returned _salt_principal is a string in forms like this: + * - host/somehost.example....@example.com + * - someacco...@example.com + * - someprinci...@example.com + * + * This is not the form that's used as salt, it's just + * the human readable form. It needs to be converted by + * smb_krb5_salt_principal2data(). + * + * @param[in] realm The realm the user/computer is added too. + * + * @param[in] sAMAccountName The sAMAccountName attribute of the object. + * + * @param[in] userPrincipalName The userPrincipalName attribute of the object + * or NULL is not available. + * + * @param[in] uac_flags UF_ACCOUNT_TYPE_MASKed userAccountControl field + * + * @param[in] mem_ctx The TALLOC_CTX to allocate _salt_principal. + * + * @param[out] _salt_principal The resulting principal as string. + * + * @retval 0 Success; otherwise - Kerberos error codes + * + * @see smb_krb5_salt_principal2data + */ +int smb_krb5_salt_principal_str(const char *realm, + const char *sAMAccountName, + const char *userPrincipalName, + uint32_t uac_flags, + TALLOC_CTX *mem_ctx, + char **_salt_principal_str) +{ + krb5_principal salt_principal = NULL; + char *salt_principal_malloc; + krb5_context krb5_ctx; + krb5_error_code krb5_ret + = smb_krb5_init_context_common(&krb5_ctx); + if (krb5_ret != 0) { + DBG_ERR("kerberos init context failed (%s)\n", + error_message(krb5_ret)); + return krb5_ret; + } + + krb5_ret = smb_krb5_salt_principal(krb5_ctx, + realm, + sAMAccountName, + userPrincipalName, + uac_flags, + &salt_principal); + + krb5_ret = krb5_unparse_name(krb5_ctx, salt_principal, + &salt_principal_malloc); + if (krb5_ret != 0) { + krb5_free_principal(krb5_ctx, salt_principal); + DBG_ERR("kerberos unparse of salt principal failed (%s)\n", + error_message(krb5_ret)); + return krb5_ret; + } + krb5_free_principal(krb5_ctx, salt_principal); + *_salt_principal_str + = talloc_strdup(mem_ctx, salt_principal_malloc); + krb5_free_unparsed_name(krb5_ctx, salt_principal_malloc); + + if (*_salt_principal_str == NULL) { + return ENOMEM; + } + return 0; +} + /** * @brief Converts the salt principal string into the salt data blob * diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h index 01a9806b670..a66b7465530 100644 --- a/lib/krb5_wrap/krb5_samba.h +++ b/lib/krb5_wrap/krb5_samba.h @@ -340,12 +340,19 @@ krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx, int smb_krb5_get_pw_salt(krb5_context context, krb5_const_principal host_princ, krb5_data *psalt); -int smb_krb5_salt_principal(const char *realm, +int smb_krb5_salt_principal(krb5_context krb5_ctx, + const char *realm, const char *sAMAccountName, const char *userPrincipalName, uint32_t uac_flags, - TALLOC_CTX *mem_ctx, - char **_salt_principal); + krb5_principal *salt_princ); + +int smb_krb5_salt_principal_str(const char *realm, + const char *sAMAccountName, + const char *userPrincipalName, + uint32_t uac_flags, + TALLOC_CTX *mem_ctx, + char **_salt_principal); int smb_krb5_salt_principal2data(krb5_context context, const char *salt_principal, TALLOC_CTX *mem_ctx, diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index 2c7e7784966..1b1fd984251 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -68,7 +68,7 @@ class TestCase(unittest.TestCase): """A Samba test case.""" @classmethod - def generate_dynamic_test(cls, fnname, suffix, *args): + def generate_dynamic_test(cls, fnname, suffix, *args, doc=None): """ fnname is something like "test_dynamic_sum" suffix is something like "1plus2" @@ -81,6 +81,7 @@ class TestCase(unittest.TestCase): """ def fn(self): getattr(self, "_%s_with_args" % fnname)(*args) + fn.__doc__ = doc setattr(cls, "%s_%s" % (fnname, suffix), fn) @classmethod diff --git a/python/samba/tests/krb5/as_canonicalization_tests.py b/python/samba/tests/krb5/as_canonicalization_tests.py index 9538d0ae3cf..674fcb37101 100755 --- a/python/samba/tests/krb5/as_canonicalization_tests.py +++ b/python/samba/tests/krb5/as_canonicalization_tests.py @@ -171,9 +171,10 @@ class KerberosASCanonicalizationTests(KDCBaseTest): def machine_account_creds(self): if self.machine_creds is None: samdb = self.get_samdb() - self.machine_creds, _ = self.create_account(samdb, - MACHINE_NAME, - machine_account=True) + self.machine_creds, _ = self.create_account( + samdb, + MACHINE_NAME, + account_type=self.AccountType.COMPUTER) self.machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) self.machine_creds.set_kerberos_state(DONT_USE_KERBEROS) diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index 7d7baaebf24..08081928363 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -113,6 +113,13 @@ class AsReqKerberosTests(KDCBaseTest): def test_as_req_enc_timestamp(self): client_creds = self.get_client_creds() + self._run_as_req_enc_timestamp(client_creds) + + def test_as_req_enc_timestamp_mac(self): + client_creds = self.get_mach_creds() + self._run_as_req_enc_timestamp(client_creds) + + def _run_as_req_enc_timestamp(self, client_creds): client_account = client_creds.get_username() client_as_etypes = self.get_default_enctypes() client_kvno = client_creds.get_kvno() @@ -197,6 +204,9 @@ class AsReqKerberosTests(KDCBaseTest): pac_request=True) self.assertIsNotNone(as_rep) + return etype_info2 + + if __name__ == "__main__": global_asn1_print = False global_hexdump = False diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 1fc15315b0b..b24c6376ab0 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -23,6 +23,7 @@ import tempfile import binascii import collections import secrets +from enum import Enum, auto from collections import namedtuple import ldb @@ -90,6 +91,10 @@ class KDCBaseTest(RawKerberosTest): """ Base class for KDC tests. """ + class AccountType(Enum): + USER = auto() + COMPUTER = auto() + @classmethod def setUpClass(cls): super().setUpClass() @@ -103,7 +108,7 @@ class KDCBaseTest(RawKerberosTest): # An identifier to ensure created accounts have unique names. Windows # caches accounts based on usernames, so account names being different # across test runs avoids previous test runs affecting the results. - cls.account_base = f'krb5_{secrets.token_hex(5)}_' + cls.account_base = f'{secrets.token_hex(4)}_' cls.account_id = 0 # A set containing DNs of accounts created as part of testing. @@ -230,16 +235,18 @@ class KDCBaseTest(RawKerberosTest): return default_enctypes - def create_account(self, samdb, name, machine_account=False, + def create_account(self, samdb, name, account_type=AccountType.USER, spn=None, upn=None, additional_details=None, - ou=None, account_control=0): + ou=None, account_control=0, add_dollar=True): '''Create an account for testing. The dn of the created account is added to self.accounts, which is used by tearDownClass to clean up the created accounts. ''' if ou is None: - guid = (DS_GUID_COMPUTERS_CONTAINER if machine_account - else DS_GUID_USERS_CONTAINER) + if account_type is account_type.COMPUTER: + guid = DS_GUID_COMPUTERS_CONTAINER + else: + guid = DS_GUID_USERS_CONTAINER ou = samdb.get_wellknown_dn(samdb.get_default_basedn(), guid) @@ -248,14 +255,18 @@ class KDCBaseTest(RawKerberosTest): # remove the account if it exists, this will happen if a previous test # run failed delete_force(samdb, dn) - if machine_account: - object_class = "computer" - account_name = "%s$" % name - account_control |= UF_WORKSTATION_TRUST_ACCOUNT - else: + account_name = name + if account_type is self.AccountType.USER: object_class = "user" - account_name = name account_control |= UF_NORMAL_ACCOUNT + else: + object_class = "computer" + if add_dollar: + account_name += '$' + if account_type is self.AccountType.COMPUTER: + account_control |= UF_WORKSTATION_TRUST_ACCOUNT + else: + self.fail() password = generate_random_password(32, 32) utf16pw = ('"%s"' % password).encode('utf-16-le') @@ -267,6 +278,10 @@ class KDCBaseTest(RawKerberosTest): "userAccountControl": str(account_control), "unicodePwd": utf16pw} if spn is not None: + if isinstance(spn, str): + spn = spn.format(account=account_name) + else: + spn = tuple(s.format(account=account_name) for s in spn) details["servicePrincipalName"] = spn if upn is not None: details["userPrincipalName"] = upn @@ -280,11 +295,12 @@ class KDCBaseTest(RawKerberosTest): creds.set_domain(samdb.domain_netbios_name().upper()) creds.set_password(password) creds.set_username(account_name) - if machine_account: - creds.set_workstation(name) - else: + if account_type is self.AccountType.USER: creds.set_workstation('') + else: + creds.set_workstation(name) creds.set_dn(ldb.Dn(samdb, dn)) + creds.set_upn(upn) creds.set_spn(spn) # # Save the account name so it can be deleted in tearDownClass @@ -609,13 +625,18 @@ class KDCBaseTest(RawKerberosTest): return cleanup def get_cached_creds(self, *, - machine_account, + account_type, opts=None, use_cache=True): if opts is None: opts = {} opts_default = { + 'name_prefix': None, + 'name_suffix': None, + 'add_dollar': True, + 'upn': None, + 'spn': None, 'allowed_replication': False, 'allowed_replication_mock': False, 'denied_replication': False, @@ -632,7 +653,7 @@ class KDCBaseTest(RawKerberosTest): } account_opts = { -- Samba Shared Repository