1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +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,
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);

View File

@ -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));

View File

@ -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);

View File

@ -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;
}

View File

@ -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"));