[PATCH] Restructure winbind xids2sids

Volker Lendecke Volker.Lendecke at SerNet.DE
Mon Mar 28 19:22:53 UTC 2016


Hi!

This is a patchset that passes down the xids2sids operation from the
winbind frontend to the idmap backends.

Review appreciated!

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From e0111e47a0481cd5f5b25ab467c487c708b72abc Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 22 Feb 2016 17:03:43 +0100
Subject: [PATCH 1/8] idmap: Factor out lp_scan_idmap_domains()

This simplifies idmap_found_domain_backend() by moving the regex magic
somewhere else. Also, this routine will be useful soon somewhere else, thus
make it non-static to idmap.c.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/idmap.c          | 125 +++++++++++++++++++++++++-------------
 source3/winbindd/winbindd_proto.h |   3 +
 2 files changed, 87 insertions(+), 41 deletions(-)

diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c
index 7eb7e58..7b4ed4f 100644
--- a/source3/winbindd/idmap.c
+++ b/source3/winbindd/idmap.c
@@ -70,13 +70,71 @@ static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx,
 					      const char *domainname,
 					      const char *modulename,
 					      bool check_range);
-static bool idmap_found_domain_backend(
+
+struct lp_scan_idmap_domains_state {
+	bool (*fn)(const char *domname, void *private_data);
+	void *private_data;
+};
+
+static bool lp_scan_idmap_found_domain(
 	const char *string, regmatch_t matches[], void *private_data);
 
+bool lp_scan_idmap_domains(bool (*fn)(const char *domname,
+				      void *private_data),
+			   void *private_data)
+{
+	struct lp_scan_idmap_domains_state state = {
+		.fn = fn, .private_data = private_data };
+	int ret;
+
+	ret = lp_wi_scan_global_parametrics(
+		"idmapconfig\\(.*\\):backend", 2,
+		lp_scan_idmap_found_domain, &state);
+	if (ret != 0) {
+		DBG_WARNING("wi_scan_global_parametrics returned %d\n", ret);
+		return false;
+	}
+
+	return true;
+}
+
+static bool lp_scan_idmap_found_domain(
+	const char *string, regmatch_t matches[], void *private_data)
+{
+	bool ok;
+
+	if (matches[1].rm_so == -1) {
+		DBG_WARNING("Found match, but no name??\n");
+		return false;
+	}
+	if (matches[1].rm_eo <= matches[1].rm_so) {
+		DBG_WARNING("Invalid match\n");
+		return false;
+	}
+
+	{
+		struct lp_scan_idmap_domains_state *state = private_data;
+		regoff_t len = matches[1].rm_eo - matches[1].rm_so;
+		char domname[len+1];
+
+		memcpy(domname, string + matches[1].rm_so, len);
+		domname[len] = '\0';
+
+		DBG_DEBUG("Found idmap domain \"%s\"\n", domname);
+
+		ok = state->fn(domname, state->private_data);
+	}
+
+	return ok;
+}
+
+static bool idmap_found_domain_backend(const char *domname,
+				       void *private_data);
+
 static bool idmap_init(void)
 {
 	static bool initialized;
-	int ret;
+	bool ok;
 
 	if (initialized) {
 		return true;
@@ -109,11 +167,9 @@ static bool idmap_init(void)
 		return false;
 	}
 
-	ret = lp_wi_scan_global_parametrics(
-		"idmapconfig\\(.*\\):backend", 2,
-		idmap_found_domain_backend, NULL);
-	if (ret != 0) {
-		DBG_WARNING("wi_scan_global_parametrics returned %d\n", ret);
+	ok = lp_scan_idmap_domains(idmap_found_domain_backend, NULL);
+	if (!ok) {
+		DBG_WARNING("lp_scan_idmap_domains failed\n");
 		return false;
 	}
 
@@ -161,46 +217,33 @@ bool domain_has_idmap_config(const char *domname)
 	return false;
 }
 
-static bool idmap_found_domain_backend(
-	const char *string, regmatch_t matches[], void *private_data)
+static bool idmap_found_domain_backend(const char *domname,
+				       void *private_data)
 {
-	if (matches[1].rm_so == -1) {
-		DBG_WARNING("Found match, but no name??\n");
-		return false;
-	}
-
-	{
-		struct idmap_domain *dom, **tmp;
-		regoff_t len = matches[1].rm_eo - matches[1].rm_so;
-		char domname[len+1];
+	struct idmap_domain *dom, **tmp;
 
-		memcpy(domname, string + matches[1].rm_so, len);
-		domname[len] = '\0';
+	DBG_DEBUG("Found idmap domain \"%s\"\n", domname);
 
-		DBG_DEBUG("Found idmap domain \"%s\"\n", domname);
-
-		if (strcmp(domname, "*") == 0) {
-			return false;
-		}
+	if (strcmp(domname, "*") == 0) {
+		return false;
+	}
 
-		dom = idmap_init_named_domain(idmap_domains, domname);
-		if (dom == NULL) {
-			DBG_NOTICE("Could not init idmap domain %s\n",
-				   domname);
-			return false;
-		}
+	dom = idmap_init_named_domain(idmap_domains, domname);
+	if (dom == NULL) {
+		DBG_NOTICE("Could not init idmap domain %s\n", domname);
+		return false;
+	}
 
-		tmp = talloc_realloc(idmap_domains, idmap_domains,
-				     struct idmap_domain *, num_domains + 1);
-		if (tmp == NULL) {
-			DBG_WARNING("talloc_realloc failed\n");
-			TALLOC_FREE(dom);
-			return false;
-		}
-		idmap_domains = tmp;
-		idmap_domains[num_domains] = dom;
-		num_domains += 1;
+	tmp = talloc_realloc(idmap_domains, idmap_domains,
+			     struct idmap_domain *, num_domains + 1);
+	if (tmp == NULL) {
+		DBG_WARNING("talloc_realloc failed\n");
+		TALLOC_FREE(dom);
+		return false;
 	}
+	idmap_domains = tmp;
+	idmap_domains[num_domains] = dom;
+	num_domains += 1;
 
 	return false;
 }
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 12629ff..7c9a924 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -331,6 +331,9 @@ struct winbindd_child *idmap_child(void);
 struct idmap_domain *idmap_find_domain_with_sid(const char *domname,
 						const struct dom_sid *sid);
 bool domain_has_idmap_config(const char *domname);
+bool lp_scan_idmap_domains(bool (*fn)(const char *domname,
+				      void *private_data),
+			   void *private_data);
 
 /* The following definitions come from winbindd/winbindd_locator.c  */
 
-- 
2.1.4


From d56c969b2216a44e2f3bc000acedcf56952752e4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 4 Mar 2016 14:23:51 +0100
Subject: [PATCH 2/8] winbind: Introduce id_map_ptrs_init

This simplifies _wbint_Sids2UnixIDs a bit and will be re-used in _wbint_UnixIDs2Sids

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/idmap_proto.h       |  2 ++
 source3/winbindd/idmap_util.c        | 31 +++++++++++++++++++++++++++++++
 source3/winbindd/winbindd_dual_srv.c | 33 ++++++++-------------------------
 3 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index a12e5b4..0e124cd 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -59,6 +59,8 @@ struct id_map *idmap_find_map_by_sid(struct id_map **maps, struct dom_sid *sid);
 char *idmap_fetch_secret(const char *backend, const char *domain,
 			 const char *identity);
 
+struct id_map **id_map_ptrs_init(TALLOC_CTX *mem_ctx, size_t num_ids);
+
 /* max number of ids requested per LDAP batch query */
 #define IDMAP_LDAP_MAX_IDS 30
 
diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c
index f90565f..7591530 100644
--- a/source3/winbindd/idmap_util.c
+++ b/source3/winbindd/idmap_util.c
@@ -238,3 +238,34 @@ char *idmap_fetch_secret(const char *backend, const char *domain,
 
 	return ret;
 }
+
+struct id_map **id_map_ptrs_init(TALLOC_CTX *mem_ctx, size_t num_ids)
+{
+	struct id_map **ptrs;
+	struct id_map *maps;
+	struct dom_sid *sids;
+	size_t i;
+
+	ptrs = talloc_array(mem_ctx, struct id_map *, num_ids+1);
+	if (ptrs == NULL) {
+		return NULL;
+	}
+	maps = talloc_array(ptrs, struct id_map, num_ids);
+	if (maps == NULL) {
+		TALLOC_FREE(ptrs);
+		return NULL;
+	}
+	sids = talloc_zero_array(ptrs, struct dom_sid, num_ids);
+	if (sids == NULL) {
+		TALLOC_FREE(ptrs);
+		return NULL;
+	}
+
+	for (i=0; i<num_ids; i++) {
+		maps[i] = (struct id_map) { .sid = &sids[i] };
+		ptrs[i] = &maps[i];
+	}
+	ptrs[num_ids] = NULL;
+
+	return ptrs;
+}
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index e42dce5..7c415e6 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -127,9 +127,7 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
 	struct wbint_TransID *ids;
 	uint32_t num_ids;
 
-	struct id_map *id_maps = NULL;
 	struct id_map **id_map_ptrs = NULL;
-	struct dom_sid *sids = NULL;
 	struct idmap_domain *dom;
 	NTSTATUS status = NT_STATUS_NO_MEMORY;
 
@@ -157,18 +155,10 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
 		return NT_STATUS_OK;
 	}
 
-	id_maps = talloc_array(talloc_tos(), struct id_map, num_ids);
-	if (id_maps == NULL) {
-		goto nomem;
-	}
-	id_map_ptrs = talloc_array(talloc_tos(), struct id_map *, num_ids+1);
+	id_map_ptrs = id_map_ptrs_init(talloc_tos(), num_ids);
 	if (id_map_ptrs == NULL) {
 		goto nomem;
 	}
-	sids = talloc_array(talloc_tos(), struct dom_sid, num_ids);
-	if (sids == NULL) {
-		goto nomem;
-	}
 
 	/*
 	 * Convert the input data into a list of id_map structs
@@ -177,18 +167,12 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
 	 */
 
 	for (i=0; i<num_ids; i++) {
+		struct id_map *m = id_map_ptrs[i];
 
-		sid_compose(&sids[i], d->sid, ids[i].rid);
-
-		id_maps[i] = (struct id_map) {
-			.sid = &sids[i],
-			.xid.type = ids[i].type,
-			.status = ID_UNKNOWN
-		};
-
-		id_map_ptrs[i] = &id_maps[i];
+		sid_compose(m->sid, d->sid, ids[i].rid);
+		m->status = ID_UNKNOWN;
+		m->xid = (struct unixid) { .type = ids[i].type };
 	}
-	id_map_ptrs[num_ids] = NULL;
 
 	status = dom->methods->sids_to_unixids(dom, id_map_ptrs);
 
@@ -203,9 +187,10 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
 	 */
 
 	for (i=0; i<num_ids; i++) {
+		struct id_map *m = id_map_ptrs[i];
 
-		if (id_maps[i].status == ID_MAPPED) {
-			ids[i].xid = id_maps[i].xid;
+		if (m->status == ID_MAPPED) {
+			ids[i].xid = m->xid;
 		} else {
 			ids[i].xid.id = UINT32_MAX;
 			ids[i].xid.type = ID_TYPE_NOT_SPECIFIED;
@@ -216,9 +201,7 @@ NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
 nomem:
 	status = NT_STATUS_NO_MEMORY;
 done:
-	TALLOC_FREE(id_maps);
 	TALLOC_FREE(id_map_ptrs);
-	TALLOC_FREE(sids);
 	return status;
 }
 
-- 
2.1.4


From ad082278a1378ff25599877734d276c7714e76b8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 1 Mar 2016 14:34:26 +0100
Subject: [PATCH 3/8] winbind: Do per-domain xids2sids calls

This prepares the equivalent of 2b1dd01934b657a for xids2sids.

Collecting sids2xids per domain is a bit easier: SIDs carry their own domain
prefix. For the reverse, we need to scan the configuration for all the idmap
range definitions.

It has a separate effect: It enables overlapping idmap ranges. The per-domain
calls are done whenever a range matches. If the idmap child finds a successful
xid2sid mapping, this will be collected as one result. This means that every
range definition can contribute mappings.

If there are two rfc2307 sfu domains with overlapping ranges, the domains will
be queried one after the other for a specific mapping. If the defined ranges
overlap, the admin has to make sure that there are no conflicts, because in the
current code "the first writer wins", and the code does not specify an order
(yet).

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/wb_xids2sids.c | 280 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 270 insertions(+), 10 deletions(-)

diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c
index 6c3f0f6..7328f1e 100644
--- a/source3/winbindd/wb_xids2sids.c
+++ b/source3/winbindd/wb_xids2sids.c
@@ -23,8 +23,244 @@
 #include "idmap_cache.h"
 #include "librpc/gen_ndr/ndr_winbind_c.h"
 
+struct wb_xids2sids_dom_map {
+	unsigned low_id;
+	unsigned high_id;
+	const char *name;
+};
+
+/*
+ * Map idmap ranges to domain names, taken from smb.conf. This is
+ * stored in the parent winbind and used to assemble xid2sid calls
+ * into per-idmap-domain chunks.
+ */
+static struct wb_xids2sids_dom_map *dom_maps;
+
+static bool wb_xids2sids_add_dom(const char *domname,
+				 void *private_data)
+{
+	struct wb_xids2sids_dom_map *map = NULL;
+	size_t num_maps = talloc_array_length(dom_maps);
+	size_t i;
+	char *config_option;
+	const char *range;
+	unsigned low_id, high_id;
+	int ret;
+
+	config_option = talloc_asprintf(
+		talloc_tos(), "idmap config %s", domname);
+	if (config_option == NULL) {
+		return false;
+	}
+	range = lp_parm_const_string(-1, config_option, "range", NULL);
+	TALLOC_FREE(config_option);
+
+	if (range == NULL) {
+		DBG_DEBUG("No range for domain %s found\n", domname);
+		return false;
+	}
+
+	ret = sscanf(range, "%u - %u", &low_id, &high_id);
+	if (ret != 2) {
+		DBG_DEBUG("Invalid range spec \"%s\" for domain %s\n",
+			  range, domname);
+		return false;
+	}
+
+	if (low_id > high_id) {
+		DBG_DEBUG("Invalid range %u - %u for domain %s\n",
+			  low_id, high_id, domname);
+		return false;
+	}
+
+	for (i=0; i<num_maps; i++) {
+		if (strequal(domname, dom_maps[i].name)) {
+			map = &dom_maps[i];
+			break;
+		}
+	}
+
+	if (map == NULL) {
+		struct wb_xids2sids_dom_map *tmp;
+		char *name;
+
+		name = talloc_strdup(talloc_tos(), domname);
+		if (name == NULL) {
+			DBG_DEBUG("talloc failed\n");
+			return false;
+		}
+
+		tmp = talloc_realloc(
+			NULL, dom_maps, struct wb_xids2sids_dom_map,
+			num_maps+1);
+		if (tmp == NULL) {
+			TALLOC_FREE(name);
+			return false;
+		}
+		dom_maps = tmp;
+
+		map = &dom_maps[num_maps];
+		map->name = talloc_move(dom_maps, &name);
+	}
+
+	map->low_id = low_id;
+	map->high_id = high_id;
+
+	return false;
+}
+
+static void wb_xids2sids_init_dom_maps(void)
+{
+	if (dom_maps != NULL) {
+		return;
+	}
+
+	/*
+	 * Put the passdb idmap domain first. We always need to try
+	 * there first.
+	 */
+
+	dom_maps = talloc_array(NULL, struct wb_xids2sids_dom_map, 1);
+	if (dom_maps == NULL) {
+		return;
+	}
+	dom_maps[0].low_id = 0;
+	dom_maps[0].high_id = UINT_MAX;
+	dom_maps[0].name = talloc_strdup(dom_maps, get_global_sam_name());
+	if (dom_maps[0].name == NULL) {
+		TALLOC_FREE(dom_maps);
+		return;
+	}
+
+	lp_scan_idmap_domains(wb_xids2sids_add_dom, NULL);
+}
+
+struct wb_xids2sids_dom_state {
+	struct unixid *all_xids;
+	size_t num_all_xids;
+	struct dom_sid *all_sids;
+	struct wb_xids2sids_dom_map *dom_map;
+
+	size_t num_dom_xids;
+	struct unixid *dom_xids;
+	struct dom_sid *dom_sids;
+};
+
+static void wb_xids2sids_dom_done(struct tevent_req *subreq);
+
+static struct tevent_req *wb_xids2sids_dom_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	struct wb_xids2sids_dom_map *dom_map,
+	struct unixid *xids, size_t num_xids, struct dom_sid *sids)
+{
+	struct tevent_req *req, *subreq;
+	struct wb_xids2sids_dom_state *state;
+	struct winbindd_child *child;
+	size_t i;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct wb_xids2sids_dom_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->all_xids = xids;
+	state->num_all_xids = num_xids;
+	state->all_sids = sids;
+	state->dom_map = dom_map;
+
+	state->dom_xids = talloc_array(state, struct unixid, num_xids);
+	if (tevent_req_nomem(state->dom_xids, req)) {
+		return tevent_req_post(req, ev);
+	}
+	state->dom_sids = talloc_array(state, struct dom_sid, num_xids);
+	if (tevent_req_nomem(state->dom_sids, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	for (i=0; i<num_xids; i++) {
+		struct unixid id = state->all_xids[i];
+
+		if ((id.id < dom_map->low_id) || (id.id > dom_map->high_id)) {
+			/* out of range */
+			continue;
+		}
+		if (!is_null_sid(&state->all_sids[i])) {
+			/* already mapped */
+			continue;
+		}
+
+		state->dom_xids[state->num_dom_xids++] = id;
+	}
+
+	if (state->num_dom_xids == 0) {
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
+	}
+
+	child = idmap_child();
+	subreq = dcerpc_wbint_UnixIDs2Sids_send(
+		state, ev, child->binding_handle,
+		state->num_dom_xids, state->dom_xids, state->dom_sids);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, wb_xids2sids_dom_done, req);
+	return req;
+}
+
+static void wb_xids2sids_dom_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct wb_xids2sids_dom_state *state = tevent_req_data(
+		req, struct wb_xids2sids_dom_state);
+	struct wb_xids2sids_dom_map *dom_map = state->dom_map;
+	NTSTATUS status, result;
+	size_t i;
+	size_t dom_sid_idx;
+
+	status = dcerpc_wbint_UnixIDs2Sids_recv(subreq, state, &result);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+	if (!NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) &&
+	    tevent_req_nterror(req, result)) {
+		return;
+	}
+
+	dom_sid_idx = 0;
+
+	for (i=0; i<state->num_all_xids; i++) {
+		struct unixid id = state->all_xids[i];
+
+		if ((id.id < dom_map->low_id) || (id.id > dom_map->high_id)) {
+			/* out of range */
+			continue;
+		}
+		if (!is_null_sid(&state->all_sids[i])) {
+			/* already mapped */
+			continue;
+		}
+
+		sid_copy(&state->all_sids[i], &state->dom_sids[dom_sid_idx++]);
+	}
+
+	tevent_req_done(req);
+}
+
+static NTSTATUS wb_xids2sids_dom_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
 struct wb_xids2sids_state {
+	struct tevent_context *ev;
+	struct unixid *xids;
+	size_t num_xids;
 	struct dom_sid *sids;
+
+	size_t dom_idx;
 };
 
 static void wb_xids2sids_done(struct tevent_req *subreq);
@@ -36,23 +272,33 @@ struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx,
 {
 	struct tevent_req *req, *subreq;
 	struct wb_xids2sids_state *state;
-	struct winbindd_child *child;
+	size_t num_domains;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct wb_xids2sids_state);
 	if (req == NULL) {
 		return NULL;
 	}
+	state->ev = ev;
+	state->xids = xids;
+	state->num_xids = num_xids;
 
-	state->sids = talloc_array(state, struct dom_sid, num_xids);
+	state->sids = talloc_zero_array(state, struct dom_sid, num_xids);
 	if (tevent_req_nomem(state->sids, req)) {
 		return tevent_req_post(req, ev);
 	}
 
-	child = idmap_child();
+	wb_xids2sids_init_dom_maps();
+	num_domains = talloc_array_length(dom_maps);
 
-	subreq = dcerpc_wbint_UnixIDs2Sids_send(
-		state, ev, child->binding_handle, num_xids, xids, state->sids);
+	if (num_domains == 0) {
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = wb_xids2sids_dom_send(
+		state, state->ev, &dom_maps[state->dom_idx],
+		state->xids, state->num_xids, state->sids);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -66,15 +312,29 @@ static void wb_xids2sids_done(struct tevent_req *subreq)
 		subreq, struct tevent_req);
 	struct wb_xids2sids_state *state = tevent_req_data(
 		req, struct wb_xids2sids_state);
-	NTSTATUS status, result;
+	size_t num_domains = talloc_array_length(dom_maps);
+	NTSTATUS status;
 
-	status = dcerpc_wbint_UnixIDs2Sids_recv(subreq, state, &result);
+	status = wb_xids2sids_dom_recv(subreq);
 	TALLOC_FREE(subreq);
-	if (any_nt_status_not_ok(status, result, &status)) {
-		tevent_req_nterror(req, status);
+	if (tevent_req_nterror(req, status)) {
 		return;
 	}
-	tevent_req_done(req);
+
+	state->dom_idx += 1;
+
+	if (state->dom_idx >= num_domains) {
+		tevent_req_done(req);
+		return;
+	}
+
+	subreq = wb_xids2sids_dom_send(
+		state, state->ev, &dom_maps[state->dom_idx],
+		state->xids, state->num_xids, state->sids);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, wb_xids2sids_done, req);
 }
 
 NTSTATUS wb_xids2sids_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-- 
2.1.4


From 38af381db173569f6b0878801ec632560b508291 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 4 Mar 2016 15:03:08 +0100
Subject: [PATCH 4/8] winbind: Add idmap_backend_unixids_to_sids

This is the plural version of idmap_backends_unixid_to_sid that expects all ids
to come from the same idmap domain. The singular version walks the domain list
itself, this one expects the domain name to be passed to it.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/idmap.c       | 31 +++++++++++++++++++++++++++++++
 source3/winbindd/idmap_proto.h |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c
index 7b4ed4f..0ff35ca 100644
--- a/source3/winbindd/idmap.c
+++ b/source3/winbindd/idmap.c
@@ -25,6 +25,7 @@
 #include "winbindd.h"
 #include "idmap.h"
 #include "lib/util_sid_passdb.h"
+#include "libcli/security/dom_sid.h"
 #include "passdb.h"
 
 #undef DBGC_CLASS
@@ -587,6 +588,36 @@ NTSTATUS idmap_allocate_gid(struct unixid *id)
 	return idmap_allocate_unixid(id);
 }
 
