From: Andreas Schneider Date: Mon, 28 Jul 2025 08:43:36 +0000 (+0200) Subject: s3:net: Pass down the server from cmdline to sync_pw2keytabs() X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fv4-21-test;p=thirdparty%2Fsamba.git s3:net: Pass down the server from cmdline to sync_pw2keytabs() This makes sure that during 'net ads join' the keytab create code - sync_pw2keytabs() talks to the same DC at what the machine account was created. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15905 Signed-off-by: Andreas Schneider Signed-off-by: Pavel Filipenský Pair-Programmed-With: Pavel Filipenský Reviewed-by: Alexander Bokovoy Autobuild-User(master): Pavel Filipensky Autobuild-Date(master): Fri Sep 5 13:38:33 UTC 2025 on atb-devel-224 (cherry picked from commit 5d1d3a8b568b5a07ed1ed537d20aa93820cecc14) Autobuild-User(v4-21-test): Jule Anger Autobuild-Date(v4-21-test): Thu Sep 11 12:28:03 UTC 2025 on atb-devel-224 --- diff --git a/selftest/knownfail b/selftest/knownfail index 94d9ffc5fcb..a7a2e2b2251 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -340,7 +340,6 @@ ^samba.tests.dcerpc.dnsserver.samba.tests.dcerpc.dnsserver.DnsserverTests.test_security_descriptor.* ^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dbcheck_dangling_multi_valued_clean ^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_missing -^samba4.blackbox.net_ads_join.join # We currently don't send referrals for LDAP modify of non-replicated attrs ^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.* diff --git a/source3/include/secrets.h b/source3/include/secrets.h index a454c8bb8ff..061b9c6ef34 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -125,12 +125,15 @@ char *secrets_domain_info_string(TALLOC_CTX *mem_ctx, const struct secrets_domai NTSTATUS secrets_fetch_or_upgrade_domain_info(const char *domain, TALLOC_CTX *mem_ctx, struct secrets_domain_info1 **pinfo); -NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname, - const char *cleartext_unix, - TALLOC_CTX *mem_ctx, - struct secrets_domain_info1 **pinfo, - struct secrets_domain_info1_change **pprev, - NTSTATUS (*sync_pw2keytabs_fn)(void)); +NTSTATUS secrets_prepare_password_change( + const char *domain, + const char *dcname, + const char *cleartext_unix, + TALLOC_CTX *mem_ctx, + struct secrets_domain_info1 **pinfo, + struct secrets_domain_info1_change **pprev, + NTSTATUS (*sync_pw2keytabs_fn)(const char *), + const char *opt_host); NTSTATUS secrets_failed_password_change(const char *change_server, NTSTATUS local_status, NTSTATUS remote_status, @@ -139,10 +142,12 @@ NTSTATUS secrets_defer_password_change(const char *change_server, NTSTATUS local_status, NTSTATUS remote_status, const struct secrets_domain_info1 *info); -NTSTATUS secrets_finish_password_change(const char *change_server, - NTTIME change_time, - const struct secrets_domain_info1 *info, - NTSTATUS (*sync_pw2keytabs_fn)(void)); +NTSTATUS secrets_finish_password_change( + const char *change_server, + NTTIME change_time, + const struct secrets_domain_info1 *info, + NTSTATUS (*sync_pw2keytabs_fn)(const char *), + const char *prefer_dc); bool secrets_delete_machine_password_ex(const char *domain, const char *realm); bool secrets_delete_domain_sid(const char *domain); char *secrets_fetch_prev_machine_password(const char *domain); diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h index 8440c35e46d..2e67eef155c 100644 --- a/source3/libads/ads_proto.h +++ b/source3/libads/ads_proto.h @@ -230,6 +230,6 @@ struct spn_struct { /* parse a windows style SPN, returns NULL if parsing fails */ struct spn_struct *parse_spn(TALLOC_CTX *ctx, const char *srvprinc); -NTSTATUS sync_pw2keytabs(void); +NTSTATUS sync_pw2keytabs(const char *prefer_dc); #endif /* _LIBADS_ADS_PROTO_H_ */ diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c index 49a892e5a55..1d4f9c12e1d 100644 --- a/source3/libads/kerberos_keytab.c +++ b/source3/libads/kerberos_keytab.c @@ -84,6 +84,7 @@ struct pw2kt_global_state { char *ad_upn; char *ad_sam_account; char **ad_spn_array; + const char *prefer_dc; size_t ad_num_spns; /* This is from secrets.db */ struct secrets_domain_info1 *info; @@ -869,8 +870,11 @@ static ADS_STATUS pw2kt_get_dc_info(struct pw2kt_global_state *state) int count; bool ok; TALLOC_CTX *tmp_ctx = talloc_stackframe(); - ADS_STRUCT *ads = ads_init( - tmp_ctx, lp_realm(), lp_workgroup(), NULL, ADS_SASL_SIGN); + ADS_STRUCT *ads = ads_init(tmp_ctx, + lp_realm(), + lp_workgroup(), + state->prefer_dc, + ADS_SASL_SIGN); if (ads == NULL) { DBG_ERR("ads_init() failed\n"); @@ -1029,7 +1033,20 @@ static bool pw2kt_default_keytab_name(char *name_str, size_t name_size) return true; } -NTSTATUS sync_pw2keytabs(void) +/** + * @internal + * + * @brief Sync machine password from secrets to keytab + * + * @param prefer_dc The DC we should talk to. This is especially important + * during domain join. Pass NULL if we should pick a random + * one. + * + * @return An NTSTATUS error code. + * + * @see NT_STATUS_IS_OK() + */ +NTSTATUS sync_pw2keytabs(const char *prefer_dc) { TALLOC_CTX *frame = talloc_stackframe(); const struct loadparm_substitution *lp_sub = @@ -1055,6 +1072,7 @@ NTSTATUS sync_pw2keytabs(void) TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } + state->prefer_dc = prefer_dc; lp_ptr = lp_sync_machine_password_to_keytab(); if (lp_ptr == NULL) { diff --git a/source3/libads/trusts_util.c b/source3/libads/trusts_util.c index 6f805f2365e..e774a0b73e6 100644 --- a/source3/libads/trusts_util.c +++ b/source3/libads/trusts_util.c @@ -325,10 +325,11 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, &info, &prev, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + NULL /* opt_host */); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", domain)); @@ -429,10 +430,11 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, prev->password->change_time, info, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + prev->password->change_server); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", domain)); @@ -578,10 +580,11 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, info->next_change->change_time, info, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + info->next_change->change_server); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("secrets_finish_password_change() failed for domain %s!\n", domain)); diff --git a/source3/libads/util.c b/source3/libads/util.c index 243dd09f3d0..360e556ab9b 100644 --- a/source3/libads/util.c +++ b/source3/libads/util.c @@ -59,10 +59,11 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip &info, &prev, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + ads->auth.kdc_server); if (!NT_STATUS_IS_OK(status)) { return ADS_ERROR_NT(status); } @@ -138,10 +139,11 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip now, info, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + ads->auth.kdc_server); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("Failed to save machine password\n")); return ADS_ERROR_NT(status); diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index dc924ad199a..d47178e5700 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -866,7 +866,7 @@ static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx, static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r) { - NTSTATUS ntstatus = sync_pw2keytabs(); + NTSTATUS ntstatus = sync_pw2keytabs(r->in.dc_name); return NT_STATUS_IS_OK(ntstatus); } diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index 21571349004..8e16b2c5640 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -1674,7 +1674,8 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname, TALLOC_CTX *mem_ctx, struct secrets_domain_info1 **pinfo, struct secrets_domain_info1_change **pprev, - NTSTATUS (*sync_pw2keytabs_fn)(void)) + NTSTATUS (*sync_pw2keytabs_fn)(const char *), + const char *opt_host) { TALLOC_CTX *frame = talloc_stackframe(); struct db_context *db = NULL; @@ -1770,7 +1771,7 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname, } if (prev == NULL && sync_pw2keytabs_fn != NULL) { - status = sync_pw2keytabs_fn(); + status = sync_pw2keytabs_fn(opt_host); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("Sync of machine password failed.\n"); dbwrap_transaction_cancel(db); @@ -2023,7 +2024,8 @@ NTSTATUS secrets_defer_password_change(const char *change_server, NTSTATUS secrets_finish_password_change(const char *change_server, NTTIME change_time, const struct secrets_domain_info1 *cookie, - NTSTATUS (*sync_pw2keytabs_fn)(void)) + NTSTATUS (*sync_pw2keytabs_fn)(const char *), + const char *prefer_dc) { const char *domain = cookie->domain_info.name.string; TALLOC_CTX *frame = talloc_stackframe(); @@ -2102,7 +2104,7 @@ NTSTATUS secrets_finish_password_change(const char *change_server, } if (sync_pw2keytabs_fn != NULL) { - status = sync_pw2keytabs_fn(); + status = sync_pw2keytabs_fn(prefer_dc); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("Sync of machine password failed.\n"); TALLOC_FREE(frame); diff --git a/source3/utils/net.c b/source3/utils/net.c index 7ce93ced79e..ecabd980d0c 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -235,10 +235,11 @@ static int net_changesecretpw(struct net_context *c, int argc, &info, &prev, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + c->opt_host); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Unable to write the machine account password in the secrets database")); @@ -261,10 +262,11 @@ static int net_changesecretpw(struct net_context *c, int argc, now, info, #ifdef HAVE_ADS - sync_pw2keytabs); + sync_pw2keytabs, #else - NULL); + NULL, #endif + c->opt_host); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Unable to write the machine account password in the secrets database")); diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 4778c6d9cf4..c68b45aacd1 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -2959,7 +2959,7 @@ static int net_ads_keytab_create(struct net_context *c, int argc, const char **a net_use_krb_machine_account(c); } - ntstatus = sync_pw2keytabs(); + ntstatus = sync_pw2keytabs(c->opt_host); ret = NT_STATUS_IS_OK(ntstatus) ? 0 : 1; return ret; }