1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

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ý <pfilipensky@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Pavel Filipenský 2023-12-21 13:57:38 +01:00 committed by Pavel Filipensky
parent 7c65aa8c7b
commit 683f6eec40
5 changed files with 99 additions and 16 deletions

View File

@ -129,7 +129,8 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname,
const char *cleartext_unix, const char *cleartext_unix,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
struct secrets_domain_info1 **pinfo, 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 secrets_failed_password_change(const char *change_server,
NTSTATUS local_status, NTSTATUS local_status,
NTSTATUS remote_status, NTSTATUS remote_status,
@ -140,7 +141,8 @@ NTSTATUS secrets_defer_password_change(const char *change_server,
const struct secrets_domain_info1 *info); const struct secrets_domain_info1 *info);
NTSTATUS secrets_finish_password_change(const char *change_server, NTSTATUS secrets_finish_password_change(const char *change_server,
NTTIME change_time, 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_machine_password_ex(const char *domain, const char *realm);
bool secrets_delete_domain_sid(const char *domain); bool secrets_delete_domain_sid(const char *domain);
char *secrets_fetch_prev_machine_password(const char *domain); char *secrets_fetch_prev_machine_password(const char *domain);

View File

@ -26,6 +26,7 @@
#include "../librpc/gen_ndr/ndr_netlogon.h" #include "../librpc/gen_ndr/ndr_netlogon.h"
#include "librpc/gen_ndr/secrets.h" #include "librpc/gen_ndr/secrets.h"
#include "secrets.h" #include "secrets.h"
#include "ads.h"
#include "passdb.h" #include "passdb.h"
#include "libsmb/libsmb.h" #include "libsmb/libsmb.h"
#include "source3/include/messages.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_WKSTA:
case SEC_CHAN_BDC: case SEC_CHAN_BDC:
status = secrets_prepare_password_change(domain, dcname, status = secrets_prepare_password_change(domain,
dcname,
new_trust_pw_str, new_trust_pw_str,
frame, &info, &prev); frame,
&info,
&prev,
#ifdef HAVE_ADS
sync_pw2keytabs);
#else
NULL);
#endif
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n",
domain)); domain));
@ -415,9 +424,15 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
current_timestring(talloc_tos(), false), current_timestring(talloc_tos(), false),
__func__, domain, context_name)); __func__, domain, context_name));
status = secrets_finish_password_change(prev->password->change_server, status = secrets_finish_password_change(
prev->password->change_time, prev->password->change_server,
info); prev->password->change_time,
info,
#ifdef HAVE_ADS
sync_pw2keytabs);
#else
NULL);
#endif
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n", DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n",
domain)); domain));
@ -559,9 +574,14 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
case SEC_CHAN_WKSTA: case SEC_CHAN_WKSTA:
case SEC_CHAN_BDC: case SEC_CHAN_BDC:
status = secrets_finish_password_change( status = secrets_finish_password_change(
info->next_change->change_server, info->next_change->change_server,
info->next_change->change_time, info->next_change->change_time,
info); info,
#ifdef HAVE_ADS
sync_pw2keytabs);
#else
NULL);
#endif
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("secrets_finish_password_change() failed for domain %s!\n", DEBUG(0, ("secrets_finish_password_change() failed for domain %s!\n",
domain)); domain));

View File

@ -56,7 +56,13 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
ads->auth.kdc_server, ads->auth.kdc_server,
new_password, new_password,
talloc_tos(), talloc_tos(),
&info, &prev); &info,
&prev,
#ifdef HAVE_ADS
sync_pw2keytabs);
#else
NULL);
#endif
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
return ADS_ERROR_NT(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; 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)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(1,("Failed to save machine password\n")); DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_NT(status); return ADS_ERROR_NT(status);

View File

@ -1673,7 +1673,8 @@ NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname,
const char *cleartext_unix, const char *cleartext_unix,
TALLOC_CTX *mem_ctx, TALLOC_CTX *mem_ctx,
struct secrets_domain_info1 **pinfo, 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(); TALLOC_CTX *frame = talloc_stackframe();
struct db_context *db = NULL; 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; 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); *pinfo = talloc_move(mem_ctx, &info);
if (prev != NULL) { if (prev != NULL) {
*pprev = talloc_move(mem_ctx, &prev); *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, NTSTATUS secrets_finish_password_change(const char *change_server,
NTTIME change_time, 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; const char *domain = cookie->domain_info.name.string;
TALLOC_CTX *frame = talloc_stackframe(); TALLOC_CTX *frame = talloc_stackframe();
@ -2067,6 +2079,20 @@ NTSTATUS secrets_finish_password_change(const char *change_server,
return status; 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); ret = dbwrap_transaction_commit(db);
if (ret != 0) { if (ret != 0) {
DBG_ERR("dbwrap_transaction_commit() failed for %s\n", 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; 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); TALLOC_FREE(frame);
return NT_STATUS_OK; return NT_STATUS_OK;
} }

View File

@ -224,7 +224,13 @@ static int net_changesecretpw(struct net_context *c, int argc,
"localhost", "localhost",
trust_pw, trust_pw,
talloc_tos(), talloc_tos(),
&info, &prev); &info,
&prev,
#ifdef HAVE_ADS
sync_pw2keytabs);
#else
NULL);
#endif
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
d_fprintf(stderr, d_fprintf(stderr,
_("Unable to write the machine account password in the secrets database")); _("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; 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)) { if (!NT_STATUS_IS_OK(status)) {
d_fprintf(stderr, d_fprintf(stderr,
_("Unable to write the machine account password in the secrets database")); _("Unable to write the machine account password in the secrets database"));