From 3812930e641d10d1ead10b52ddc7240dd585d0f6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 11 Sep 2020 15:42:42 +0200
Subject: [PATCH 016/266] CVE-2020-25717 winbindd: defer the setup_child() from
 init_idmap_child()

At startup we trigger a wb_parent_idmap_setup_send() and make
sure setup_child() is called just before wb_parent_idmap_setup_recv()
finished.

This makes sure our view of the idmap config in the parent matches
what we have in the child.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

(cherry picked from commit 28e020c0a863411cfa95e3b1ed943d922b8635bd)
---
 source3/winbindd/winbindd_idmap.c | 45 ++++++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 3 deletions(-)

Conflict:NA
Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=3812930e641d10d1ead10b52ddc7240dd585d0f6

diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c
index 14836e3b8a0..3e2461478a9 100644
--- a/source3/winbindd/winbindd_idmap.c
+++ b/source3/winbindd/winbindd_idmap.c
@@ -81,11 +81,44 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = {
 	}
 };
 
+static void init_idmap_child_done(struct tevent_req *subreq);
+
 void init_idmap_child(void)
 {
-	setup_child(NULL, &static_idmap_child,
-		    idmap_dispatch_table,
-		    "log.winbindd", "idmap");
+	struct tevent_req *subreq = NULL;
+
+	subreq = wb_parent_idmap_setup_send(global_event_context(),
+					    global_event_context());
+	if (subreq == NULL) {
+		/*
+		 * This is only an optimization, so we're free to
+		 * to ignore errors
+		 */
+		DBG_ERR("wb_parent_idmap_setup_send() failed\n");
+		return;
+	}
+	tevent_req_set_callback(subreq, init_idmap_child_done, NULL);
+	DBG_DEBUG("wb_parent_idmap_setup_send() started\n");
+}
+
+static void init_idmap_child_done(struct tevent_req *subreq)
+{
+	const struct wb_parent_idmap_config *cfg = NULL;
+	NTSTATUS status;
+
+	status = wb_parent_idmap_setup_recv(subreq, &cfg);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * This is only an optimization, so we're free to
+		 * to ignore errors
+		 */
+		DBG_ERR("wb_parent_idmap_setup_recv() failed %s\n",
+			nt_errstr(status));
+		return;
+	}
+
+	DBG_DEBUG("wb_parent_idmap_setup_recv() finished\n");
 }
 
 struct wb_parent_idmap_setup_state {
@@ -306,6 +339,12 @@ static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req)
 
  next_domain:
 	if (state->dom_idx == state->cfg->num_doms) {
+		/*
+		 * We're done, so start the idmap child
+		 */
+		setup_child(NULL, &static_idmap_child,
+			    idmap_dispatch_table,
+			    "log.winbindd", "idmap");
 		tevent_req_done(req);
 		return;
 	}
-- 
2.23.0