+NTSTATUS idmap_backend_unixids_to_sids(struct id_map **maps,
+				       const char *domain_name)
+{
+	struct idmap_domain *dom = NULL;
+	NTSTATUS status;
+	bool ok;
+
+	ok = idmap_init();
+	if (!ok) {
+		return NT_STATUS_NONE_MAPPED;
+	}
+
+	if (strequal(domain_name, get_global_sam_name())) {
+		dom = passdb_idmap_domain;
+	}
+	if (dom == NULL) {
+		dom = idmap_find_domain(domain_name);
+	}
+	if (dom == NULL) {
+		return NT_STATUS_NONE_MAPPED;
+	}
+
+	status = dom->methods->unixids_to_sids(dom, maps);
+
+	DBG_DEBUG("unixid_to_sids for domain %s returned %s\n",
+		  domain_name, nt_errstr(status));
+
+	return status;
+}
+
 NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id)
 {
 	struct idmap_domain *dom;
diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index 0e124cd..78a5c41 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -35,6 +35,8 @@ void idmap_close(void);
 NTSTATUS idmap_allocate_uid(struct unixid *id);
 NTSTATUS idmap_allocate_gid(struct unixid *id);
 NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id);
+NTSTATUS idmap_backend_unixids_to_sids(struct id_map **maps,
+				       const char *domain_name);
 
 /* The following definitions come from winbindd/idmap_nss.c  */
 
