From: Pavel Filipenský Date: Thu, 21 Dec 2023 12:57:38 +0000 (+0100) Subject: s3: Sync machine account password in secrets_{prepare,finish}_password_change X-Git-Tag: tdb-1.4.11~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=683f6eec40f2efbb122329800ebb2f5d2f518746;p=thirdparty%2Fsamba.git s3: Sync machine account password in secrets_{prepare,finish}_password_change BUG: https://bugzilla.samba.org/show_bug.cgi?id=6750 Signed-off-by: Pavel Filipenský Reviewed-by: Stefan Metzmacher --- diff --git a/source3/include/secrets.h b/source3/include/secrets.h index 47cf40432f0..a454c8bb8ff 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -129,7 +129,8 @@ 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); + struct secrets_domain_info1_change **pprev, + NTSTATUS (*sync_pw2keytabs_fn)(void)); NTSTATUS secrets_failed_password_change(const char *change_server, NTSTATUS local_status, NTSTATUS remote_status, @@ -140,7 +141,8 @@ NTSTATUS secrets_defer_password_change(const char *change_server, const struct secrets_domain_info1 *info); NTSTATUS secrets_finish_password_change(const char *change_server, NTTIME change_time, - const struct secrets_domain_info1 *info); + const struct secrets_domain_info1 *info, + NTSTATUS (*sync_pw2keytabs_fn)(void)); 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/trusts_util.c b/source3/libads/trusts_util.c index c40eb791802..6f805f2365e 100644 --- a/source3/libads/trusts_util.c +++ b/source3/libads/trusts_util.c @@ -26,6 +26,7 @@ #include "../librpc/gen_ndr/ndr_netlogon.h" #include "librpc/gen_ndr/secrets.h" #include "secrets.h" +#include "ads.h" #include "passdb.h" #include "libsmb/libsmb.h" #include "source3/include/messages.h" @@ -317,9 +318,17 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, case SEC_CHAN_WKSTA: case SEC_CHAN_BDC: - status = secrets_prepare_password_change(domain, dcname, + status = secrets_prepare_password_change(domain, + dcname, new_trust_pw_str, - frame, &info, &prev); + frame, + &info, + &prev, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", domain)); @@ -415,9 +424,15 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, current_timestring(talloc_tos(), false), __func__, domain, context_name)); - status = secrets_finish_password_change(prev->password->change_server, - prev->password->change_time, - info); + status = secrets_finish_password_change( + prev->password->change_server, + prev->password->change_time, + info, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", domain)); @@ -559,9 +574,14 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, case SEC_CHAN_WKSTA: case SEC_CHAN_BDC: status = secrets_finish_password_change( - info->next_change->change_server, - info->next_change->change_time, - info); + info->next_change->change_server, + info->next_change->change_time, + info, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif 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 0938db5ea64..243dd09f3d0 100644 --- a/source3/libads/util.c +++ b/source3/libads/util.c @@ -56,7 +56,13 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip ads->auth.kdc_server, new_password, talloc_tos(), - &info, &prev); + &info, + &prev, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif if (!NT_STATUS_IS_OK(status)) { return ADS_ERROR_NT(status); } @@ -128,7 +134,14 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip return ret; } - status = secrets_finish_password_change(ads->auth.kdc_server, now, info); + status = secrets_finish_password_change(ads->auth.kdc_server, + now, + info, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("Failed to save machine password\n")); return ADS_ERROR_NT(status); diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index c97b35e7e52..21571349004 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -1673,7 +1673,8 @@ 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) + struct secrets_domain_info1_change **pprev, + NTSTATUS (*sync_pw2keytabs_fn)(void)) { TALLOC_CTX *frame = talloc_stackframe(); struct db_context *db = NULL; @@ -1768,6 +1769,16 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname, return NT_STATUS_INTERNAL_DB_ERROR; } + if (prev == NULL && sync_pw2keytabs_fn != NULL) { + status = sync_pw2keytabs_fn(); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("Sync of machine password failed.\n"); + dbwrap_transaction_cancel(db); + TALLOC_FREE(frame); + return status; + } + } + *pinfo = talloc_move(mem_ctx, &info); if (prev != NULL) { *pprev = talloc_move(mem_ctx, &prev); @@ -2011,7 +2022,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) + const struct secrets_domain_info1 *cookie, + NTSTATUS (*sync_pw2keytabs_fn)(void)) { const char *domain = cookie->domain_info.name.string; TALLOC_CTX *frame = talloc_stackframe(); @@ -2067,6 +2079,20 @@ NTSTATUS secrets_finish_password_change(const char *change_server, return status; } + /* + * For the clustered samba, it is important to have following order: + * 1. dbwrap_transaction_commit() + * 2. sync_pw2keytabs() + * Only this order ensures a correct behavior of + * the 'sync machine password script' that does: + * 'onnode all net ads keytab create' + * + * If we would call sync_pw2keytabs() before committing the changes to + * the secrets.tdb, it will not be updated on other nodes, so triggering + * 'net ads keytab create' will not see the new password yet. + * + * This applies also to secrets_prepare_password_change(). + */ ret = dbwrap_transaction_commit(db); if (ret != 0) { DBG_ERR("dbwrap_transaction_commit() failed for %s\n", @@ -2075,6 +2101,15 @@ NTSTATUS secrets_finish_password_change(const char *change_server, return NT_STATUS_INTERNAL_DB_ERROR; } + if (sync_pw2keytabs_fn != NULL) { + status = sync_pw2keytabs_fn(); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("Sync of machine password failed.\n"); + TALLOC_FREE(frame); + return status; + } + } + TALLOC_FREE(frame); return NT_STATUS_OK; } diff --git a/source3/utils/net.c b/source3/utils/net.c index 9c070372600..7b40d2bee95 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -224,7 +224,13 @@ static int net_changesecretpw(struct net_context *c, int argc, "localhost", trust_pw, talloc_tos(), - &info, &prev); + &info, + &prev, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Unable to write the machine account password in the secrets database")); @@ -243,7 +249,14 @@ static int net_changesecretpw(struct net_context *c, int argc, } return 1; } - status = secrets_finish_password_change("localhost", now, info); + status = secrets_finish_password_change("localhost", + now, + info, +#ifdef HAVE_ADS + sync_pw2keytabs); +#else + NULL); +#endif if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Unable to write the machine account password in the secrets database"));