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,
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);
#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"
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));
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));
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));
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);
}
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);
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;
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);
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();
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",
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;
}
"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"));
}
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"));