-- 
2.1.4


From 746d4fb8b0ea9db309d0391f617e28de6eb96a48 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 16 Mar 2016 15:25:35 +0100
Subject: [PATCH 5/8] winbind: Pass down the domain name to xids2sids

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 librpc/idl/winbind.idl          | 1 +
 source3/winbindd/wb_xids2sids.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl
index b1aed30..60c875b 100644
--- a/librpc/idl/winbind.idl
+++ b/librpc/idl/winbind.idl
@@ -57,6 +57,7 @@ interface winbind
 	);
 
     NTSTATUS wbint_UnixIDs2Sids(
+	[in,string,charset(UTF8)] char *domain_name,
 	[in] uint32 num_ids,
 	[in] unixid xids[num_ids],
 	[out] dom_sid sids[num_ids]
diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c
index 7328f1e..77372f7 100644
--- a/source3/winbindd/wb_xids2sids.c
+++ b/source3/winbindd/wb_xids2sids.c
@@ -199,7 +199,7 @@ static struct tevent_req *wb_xids2sids_dom_send(
 
 	child = idmap_child();
 	subreq = dcerpc_wbint_UnixIDs2Sids_send(
-		state, ev, child->binding_handle,
+		state, ev, child->binding_handle, dom_map->name,
 		state->num_dom_xids, state->dom_xids, state->dom_sids);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
-- 
2.1.4


From 21d0bf81b529280aa5ce1c726ea70b0cbeac79a7 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 4 Mar 2016 15:45:24 +0100
Subject: [PATCH 6/8] winbind: Use plural xids2sids in _wbint_UnixIDs2Sids

We've had plural xid2sid idmap backends for a while. Start using
them.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/winbindd_dual_srv.c | 38 +++++++++++++++++++-----------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 7c415e6..fb65e9d 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -208,30 +208,32 @@ done:
 NTSTATUS _wbint_UnixIDs2Sids(struct pipes_struct *p,
 			     struct wbint_UnixIDs2Sids *r)
 {
+	struct id_map **maps;
+	NTSTATUS status;
 	uint32_t i;
 
+	maps = id_map_ptrs_init(talloc_tos(), r->in.num_ids);
+	if (maps == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
 	for (i=0; i<r->in.num_ids; i++) {
-		struct unixid *xid = &r->in.xids[i];
-		struct dom_sid *sid = &r->out.sids[i];
-		NTSTATUS status;
-
-		switch (xid->type) {
-		    case ID_TYPE_UID:
-			    status = idmap_uid_to_sid(sid, xid->id);
-			    break;
-		    case ID_TYPE_GID:
-			    status = idmap_gid_to_sid(sid, xid->id);
-			    break;
-		    default:
-			    status = NT_STATUS_NONE_MAPPED;
-			    break;
-		}
+		maps[i]->status = ID_UNKNOWN;
+		maps[i]->xid = r->in.xids[i];
+	}
 
-		if (!NT_STATUS_IS_OK(status)) {
-			*sid = (struct dom_sid) {0};
-		}
+	status = idmap_backend_unixids_to_sids(maps, r->in.domain_name);
+	if (!NT_STATUS_IS_OK(status)) {
+		TALLOC_FREE(maps);
+		return status;
 	}
 
+	for (i=0; i<r->in.num_ids; i++) {
+		sid_copy(&r->out.sids[i], maps[i]->sid);
+	}
+
+	TALLOC_FREE(maps);
+
 	return NT_STATUS_OK;
 }
 
-- 
2.1.4


From 20841ddd11d46b2a4bb7ef9c4e0297512ac29563 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 16 Mar 2016 15:33:48 +0100
Subject: [PATCH 7/8] winbind: Remove unused idmap_[ug]id_to_sid

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/winbindd/idmap_proto.h |   2 -
 source3/winbindd/idmap_util.c  | 126 -----------------------------------------
 2 files changed, 128 deletions(-)

diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index 78a5c41..c690d27 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -52,8 +52,6 @@ NTSTATUS idmap_tdb_init(void);
 
 /* The following definitions come from winbindd/idmap_util.c  */
 
-NTSTATUS idmap_uid_to_sid(struct dom_sid *sid, uid_t uid);
-NTSTATUS idmap_gid_to_sid(struct dom_sid *sid, gid_t gid);
 bool idmap_unix_id_is_in_range(uint32_t id, struct idmap_domain *dom);
 struct id_map *idmap_find_map_by_id(struct id_map **maps, enum id_type type,
 				    uint32_t id);
diff --git a/source3/winbindd/idmap_util.c b/source3/winbindd/idmap_util.c
index 7591530..3da39e8 100644
--- a/source3/winbindd/idmap_util.c
+++ b/source3/winbindd/idmap_util.c
@@ -29,132 +29,6 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
 
-/*****************************************************************
- Returns the SID mapped to the given UID.
- If mapping is not possible returns an error.
-*****************************************************************/
-
-NTSTATUS idmap_uid_to_sid(struct dom_sid *sid, uid_t uid)
-{
-	NTSTATUS ret;
-	struct id_map map;
-	bool expired;
-
-	DEBUG(10, ("idmap_uid_to_sid: uid = [%lu]\n", (unsigned long)uid));
-
-	if (winbindd_use_idmap_cache()
-	    && idmap_cache_find_uid2sid(uid, sid, &expired)) {
-		DEBUG(10, ("idmap_cache_find_uid2sid found %u%s\n",
-			(unsigned int)uid,
-			   expired ? " (expired)": ""));
-		if (expired && idmap_is_online()) {
-			DEBUG(10, ("revalidating expired entry\n"));
-			goto backend;
-		}
-		if (is_null_sid(sid)) {
-			DEBUG(10, ("Returning negative cache entry\n"));
-			return NT_STATUS_NONE_MAPPED;
-		}
-		DEBUG(10, ("Returning positive cache entry\n"));
-		return NT_STATUS_OK;
-	}
-
-backend:
-	ZERO_STRUCT(map);
-	map.sid = sid;
-	map.xid.type = ID_TYPE_UID;
-	map.xid.id = uid;
-
-	ret = idmap_backends_unixid_to_sid(&map);
-	if ( ! NT_STATUS_IS_OK(ret)) {
-		DEBUG(10, ("error mapping uid [%lu]: %s\n", (unsigned long)uid,
-			   nt_errstr(ret)));
-		map.status = ID_UNMAPPED;
-	}
-
-	if (map.status != ID_MAPPED) {
-		if (winbindd_use_idmap_cache()) {
-			struct dom_sid null_sid;
-			struct unixid id;
-			id.type = ID_TYPE_UID;
-			id.id = uid;
-			ZERO_STRUCT(null_sid);
-			idmap_cache_set_sid2unixid(&null_sid, &id);
-		}
-		DEBUG(10, ("uid [%lu] not mapped\n", (unsigned long)uid));
-		return NT_STATUS_NONE_MAPPED;
-	}
-
-	if (winbindd_use_idmap_cache()) {
-		idmap_cache_set_sid2unixid(sid, &map.xid);
-	}
-
-	return NT_STATUS_OK;
-}
-
-/*****************************************************************
- Returns SID mapped to the given GID.
- If mapping is not possible returns an error.
-*****************************************************************/
-
-NTSTATUS idmap_gid_to_sid(struct dom_sid *sid, gid_t gid)
-{
-	NTSTATUS ret;
-	struct id_map map;
-	bool expired;
-
-	DEBUG(10, ("idmap_gid_to_sid: gid = [%lu]\n", (unsigned long)gid));
-
-	if (winbindd_use_idmap_cache()
-	    && idmap_cache_find_gid2sid(gid, sid, &expired)) {
-		DEBUG(10, ("idmap_cache_find_gid2sid found %u%s\n",
-			(unsigned int)gid,
-			   expired ? " (expired)": ""));
-		if (expired && idmap_is_online()) {
-			DEBUG(10, ("revalidating expired entry\n"));
-			goto backend;
-		}
-		if (is_null_sid(sid)) {
-			DEBUG(10, ("Returning negative cache entry\n"));
-			return NT_STATUS_NONE_MAPPED;
-		}
-		DEBUG(10, ("Returning positive cache entry\n"));
-		return NT_STATUS_OK;
-	}
-
-backend:
-	ZERO_STRUCT(map);
-	map.sid = sid;
-	map.xid.type = ID_TYPE_GID;
-	map.xid.id = gid;
-
-	ret = idmap_backends_unixid_to_sid(&map);
-	if ( ! NT_STATUS_IS_OK(ret)) {
-		DEBUG(10, ("error mapping gid [%lu]: %s\n", (unsigned long)gid,
-			   nt_errstr(ret)));
-		map.status = ID_UNMAPPED;
-	}
-
-	if (map.status != ID_MAPPED) {
-		if (winbindd_use_idmap_cache()) {
-			struct dom_sid null_sid;
-			struct unixid id;
-			id.type = ID_TYPE_GID;
-			id.id = gid;
-			ZERO_STRUCT(null_sid);
-			idmap_cache_set_sid2unixid(&null_sid, &id);
-		}
-		DEBUG(10, ("gid [%lu] not mapped\n", (unsigned long)gid));
-		return NT_STATUS_NONE_MAPPED;
-	}
-
-	if (winbindd_use_idmap_cache()) {
-		idmap_cache_set_sid2unixid(sid, &map.xid);
-	}
-
-	return NT_STATUS_OK;
-}
-
 /**
  * check whether a given unix id is inside the filter range of an idmap domain
  */
-- 
2.1.4


From 3a2c0371f52be96c79f198bc22f9055a8caac111 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 16 Mar 2016 15:35:51 +0100
Subject: [PATCH 8/8] winbind: Remove unused idmap_backends_unixid_to_sid

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/torture/test_idmap_tdb_common.c |  5 ----
 source3/winbindd/idmap.c                | 46 ---------------------------------
 source3/winbindd/idmap_proto.h          |  1 -
 3 files changed, 52 deletions(-)

diff --git a/source3/torture/test_idmap_tdb_common.c b/source3/torture/test_idmap_tdb_common.c
index dd736ad..897d217 100644
--- a/source3/torture/test_idmap_tdb_common.c
+++ b/source3/torture/test_idmap_tdb_common.c
@@ -62,11 +62,6 @@ bool idmap_is_online(void)
 	return true;
 }
 
-NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id)
-{
-	return NT_STATUS_OK;
-}
-
 static bool open_db(struct idmap_tdb_common_context *ctx)
 {
 	NTSTATUS status;
diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c
index 0ff35ca..84834f1 100644
--- a/source3/winbindd/idmap.c
+++ b/source3/winbindd/idmap.c
@@ -617,49 +617,3 @@ NTSTATUS idmap_backend_unixids_to_sids(struct id_map **maps,
 
 	return status;
 }
-
-NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id)
-{
-	struct idmap_domain *dom;
-	struct id_map *maps[2];
-	bool ok;
-	int i;
-
-	ok = idmap_init();
-	if (!ok) {
-		return NT_STATUS_NONE_MAPPED;
-	}
-
-	DEBUG(10, ("idmap_backend_unixid_to_sid: xid = %d (type %d)\n",
-		   id->xid.id, id->xid.type));
-
-	maps[0] = id;
-	maps[1] = NULL;
-
-	/*
-	 * Always give passdb a chance first
-	 */
-
-	dom = passdb_idmap_domain;
-	if ((dom != NULL)
-	    && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))
-	    && id->status == ID_MAPPED) {
-		return NT_STATUS_OK;
-	}
-
-	dom = default_idmap_domain;
-
-	for (i=0; i<num_domains; i++) {
-		if ((id->xid.id >= idmap_domains[i]->low_id) &&
-		    (id->xid.id <= idmap_domains[i]->high_id)) {
-			dom = idmap_domains[i];
-			break;
-		}
-	}
-
-	if (dom == NULL) {
-		return NT_STATUS_NONE_MAPPED;
-	}
-
-	return dom->methods->unixids_to_sids(dom, maps);
-}
diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index c690d27..ea96d72 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -34,7 +34,6 @@ NTSTATUS smb_register_idmap(int version, const char *name,
 void idmap_close(void);
 NTSTATUS idmap_allocate_uid(struct unixid *id);
 NTSTATUS idmap_allocate_gid(struct unixid *id);
-NTSTATUS idmap_backends_unixid_to_sid(struct id_map *id);
 NTSTATUS idmap_backend_unixids_to_sids(struct id_map **maps,
 				       const char *domain_name);
 
-- 
2.1.4



More information about the samba-technical mailing list