[PATCH] Restructure winbind xids2sids

Jeremy Allison jra at samba.org
Wed Mar 30 00:03:19 UTC 2016


On Mon, Mar 28, 2016 at 09:22:53PM +0200, Volker Lendecke wrote:
> Hi!
> 
> This is a patchset that passes down the xids2sids operation from the
> winbind frontend to the idmap backends.
> 
> Review appreciated!

OK, spent a lot of time going through it (sorry for
the initial mistake on the talloc heirarchy).

Took me a while to spot the clever bit of

wb_xids2sids_send()
  |
  --> wb_xids2sids_dom_send()
     |
     ---> wb_xids2sids_done()

	which can then re-call wb_xids2sids_dom_send()
				|
				--> wb_xids2sids_done()

to deal with the rest of the (unanswered) domain xid's
without recursion and using multiple tevent reqs.

Really nice work !!!!

Reviewed-by: Jeremy Allison <jra at samba.org>

> -- 
> 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

> 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