[PATCH] automatic machine account password change for winbindd

Guenther Deschner gd at samba.org
Fri Aug 22 15:00:57 GMT 2008


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

$SUBJECT pretty much says it all. Given defaults, the patch will make
sure that the machine account password on a member server will get
changed once a week.

Sounds ok?

Guenther
- --
Günther Deschner                    GPG-ID: 8EE11688
Red Hat                         gdeschner at redhat.com
Samba Team                              gd at samba.org
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkiu1KgACgkQSOk3aI7hFoj0zACfaJo+Kt8nT3GxnVEo5k8O6gr5
HkYAn0+VXaHu3OMhBnYbWfuzGIwMnvu9
=D0xr
-----END PGP SIGNATURE-----
-------------- next part --------------
commit 6a24f1b1a1f0a5df935a00c0a1bc0b87a1b009ed
Author: Günther Deschner <gd at samba.org>
Date:   Thu Aug 21 01:20:22 2008 +0200

    winbindd: add event based machine password change.
    
    Guenther

diff --git a/source/winbindd/winbindd.h b/source/winbindd/winbindd.h
index 1b8cd91..04b0b39 100644
--- a/source/winbindd/winbindd.h
+++ b/source/winbindd/winbindd.h
@@ -153,6 +153,7 @@ struct winbindd_child {
 
 	struct fd_event event;
 	struct timed_event *lockout_policy_event;
+	struct timed_event *machine_password_change_event;
 	struct winbindd_async_request *requests;
 
 	const struct winbindd_child_dispatch_table *table;
diff --git a/source/winbindd/winbindd_dual.c b/source/winbindd/winbindd_dual.c
index 1e8325f..aa6da54 100644
--- a/source/winbindd/winbindd_dual.c
+++ b/source/winbindd/winbindd_dual.c
@@ -840,6 +840,110 @@ static void account_lockout_policy_handler(struct event_context *ctx,
 						      child);
 }
 
+static time_t get_machine_password_timeout(void)
+{
+	/* until we have gpo support use lp setting */
+	return lp_machine_password_timeout();
+}
+
+static bool calculate_next_machine_pwd_change(const char *domain,
+					      struct timeval *t)
+{
+	time_t pass_last_set_time;
+	time_t timeout;
+	time_t next_change;
+
+	if (!secrets_fetch_machine_password(domain,
+					    &pass_last_set_time,
+					    NULL)) {
+		DEBUG(0,("cannot fetch own machine password ????"));
+		return false;
+	}
+
+	timeout = get_machine_password_timeout();
+	if (timeout == 0) {
+		DEBUG(10,("machine password never expires\n"));
+		return false;
+	}
+
+	if (time(NULL) < (pass_last_set_time + timeout)) {
+		next_change = pass_last_set_time + timeout;
+		DEBUG(10,("machine password still valid until: %s\n",
+			http_timestring(next_change)));
+		*t = timeval_set(next_change, 0);
+		return true;
+	}
+
+	DEBUG(10,("machine password expired, needs immediate change\n"));
+
+	*t = timeval_zero();
+
+	return true;
+}
+
+static void machine_password_change_handler(struct event_context *ctx,
+					    struct timed_event *te,
+					    const struct timeval *now,
+					    void *private_data)
+{
+	struct winbindd_child *child =
+		(struct winbindd_child *)private_data;
+	struct rpc_pipe_client *netlogon_pipe = NULL;
+	TALLOC_CTX *mem_ctx = NULL;
+	NTSTATUS result;
+	struct timeval next_change;
+
+	DEBUG(10,("machine_password_change_handler called\n"));
+
+	TALLOC_FREE(child->machine_password_change_event);
+
+	if (!calculate_next_machine_pwd_change(child->domain->name,
+					       &next_change)) {
+		return;
+	}
+
+	if (!winbindd_can_contact_domain(child->domain)) {
+		DEBUG(10,("machine_password_change_handler: Removing myself since I "
+			  "do not have an incoming trust to domain %s\n",
+			  child->domain->name));
+		return;
+	}
+
+	mem_ctx = talloc_init("machine_password_change_handler ");
+	if (!mem_ctx) {
+		return;
+	}
+
+	result = cm_connect_netlogon(child->domain, &netlogon_pipe);
+	if (!NT_STATUS_IS_OK(result)) {
+		DEBUG(10,("machine_password_change_handler: "
+			"failed to connect netlogon pipe: %s\n",
+			 nt_errstr(result)));
+		TALLOC_FREE(mem_ctx);
+		return;
+	}
+
+	result = trust_pw_find_change_and_store_it(netlogon_pipe,
+						   mem_ctx,
+						   child->domain->name);
+	TALLOC_FREE(mem_ctx);
+
+	if (!NT_STATUS_IS_OK(result)) {
+		DEBUG(10,("machine_password_change_handler: "
+			"failed to change machine password: %s\n",
+			 nt_errstr(result)));
+	} else {
+		DEBUG(10,("machine_password_change_handler: "
+			"successfully changed machine password\n"));
+	}
+
+	child->machine_password_change_event = event_add_timed(winbind_event_context(), NULL,
+							      next_change,
+							      "machine_password_change_handler",
+							      machine_password_change_handler,
+							      child);
+}
+
 /* Deal with a request to go offline. */
 
 static void child_msg_offline(struct messaging_context *msg,
@@ -1138,6 +1242,21 @@ static bool fork_domain_child(struct winbindd_child *child)
 			child);
 	}
 
+	if (child->domain && !(child->domain->internal) &&
+	    lp_server_role() == ROLE_DOMAIN_MEMBER) {
+
+		struct timeval next_change;
+
+		if (calculate_next_machine_pwd_change(child->domain->name,
+						       &next_change)) {
+			child->machine_password_change_event = event_add_timed(
+				winbind_event_context(), NULL, next_change,
+				"machine_password_change_handler",
+				machine_password_change_handler,
+				child);
+		}
+	}
+
 	while (1) {
 
 		int ret;


More information about the samba-technical mailing list