]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:net: Pass down the server from cmdline to sync_pw2keytabs()
authorAndreas Schneider <asn@samba.org>
Mon, 28 Jul 2025 08:43:36 +0000 (10:43 +0200)
committerJule Anger <janger@samba.org>
Tue, 9 Sep 2025 12:46:31 +0000 (12:46 +0000)
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 <asn@samba.org>
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Pair-Programmed-With: Pavel Filipenský <pfilipensky@samba.org>

Reviewed-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): Pavel Filipensky <pfilipensky@samba.org>
Autobuild-Date(master): Fri Sep  5 13:38:33 UTC 2025 on atb-devel-224

(cherry picked from commit 5d1d3a8b568b5a07ed1ed537d20aa93820cecc14)

Autobuild-User(v4-23-test): Jule Anger <janger@samba.org>
Autobuild-Date(v4-23-test): Tue Sep  9 12:46:31 UTC 2025 on atb-devel-224

selftest/knownfail
source3/include/secrets.h
source3/libads/ads_proto.h
source3/libads/kerberos_keytab.c
source3/libads/trusts_util.c
source3/libads/util.c
source3/libnet/libnet_join.c
source3/passdb/machine_account_secrets.c
source3/utils/net.c
source3/utils/net_ads.c

index 7c0e9dd00e7b60f0356eb635cb35f4cff5a98a82..ab2d79d7114edb6ee29eafd4ef5e4ce84921471b 100644 (file)
 ^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.*
index a454c8bb8ffe8d6228cccf73db9d7d5f3931445e..061b9c6ef34b95fbaf8e06e7f0d252d430777392 100644 (file)
@@ -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);
index e5b685308668cd70f1895329221254270368a554..a368e04d7e49b1374ac79f2a49c2316d936fadc8 100644 (file)
@@ -229,6 +229,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_ */
index ed26c6af499686514769d7d29cb83b4d6d6fe774..364d8421bda4cf91420c3233186c769e233f56b4 100644 (file)
@@ -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) {
index 9bea87990b6df9c553f08e4f17b745a6f0ea275f..2a1f732f2987693b6d89227d9bb241762b20afc7 100644 (file)
@@ -359,10 +359,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));
@@ -609,10 +610,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));
@@ -758,10 +760,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));
index 243dd09f3d05ad5ddc282bcd820f0fb9bb0df0c4..360e556ab9bbf7756307095653e21f977e27f0c7 100644 (file)
@@ -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);
index c33724494aad1c6466f246bc86c3e63159fc59e0..609b2b9622244f24aeed889d8142012450cdcdb6 100644 (file)
@@ -869,7 +869,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);
 }
index 971dd15aa5f3095defa0adf7961b0d927c8d3ed7..525092b2e1a34b96536f0fbc164823816492a6d0 100644 (file)
@@ -1673,7 +1673,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");
                        TALLOC_FREE(frame);
@@ -2022,7 +2023,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();
@@ -2101,7 +2103,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);
index 7ce93ced79eaa5440b53c91e53cfff8368bf998d..ecabd980d0c8109ce9716e5a9026f6b5b9fbab97 100644 (file)
@@ -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"));
index 6c11faeb091117a97bee18a9edc85f3047a48c82..d49b7537e716b4f269b92c0ad8ca3609c0abf8cd 100644 (file)
@@ -2935,7 +2935,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;
 }