[PATCHES] authenticating users during short disconnects from AD

Uri Simchoni uri at samba.org
Tue Dec 27 19:26:30 UTC 2016


Hi,

The following patch set allows Samba, running as an AD member file
server, to authenticate new users using Kerberos without contacting AD.
This helps operating in sites with frequent short disconnects from AD,
e.g. if someone moves between rooms, the connection needs to be
re-established, and the client has a cached ticket to the server.

With Windows servers, it is possible for a file server to authenticate
using Kerberos and serve files without an AD connection - because all
the required info is in the PAC.

With Samba, there's the added step of converting the NT access token to
a POSIX process token - to a list of POSIX id's associated with the
session. This may or may not be possible without a connection to AD,
depending on the idmap backends involved.

The patch set enables offline operation using passdb and rid backends.
Other backends currently require to know the sid type, at least in the
cased where they allocate a new mapping.

Patches 1-4 - an assortment of barriers towards offline operation that
were removed - each one is independent

Patches 5-19 - while translating sid->unix ID, skip the sid lookup if
the idmap backend allows this. This includes adding a mechanism that
allows the winbindd parent process to query idmap backends whether they
require sid lookup prior to sid->unix id mapping. The final 5 patches
can probably be squashed together - it just seems easier to follow this way.

Review appreciated,
Uri.

-------------- next part --------------
From 4f2260ac32e98c8722f90a0feebf756c2924cf69 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 26 Dec 2016 13:00:46 +0200
Subject: [PATCH 01/19] winbindd: cache name-to-sid from PAC based on lookup
 domain

The name-to-sid lookup for trusted domains is not necessarily
done against the domain - in AD member case it is done
against the primary domain. Therefore the caching should also
be done against the lookup domain.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/winbindd_pam.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 741a42f..3977dd2 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -2582,7 +2582,7 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state,
 		 * We're in the parent here, so find the child
 		 * pointer from the PAC domain name.
 		 */
-		domain = find_domain_from_name_noinit(
+		domain = find_lookup_domain_from_name(
 				info3_copy->base.logon_domain.string);
 		if (domain && domain->primary ) {
 			struct dom_sid user_sid;
-- 
2.9.3


From e6bd2babfda9c0d37f8a168215c01c63469d061c Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 26 Dec 2016 13:00:11 +0200
Subject: [PATCH 02/19] winbindd: avoid group sid lookup during user resolution

When doing getpw{nam,sid}, avoid looking up group sid,
unless there's a specific need (e.g. the group name
appears in the home dir template).

Avoiding the lookup is another step in not making calls to AD,
and improving SMB server availability during short AD disconnect
events.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 dcommits                         |   0
 source3/winbindd/wb_fill_pwent.c | 130 +++++++++++++++++++++++++++++----------
 2 files changed, 96 insertions(+), 34 deletions(-)
 create mode 100644 dcommits

diff --git a/dcommits b/dcommits
new file mode 100644
index 0000000..e69de29
diff --git a/source3/winbindd/wb_fill_pwent.c b/source3/winbindd/wb_fill_pwent.c
index 2229b05..503d386 100644
--- a/source3/winbindd/wb_fill_pwent.c
+++ b/source3/winbindd/wb_fill_pwent.c
@@ -38,6 +38,7 @@ static bool fillup_pw_field(const char *lp_template,
 
 static void wb_fill_pwent_sid2uid_done(struct tevent_req *subreq);
 static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq);
+static void wb_fill_pwent_gr_sidgid_done(struct tevent_req *subreq);
 
 struct tevent_req *wb_fill_pwent_send(TALLOC_CTX *mem_ctx,
 				      struct tevent_context *ev,
@@ -91,47 +92,43 @@ static void wb_fill_pwent_sid2uid_done(struct tevent_req *subreq)
 
 	state->pw->pw_uid = (uid_t)xids[0].id;
 
-	subreq = wb_getgrsid_send(state, state->ev, &state->info->group_sid, 0);
+	if (strstr(lp_template_homedir(), "%g") ||
+	    strstr(lp_template_shell(), "%g")) {
+		/*
+		 * The homedir / shell parts need to know the
+		 * primary group name
+		 */
+		subreq = wb_getgrsid_send(state, state->ev,
+					  &state->info->group_sid, 0);
+		if (tevent_req_nomem(subreq, req)) {
+			return;
+		}
+		tevent_req_set_callback(subreq, wb_fill_pwent_getgrsid_done,
+					req);
+		return;
+	}
+
+	subreq =
+	    wb_sids2xids_send(state, state->ev, &state->info->group_sid, 1);
 	if (tevent_req_nomem(subreq, req)) {
 		return;
 	}
-	tevent_req_set_callback(subreq, wb_fill_pwent_getgrsid_done, req);
+	tevent_req_set_callback(subreq, wb_fill_pwent_gr_sidgid_done, req);
 }
 
-static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq)
+static NTSTATUS wb_fill_pwent_finalize(struct wb_fill_pwent_state *state,
+				       const char *grp_name)
 {
-	struct tevent_req *req = tevent_req_callback_data(
-		subreq, struct tevent_req);
-	struct wb_fill_pwent_state *state = tevent_req_data(
-		req, struct wb_fill_pwent_state);
 	struct winbindd_domain *domain;
 	const char *dom_name;
-	const char *grp_name;
 	fstring user_name, output_username;
 	char *mapped_name = NULL;
-	struct talloc_dict *members;
-	TALLOC_CTX *tmp_ctx = talloc_stackframe();
 	NTSTATUS status;
 	bool ok;
 
-	/* xid handling is done in getgrsid() */
-	status = wb_getgrsid_recv(subreq,
-				  tmp_ctx,
-				  &dom_name,
-				  &grp_name,
-				  &state->pw->pw_gid,
-				  &members);
-	TALLOC_FREE(subreq);
-	if (tevent_req_nterror(req, status)) {
-		talloc_free(tmp_ctx);
-		return;
-	}
-
 	domain = find_domain_from_sid_noinit(&state->info->user_sid);
 	if (domain == NULL) {
-		talloc_free(tmp_ctx);
-		tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
-		return;
+		return NT_STATUS_NO_SUCH_USER;
 	}
 	dom_name = domain->name;
 
@@ -139,8 +136,7 @@ static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq)
 
 	fstrcpy(user_name, state->info->acct_name);
 	if (!strlower_m(user_name)) {
-		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-		return;
+		return NT_STATUS_INVALID_PARAMETER;
 	}
 	status = normalize_name_map(state, domain, user_name, &mapped_name);
 
@@ -177,9 +173,7 @@ static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq)
 			     state->info->homedir,
 			     state->pw->pw_dir);
 	if (!ok) {
-		talloc_free(tmp_ctx);
-		tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
-		return;
+		return NT_STATUS_NO_SUCH_USER;
 	}
 
 	ok = fillup_pw_field(lp_template_shell(),
@@ -190,16 +184,84 @@ static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq)
 			     state->pw->pw_gid,
 			     state->info->shell,
 			     state->pw->pw_shell);
-	talloc_free(tmp_ctx);
 	if (!ok) {
-		tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
-		return;
+		return NT_STATUS_NO_SUCH_USER;
 	}
 
 	/* Password - set to "*" as we can't generate anything useful here.
 	   Authentication can be done using the pam_winbind module. */
 
 	fstrcpy(state->pw->pw_passwd, "*");
+
+	return NT_STATUS_OK;
+}
+
+static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+	    tevent_req_callback_data(subreq, struct tevent_req);
+	struct wb_fill_pwent_state *state =
+	    tevent_req_data(req, struct wb_fill_pwent_state);
+	const char *dom_name;
+	const char *grp_name;
+	struct talloc_dict *members;
+	TALLOC_CTX *tmp_ctx = talloc_stackframe();
+	NTSTATUS status;
+
+	if (tevent_req_nomem(tmp_ctx, req)) {
+		return;
+	}
+
+	/* xid handling is done in getgrsid() */
+	status = wb_getgrsid_recv(subreq, tmp_ctx, &dom_name, &grp_name,
+				  &state->pw->pw_gid, &members);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		talloc_free(tmp_ctx);
+		return;
+	}
+
+	status = wb_fill_pwent_finalize(state, grp_name);
+	talloc_free(tmp_ctx);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	tevent_req_done(req);
+}
+
+static void wb_fill_pwent_gr_sidgid_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+	    tevent_req_callback_data(subreq, struct tevent_req);
+	struct wb_fill_pwent_state *state =
+	    tevent_req_data(req, struct wb_fill_pwent_state);
+	struct unixid xids[1];
+	NTSTATUS status;
+
+	status = wb_sids2xids_recv(subreq, xids, 1);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	if (!(xids[0].type == ID_TYPE_GID || xids[0].type == ID_TYPE_BOTH)) {
+		tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
+		return;
+	}
+
+	state->pw->pw_gid = (gid_t)xids[0].id;
+	/* if the home dir or shell has %g in it, a
+	 * gid->name lookup will be attempted, because
+	 * we're not sending the group name. This may
+	 * or may not succeed, based on the presence
+	 * of the proper nss modules
+	 */
+	status = wb_fill_pwent_finalize(state, NULL);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
 	tevent_req_done(req);
 }
 
-- 
2.9.3


From 1aadf5af6053534f40f170720cf3ac3af2ebc031 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Wed, 7 Dec 2016 13:40:05 +0200
Subject: [PATCH 03/19] winbindd: query_user - always try netsamlogon cache

Since the netsamlogon cahce is consulted as part of a
winbindd backend, always go to the backend to query a user
if the user appears in the netsamlogon cache, even if the
domain is unreachable.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/winbindd_cache.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index 05b356f..b8173aa 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -2299,7 +2299,6 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain,
 	    netsamlogon_cache_have(user_sid)) {
 		DEBUG(10, ("query_user: cached access denied and have cached "
 			   "info3\n"));
-		domain->last_status = NT_STATUS_OK;
 		centry_free(centry);
 		return NT_STATUS_NOT_FOUND;
 	}
@@ -2377,8 +2376,10 @@ NTSTATUS wb_cache_query_user(struct winbindd_domain *domain,
 
 	/* Return status value returned by seq number check */
 
-	if (!NT_STATUS_IS_OK(domain->last_status))
+	if (!NT_STATUS_IS_OK(domain->last_status) &&
+	    !netsamlogon_cache_have(user_sid)) {
 		return domain->last_status;
+	}
 
 	DEBUG(10,("query_user: [Cached] - doing backend query for info for domain %s\n",
 		domain->name ));
-- 
2.9.3


From 48e43ff25d81a6c31f35d386a55e660feeb7aab5 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Wed, 7 Dec 2016 13:42:50 +0200
Subject: [PATCH 04/19] winbindd: avoid refreshing sequence number when domain
 is offline

When there's no connectivity to the domain, avoid attempt to
refresh sequence number. Before the change, this was avoided
only if winbind offline logon was enabled. However, being
able to operate based on cached data is desired even when
offline logons are disabled (offline logons are about caching
credentials for PAM authentication, a user may not want this
and still want service from the SMB server during short
AD disconnects).

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/winbindd_util.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 38e4b8b..8d4ca9b 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -1611,9 +1611,6 @@ void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
 
 bool is_domain_offline(const struct winbindd_domain *domain)
 {
-	if (!lp_winbind_offline_logon()) {
-		return false;
-	}
 	if (get_global_winbindd_state_offline()) {
 		return true;
 	}
-- 
2.9.3


From 20068cd791b6ab6a7f3f4bc313520f574f2218da Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Wed, 7 Dec 2016 23:18:31 +0200
Subject: [PATCH 05/19] winbindd-idmap: define which backends require sid type

Some backends ignore the SID type when translating
a SID to a unix ID. Add a field that takes note of that
property - it can be utilized to bypass the resolving
of SID type while doing SID->unix id translation.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/include/idmap.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source3/include/idmap.h b/source3/include/idmap.h
index 800e694..7cb0b39 100644
--- a/source3/include/idmap.h
+++ b/source3/include/idmap.h
@@ -38,6 +38,7 @@ struct idmap_domain {
 	uint32_t low_id;
 	uint32_t high_id;
 	bool read_only;
+	bool ignore_sid_type; /* whether sid->xid needs to know sid type */
 	void *private_data;
 };
 
-- 
2.9.3


From 2619301e216565585c41c018dca4d999cd324a1e Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Sun, 25 Dec 2016 21:03:09 +0200
Subject: [PATCH 06/19] winbindd-idmap-passdb: remove stale comment

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/idmap_passdb.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c
index cf8ad74..0974263 100644
--- a/source3/winbindd/idmap_passdb.c
+++ b/source3/winbindd/idmap_passdb.c
@@ -75,10 +75,6 @@ static NTSTATUS idmap_pdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 	return NT_STATUS_OK;
 }
 
-/**********************************
- Close the idmap tdb instance
-**********************************/
-
 static struct idmap_methods passdb_methods = {
 
 	.init = idmap_pdb_init,
-- 
2.9.3


From 5728f036a901459adb4eb5e4ad6f14a30e0aa7e4 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Sun, 25 Dec 2016 21:05:01 +0200
Subject: [PATCH 07/19] winbindd: declare that idmap-passdb does not require
 SID type

Declare that idmap-passdb does not need to know the SID type
in order to perform SID->unix id translation.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/idmap_passdb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source3/winbindd/idmap_passdb.c b/source3/winbindd/idmap_passdb.c
index 0974263..3a8dd06 100644
--- a/source3/winbindd/idmap_passdb.c
+++ b/source3/winbindd/idmap_passdb.c
@@ -32,6 +32,7 @@
 
 static NTSTATUS idmap_pdb_init(struct idmap_domain *dom)
 {	
+	dom->ignore_sid_type = true;
 	return NT_STATUS_OK;
 }
 
-- 
2.9.3


From 82e5c409b9ce95e9b22e0d9244e152eadbadf8cf Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Sun, 25 Dec 2016 21:06:32 +0200
Subject: [PATCH 08/19] winbindd: declare that idmap-rid does not require sid
 type

Declare that idmap-rid does not need to know the SID type
to do SID->unix id translation.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/idmap_rid.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c
index d68dbf7..bac3233 100644
--- a/source3/winbindd/idmap_rid.c
+++ b/source3/winbindd/idmap_rid.c
@@ -41,6 +41,8 @@ static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom)
 	struct idmap_rid_context *ctx;
 	char *config_option = NULL;
 
+	dom->ignore_sid_type = true;
+
 	ctx = talloc_zero(dom, struct idmap_rid_context);
 	if (ctx == NULL) {
 		DEBUG(0, ("Out of memory!\n"));
-- 
2.9.3


From deb2519574aa6b851df0814fcdc8b2abb4903e06 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Wed, 7 Dec 2016 23:50:49 +0200
Subject: [PATCH 09/19] winbindd-idmap: define interface to explicitly
 initialize backend

This interface initializes the idmap backend for a domain, and
allows the backend to return whether it requires SID resolving
prior to sid->xid translation.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 librpc/idl/winbind.idl               |  6 +++++
 source3/include/idmap.h              |  1 +
 source3/winbindd/idmap.c             | 51 ++++++++++++++++++++++++++++++++++++
 source3/winbindd/idmap_proto.h       |  3 +++
 source3/winbindd/winbindd_dual_srv.c | 14 ++++++++++
 5 files changed, 75 insertions(+)

diff --git a/librpc/idl/winbind.idl b/librpc/idl/winbind.idl
index 60c875b..5843e51 100644
--- a/librpc/idl/winbind.idl
+++ b/librpc/idl/winbind.idl
@@ -51,6 +51,12 @@ interface winbind
 	[size_is(num_ids)] wbint_TransID ids[];
     } wbint_TransIDArray;
 
+    NTSTATUS wbint_IDMapInitDomain(
+	[in,string,charset(UTF8)] char *domain,
+	[in] dom_sid *sid,
+	[out] boolean32 *require_sid_type
+	);
+
     NTSTATUS wbint_Sids2UnixIDs(
 	[in] lsa_RefDomainList *domains,
 	[in,out] wbint_TransIDArray *ids
diff --git a/source3/include/idmap.h b/source3/include/idmap.h
index 7cb0b39..d4c8d4b 100644
--- a/source3/include/idmap.h
+++ b/source3/include/idmap.h
@@ -39,6 +39,7 @@ struct idmap_domain {
 	uint32_t high_id;
 	bool read_only;
 	bool ignore_sid_type; /* whether sid->xid needs to know sid type */
+	struct dom_sid sid;   /* some backends need this */
 	void *private_data;
 };
 
diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c
index 84834f1..0fc70cf 100644
--- a/source3/winbindd/idmap.c
+++ b/source3/winbindd/idmap.c
@@ -617,3 +617,54 @@ NTSTATUS idmap_backend_unixids_to_sids(struct id_map **maps,
 
 	return status;
 }
+
+NTSTATUS idmap_get_backend_params(const char *domain_name,
+				  bool *require_sid_type)
+{
+	struct idmap_domain *dom = NULL;
+	bool ok;
+
+	ok = idmap_init();
+	if (!ok) {
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+	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_UNSUCCESSFUL;
+	}
+
+	*require_sid_type = !dom->ignore_sid_type;
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS idmap_set_domain_sid(const char *domain_name, struct dom_sid *sid)
+{
+	struct idmap_domain *dom = NULL;
+	bool ok;
+
+	ok = idmap_init();
+	if (!ok) {
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+	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_UNSUCCESSFUL;
+	}
+
+	sid_copy(&dom->sid, sid);
+
+	return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/idmap_proto.h b/source3/winbindd/idmap_proto.h
index 84cc2f0..98d59d8 100644
--- a/source3/winbindd/idmap_proto.h
+++ b/source3/winbindd/idmap_proto.h
@@ -36,6 +36,9 @@ NTSTATUS idmap_allocate_uid(struct unixid *id);
 NTSTATUS idmap_allocate_gid(struct unixid *id);
 NTSTATUS idmap_backend_unixids_to_sids(struct id_map **maps,
 				       const char *domain_name);
+NTSTATUS idmap_get_backend_params(const char *domain_name,
+				  bool *require_sid_type);
+NTSTATUS idmap_set_domain_sid(const char *domain_name, struct dom_sid *sid);
 
 /* The following definitions come from winbindd/idmap_nss.c  */
 
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
index 4a581d33..0a810cc 100644
--- a/source3/winbindd/winbindd_dual_srv.c
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -118,6 +118,20 @@ NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
 	return status;
 }
 
+NTSTATUS _wbint_IDMapInitDomain(struct pipes_struct *p,
+				struct wbint_IDMapInitDomain *r)
+{
+	bool require_sid_type = true;
+	NTSTATUS status;
+
+	status = idmap_get_backend_params(r->in.domain, &require_sid_type);
+	if (NT_STATUS_IS_OK(status)) {
+		*r->out.require_sid_type = require_sid_type;
+		status = idmap_set_domain_sid(r->in.domain, r->in.sid);
+	}
+	return status;
+}
+
 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
 			     struct wbint_Sids2UnixIDs *r)
 {
-- 
2.9.3


From e2ce4378f3633aca35e7d82d3b59055eb5d8c1d8 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 8 Dec 2016 07:52:39 +0200
Subject: [PATCH 10/19] winbindd: add idmap_require_sid_type flag

This flag tells winbindd whether to resolve a SID
and determine its type before sending it to id-mapping.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/winbindd.h      | 1 +
 source3/winbindd/winbindd_util.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index fce2e46..b44d854 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -167,6 +167,7 @@ struct winbindd_domain {
 	bool startup;                          /* are we in the first 30 seconds after startup_time ? */
 
 	bool can_do_ncacn_ip_tcp;
+	bool idmap_require_sid_type;	       /* does idmap sid->id need to know sid type */
 
 	/*
 	 * Lookup methods for this domain (LDAP or RPC). The backend
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 8d4ca9b..9843d6c 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -272,6 +272,8 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc)
 		}
 	}
 
+	domain->idmap_require_sid_type = true;
+
 	/* Link to domain list */
 	DLIST_ADD_END(_domain_list, domain);
 
-- 
2.9.3


From 4bd75e38617691371e84fca97b44454ce3a088e0 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Fri, 9 Dec 2016 23:28:01 +0200
Subject: [PATCH 11/19] winbindd: add wb_init_idmap_backend_{send,recv}

Convenience wrapper around the IRPC routines

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c   | 87 +++++++++++++++++++++++++++++++++++++++
 source3/winbindd/winbindd_proto.h |  6 +++
 2 files changed, 93 insertions(+)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index 25260be..9b44195 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -459,3 +459,90 @@ static struct wbint_TransIDArray *wb_sids2xids_extract_for_domain_index(
 
 	return ret;
 }
+
+struct wb_init_idmap_backend_state {
+	char *domain;
+	struct dom_sid sid;
+	uint32_t require_sid_type;
+};
+
+static void wb_init_idmap_backend_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_init_idmap_backend_send(TALLOC_CTX *mem_ctx,
+					      struct tevent_context *ev,
+					      const char *domain,
+					      struct dom_sid *sid)
+{
+	struct tevent_req *req, *subreq;
+	struct wb_init_idmap_backend_state *state;
+	struct winbindd_child *child;
+
+	child = idmap_child();
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct wb_init_idmap_backend_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	if (sid) {
+		sid_copy(&state->sid, sid);
+	}
+	state->domain = talloc_strdup(state, domain);
+	if (tevent_req_nomem(state->domain, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = dcerpc_wbint_IDMapInitDomain_send(
+	    state, ev, child->binding_handle, state->domain, &state->sid,
+	    &state->require_sid_type);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	tevent_req_set_callback(subreq, wb_init_idmap_backend_done, req);
+
+	return req;
+}
+
+static void wb_init_idmap_backend_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+	    tevent_req_callback_data(subreq, struct tevent_req);
+	struct wb_init_idmap_backend_state *state =
+	    tevent_req_data(req, struct wb_init_idmap_backend_state);
+	NTSTATUS status, result;
+
+	status = dcerpc_wbint_IDMapInitDomain_recv(subreq, state, &result);
+	TALLOC_FREE(subreq);
+
+	if (tevent_req_nterror(req, status)) {
+		DBG_INFO("ipc idmap init call for domain %s failed - %s\n",
+			 state->domain, nt_errstr(status));
+		return;
+	}
+
+	if (tevent_req_nterror(req, result)) {
+		DBG_INFO("idmap init for domain %s failed - %s\n",
+			 state->domain, nt_errstr(result));
+		return;
+	}
+
+	tevent_req_done(req);
+}
+
+NTSTATUS wb_init_idmap_backend_recv(struct tevent_req *req,
+				    bool *require_sid_type)
+{
+	struct wb_init_idmap_backend_state *state =
+	    tevent_req_data(req, struct wb_init_idmap_backend_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+
+	*require_sid_type = (state->require_sid_type != 0);
+
+	return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 87df2d5..21402d9 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -954,6 +954,12 @@ NTSTATUS wb_lookupsids_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 			    struct lsa_RefDomainList **domains,
 			    struct lsa_TransNameArray **names);
 
+struct tevent_req *wb_init_idmap_backend_send(TALLOC_CTX *mem_ctx,
+					      struct tevent_context *ev,
+					      const char *domain,
+					      struct dom_sid *sid);
+NTSTATUS wb_init_idmap_backend_recv(struct tevent_req *req,
+				    bool *require_sid_type);
 struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 				     struct tevent_context *ev,
 				     const struct dom_sid *sids,
-- 
2.9.3


From 485a92a5fb54471fee201b5e9f1cd667441de85c Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Sat, 10 Dec 2016 00:30:31 +0200
Subject: [PATCH 12/19] winbindd: probe idmap backends on init

probe idmap backend of each domain to see if it
requires the SID type in order to do sid->xid translation.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/winbindd.c      |  2 +-
 source3/winbindd/winbindd_util.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index 2cd2001..1c01123 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -1394,6 +1394,7 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx,
 
 	netsamlogon_cache_init(); /* Non-critical */
 
+	init_idmap_child();
 	/* clear the cached list of trusted domains */
 
 	wcache_tdc_clear();
@@ -1403,7 +1404,6 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx,
 		exit(1);
 	}
 
-	init_idmap_child();
 	init_locator_child();
 
 	smb_nscd_flush_user_cache();
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 9843d6c..9aac391 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -37,6 +37,7 @@
 
 static struct winbindd_domain *
 add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc);
+static void init_idmap_done(struct tevent_req *req);
 
 /**
  * @file winbindd_util.c
@@ -150,6 +151,7 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc)
 	int role = lp_server_role();
 	const char *domain_name = tdc->domain_name;
 	const struct dom_sid *sid = &tdc->sid;
+	struct tevent_req *req;
 
 	if (is_null_sid(sid)) {
 		sid = NULL;
@@ -281,6 +283,13 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc)
 
 	setup_domain_child(domain);
 
+	req = wb_init_idmap_backend_send(domain, winbind_event_context(),
+					 domain->name, &domain->sid);
+	if (!req) {
+		smb_panic("failed calling idmap child to initialize backend");
+	}
+	tevent_req_set_callback(req, init_idmap_done, domain);
+
 	DEBUG(2,
 	      ("Added domain %s %s %s\n", domain->name, domain->alt_name,
 	       !is_null_sid(&domain->sid) ? sid_string_dbg(&domain->sid) : ""));
@@ -288,6 +297,26 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc)
 	return domain;
 }
 
+static void init_idmap_done(struct tevent_req *req)
+{
+	struct winbindd_domain *domain =
+	    tevent_req_callback_data(req, struct winbindd_domain);
+	NTSTATUS status;
+	bool require_sid_type = true;
+
+	status = wb_init_idmap_backend_recv(req, &require_sid_type);
+	TALLOC_FREE(req);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_WARNING("Failed initializing idmap for domain %s\n",
+			    domain->name);
+		return;
+	}
+
+	DBG_DEBUG("Domain %s id-mapping %s sid type\n", domain->name,
+		  require_sid_type ? "requires" : "does not require");
+	domain->idmap_require_sid_type = require_sid_type;
+}
+
 bool domain_is_forest_root(const struct winbindd_domain *domain)
 {
 	const uint32_t fr_flags =
-- 
2.9.3


From 6253257c60116267e28331b7e3b6535d1f0a7912 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Mon, 26 Dec 2016 06:17:36 +0200
Subject: [PATCH 13/19] winbindd-idmap-rid: use domain from IPC call

During xid->sid translation, use domain SID obtained from the
init domain IPC, not the trusted domain object (which may not
exist because idmap child might have been forked prior to
discovering the trusted domain)

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/idmap_rid.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/source3/winbindd/idmap_rid.c b/source3/winbindd/idmap_rid.c
index bac3233..e1dcab7 100644
--- a/source3/winbindd/idmap_rid.c
+++ b/source3/winbindd/idmap_rid.c
@@ -72,6 +72,7 @@ static NTSTATUS idmap_rid_id_to_sid(struct idmap_domain *dom, struct id_map *map
 {
 	struct winbindd_domain *domain;
 	struct idmap_rid_context *ctx;
+	struct dom_sid dom_sid = {0};
 
 	ctx = talloc_get_type(dom->private_data, struct idmap_rid_context);
 
@@ -82,12 +83,18 @@ static NTSTATUS idmap_rid_id_to_sid(struct idmap_domain *dom, struct id_map *map
 		return NT_STATUS_NONE_MAPPED;
 	}
 
-	domain = find_domain_from_name_noinit(dom->name);
-	if (domain == NULL ) {
-		return NT_STATUS_NO_SUCH_DOMAIN;
+	dom_sid = dom->sid;
+	if (is_null_sid(&dom_sid)) {
+		DBG_WARNING("Domain %s has not been initialized\n", dom->name);
+		domain = find_domain_from_name_noinit(dom->name);
+		if (domain == NULL) {
+			return NT_STATUS_NO_SUCH_DOMAIN;
+		}
+		dom_sid = domain->sid;
 	}
 
-	sid_compose(map->sid, &domain->sid, map->xid.id - dom->low_id + ctx->base_rid);
+	sid_compose(map->sid, &dom_sid,
+		    map->xid.id - dom->low_id + ctx->base_rid);
 
 	map->status = ID_MAPPED;
 	map->xid.type = ID_TYPE_BOTH;
-- 
2.9.3


From aa16795a87cbe9484e75d521aaf5f44193b6a27d Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 22 Dec 2016 06:41:25 +0200
Subject: [PATCH 14/19] winbindd: introduce wb_sids2xids_next

Put the code that calls the per-domain idmap backend
in its own function.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index 9b44195..029679d 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -63,6 +63,7 @@ static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map);
 static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq);
 static void wb_sids2xids_done(struct tevent_req *subreq);
 static void wb_sids2xids_gotdc(struct tevent_req *subreq);
+static bool wb_sids2xids_next(struct tevent_req *req);
 
 struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 				     struct tevent_context *ev,
@@ -167,7 +168,6 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		req, struct wb_sids2xids_state);
 	struct lsa_RefDomainList *domains = NULL;
 	struct lsa_TransNameArray *names = NULL;
-	struct winbindd_child *child;
 	NTSTATUS status;
 	int i;
 
@@ -212,12 +212,22 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 	TALLOC_FREE(names);
 	TALLOC_FREE(domains);
 
+	wb_sids2xids_next(req);
+}
+
+static bool wb_sids2xids_next(struct tevent_req *req)
+{
+	struct wb_sids2xids_state *state = tevent_req_data(
+		req, struct wb_sids2xids_state);
+	struct tevent_req *subreq;
+	struct winbindd_child *child;
+
 	child = idmap_child();
 
 	state->dom_ids = wb_sids2xids_extract_for_domain_index(
 		state, &state->ids, state->dom_index);
 	if (tevent_req_nomem(state->dom_ids, req)) {
-		return;
+		return false;
 	}
 
 	state->idmap_dom = (struct lsa_RefDomainList) {
@@ -230,9 +240,11 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		state, state->ev, child->binding_handle, &state->idmap_dom,
 		state->dom_ids);
 	if (tevent_req_nomem(subreq, req)) {
-		return;
+		return false;
 	}
 	tevent_req_set_callback(subreq, wb_sids2xids_done, req);
+
+	return true;
 }
 
 static enum id_type lsa_SidType_to_id_type(const enum lsa_SidType sid_type)
@@ -264,7 +276,6 @@ static void wb_sids2xids_done(struct tevent_req *subreq)
 	struct wb_sids2xids_state *state = tevent_req_data(
 		req, struct wb_sids2xids_state);
 	NTSTATUS status, result;
-	struct winbindd_child *child;
 
 	struct wbint_TransIDArray *src, *dst;
 	uint32_t i, src_idx;
@@ -327,27 +338,7 @@ static void wb_sids2xids_done(struct tevent_req *subreq)
 		return;
 	}
 
-	child = idmap_child();
-
-	state->dom_ids = wb_sids2xids_extract_for_domain_index(
-		state, &state->ids, state->dom_index);
-	if (tevent_req_nomem(state->dom_ids, req)) {
-		return;
-	}
-
-	state->idmap_dom = (struct lsa_RefDomainList) {
-		.count = 1,
-		.domains = &state->idmap_doms.domains[state->dom_index],
-		.max_size = 1
-	};
-
-	subreq = dcerpc_wbint_Sids2UnixIDs_send(
-		state, state->ev, child->binding_handle, &state->idmap_dom,
-		state->dom_ids);
-	if (tevent_req_nomem(subreq, req)) {
-		return;
-	}
-	tevent_req_set_callback(subreq, wb_sids2xids_done, req);
+	wb_sids2xids_next(req);
 }
 
 static void wb_sids2xids_gotdc(struct tevent_req *subreq)
-- 
2.9.3


From 629087980ca22986f86c86cb54054c6ae606c95e Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 22 Dec 2016 07:40:05 +0200
Subject: [PATCH 15/19] winbindd sids2xids: allocate wbint_TransID array
 earlier

Allocate the wbint_TransID array used for ID mapping before
doing the sid resolving - to allow skipping sid resolving
in some cases.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index 029679d..26da58d 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -126,6 +126,13 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	state->ids.num_ids = state->num_non_cached;
+	state->ids.ids = talloc_array(state, struct wbint_TransID,
+				      state->num_non_cached);
+	if (tevent_req_nomem(state->ids.ids, req)) {
+		return tevent_req_post(req, ev);
+	}
+
 	subreq = wb_lookupsids_send(state, ev, state->non_cached,
 				    state->num_non_cached);
 	if (tevent_req_nomem(subreq, req)) {
@@ -177,13 +184,6 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		return;
 	}
 
-	state->ids.num_ids = state->num_non_cached;
-	state->ids.ids = talloc_array(state, struct wbint_TransID,
-				      state->num_non_cached);
-	if (tevent_req_nomem(state->ids.ids, req)) {
-		return;
-	}
-
 	for (i=0; i<state->num_non_cached; i++) {
 		struct dom_sid dom_sid;
 		struct lsa_DomainInfo *info;
-- 
2.9.3


From 61fc077b940921a64bd091946731f7222321a756 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 22 Dec 2016 09:03:07 +0200
Subject: [PATCH 16/19] winbindd sids2xids: separate resolving list from
 mapping list

Manage two lists instead of one - a list of SIDs to be mapped,
and a (conceptual) subset that needs to be resolved before mapping.

In this patch we just introduce the lists and they have the same
content, but in later patches we can remove some SIDs from the
resolve list.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index 26da58d..f14b1c5 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -37,6 +37,10 @@ struct wb_sids2xids_state {
 	struct dom_sid *non_cached;
 	uint32_t num_non_cached;
 
+	struct dom_sid *non_resolved;
+	unsigned *res_idx;
+	uint32_t num_non_resolved;
+
 	/*
 	 * Domain array to use for the idmap call. The output from
 	 * lookupsids cannot be used directly since for migrated
@@ -126,6 +130,17 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	state->non_resolved =
+	    talloc_array(state, struct dom_sid, state->num_non_cached);
+	if (tevent_req_nomem(state->non_resolved, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	state->res_idx = talloc_array(state, unsigned, state->num_non_cached);
+	if (tevent_req_nomem(state->res_idx, req)) {
+		return tevent_req_post(req, ev);
+	}
+
 	state->ids.num_ids = state->num_non_cached;
 	state->ids.ids = talloc_array(state, struct wbint_TransID,
 				      state->num_non_cached);
@@ -133,6 +148,13 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	for (i=0; i<state->num_non_cached; i++) {
+		state->res_idx[state->num_non_resolved] = i;
+		sid_copy(&state->non_resolved[state->num_non_resolved],
+			 &state->non_cached[i]);
+		++state->num_non_resolved;
+	}
+
 	subreq = wb_lookupsids_send(state, ev, state->non_cached,
 				    state->num_non_cached);
 	if (tevent_req_nomem(subreq, req)) {
@@ -184,14 +206,15 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		return;
 	}
 
-	for (i=0; i<state->num_non_cached; i++) {
+	for (i = 0; i < state->num_non_resolved; i++) {
+		unsigned nc_idx = state->res_idx[i];
 		struct dom_sid dom_sid;
 		struct lsa_DomainInfo *info;
 		struct lsa_TranslatedName *n = &names->names[i];
-		struct wbint_TransID *t = &state->ids.ids[i];
+		struct wbint_TransID *t = &state->ids.ids[nc_idx];
 		int domain_index;
 
-		sid_copy(&dom_sid, &state->non_cached[i]);
+		sid_copy(&dom_sid, &state->non_cached[nc_idx]);
 		sid_split_rid(&dom_sid, &t->rid);
 
 		info = &domains->domains[n->sid_index];
-- 
2.9.3


From f5315cbe840665f973cf12b93e3fd99024e44191 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 22 Dec 2016 09:28:31 +0200
Subject: [PATCH 17/19] winbindd sids2xids: initialize the wbint_TransID array
 before sid resolution

Initialize whatever fields that we can in the wbint_TransID right
after its allocation.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index f14b1c5..eedf8d9 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -149,6 +149,16 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 	}
 
 	for (i=0; i<state->num_non_cached; i++) {
+		struct dom_sid dom_sid;
+		struct wbint_TransID *t = &state->ids.ids[i];
+
+		sid_copy(&dom_sid, &state->non_cached[i]);
+		sid_split_rid(&dom_sid, &t->rid);
+		t->type = ID_TYPE_BOTH;
+		t->xid.id = UINT32_MAX;
+		t->xid.type = t->type;
+		t->domain_index = -1;
+
 		state->res_idx[state->num_non_resolved] = i;
 		sid_copy(&state->non_resolved[state->num_non_resolved],
 			 &state->non_cached[i]);
@@ -215,7 +225,7 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		int domain_index;
 
 		sid_copy(&dom_sid, &state->non_cached[nc_idx]);
-		sid_split_rid(&dom_sid, &t->rid);
+		sid_split_rid(&dom_sid, NULL);
 
 		info = &domains->domains[n->sid_index];
 		t->type = lsa_SidType_to_id_type(n->sid_type);
@@ -228,7 +238,6 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq)
 		}
 		t->domain_index = domain_index;
 
-		t->xid.id = UINT32_MAX;
 		t->xid.type = t->type;
 	}
 
-- 
2.9.3


From c6d66bfce0a31b2aa0f18e67c268b6cd99913bb3 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 22 Dec 2016 09:32:26 +0200
Subject: [PATCH 18/19] winbindd sids2xids: skip resolution of SIDs handled by
 passdb

SIDs whose ID mapping is handled by passdb do not need to be
resolved prior to ID mapping - neither their type nor their
domain name is required.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index eedf8d9..bfef236 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -23,6 +23,7 @@
 #include "../libcli/security/security.h"
 #include "idmap_cache.h"
 #include "librpc/gen_ndr/ndr_winbind_c.h"
+#include "lib/util_sid_passdb.h"
 #include "librpc/gen_ndr/ndr_netlogon.h"
 #include "lsa.h"
 
@@ -151,6 +152,7 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 	for (i=0; i<state->num_non_cached; i++) {
 		struct dom_sid dom_sid;
 		struct wbint_TransID *t = &state->ids.ids[i];
+		int domain_index;
 
 		sid_copy(&dom_sid, &state->non_cached[i]);
 		sid_split_rid(&dom_sid, &t->rid);
@@ -159,18 +161,45 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 		t->xid.type = t->type;
 		t->domain_index = -1;
 
+		if (sid_check_is_for_passdb(&state->non_cached[i])) {
+			/*
+			 * It doesn't really matter what domain
+			 * name we put here, as long as it doesn't
+			 * collide with another "real" domain
+			 */
+			DBG_DEBUG(
+			    "sid %s handled by passdb and does not require "
+			    "resolution\n",
+			    sid_string_dbg(&state->non_cached[i]));
+			domain_index = init_lsa_ref_domain_list(
+			    state, &state->idmap_doms, "", &dom_sid);
+			if (domain_index == -1) {
+				tevent_req_oom(req);
+				return tevent_req_post(req, ev);
+			}
+			t->domain_index = domain_index;
+			continue;
+		}
+
+		DBG_DEBUG("sid %s requires resolution before mapping\n",
+			  sid_string_dbg(&state->non_cached[i]));
 		state->res_idx[state->num_non_resolved] = i;
 		sid_copy(&state->non_resolved[state->num_non_resolved],
 			 &state->non_cached[i]);
 		++state->num_non_resolved;
 	}
 
-	subreq = wb_lookupsids_send(state, ev, state->non_cached,
-				    state->num_non_cached);
-	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, ev);
+	if (state->num_non_resolved != 0) {
+		subreq = wb_lookupsids_send(state, ev, state->non_resolved,
+					    state->num_non_resolved);
+		if (tevent_req_nomem(subreq, req)) {
+			return tevent_req_post(req, ev);
+		}
+		tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done,
+					req);
+	} else {
+		wb_sids2xids_next(req);
 	}
-	tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req);
 	return req;
 }
 
-- 
2.9.3


From 7053ccc19c0ca3db7acd157c2c876a116b993512 Mon Sep 17 00:00:00 2001
From: Uri Simchoni <uri at samba.org>
Date: Thu, 22 Dec 2016 09:34:44 +0200
Subject: [PATCH 19/19] winbindd sids2xids: skip SID resolution if domain
 allows it

For SIDs where we can identify the domain, and the domain is
known not to require SID type for ID mapping, skip the
resolution step.

Signed-off-by: Uri Simchoni <uri at samba.org>
---
 source3/winbindd/wb_sids2xids.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c
index bfef236..54a9dff 100644
--- a/source3/winbindd/wb_sids2xids.c
+++ b/source3/winbindd/wb_sids2xids.c
@@ -153,6 +153,7 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 		struct dom_sid dom_sid;
 		struct wbint_TransID *t = &state->ids.ids[i];
 		int domain_index;
+		struct winbindd_domain *domain = NULL;
 
 		sid_copy(&dom_sid, &state->non_cached[i]);
 		sid_split_rid(&dom_sid, &t->rid);
@@ -181,6 +182,22 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
 			continue;
 		}
 
+		domain = find_domain_from_sid_noinit(&dom_sid);
+		if (domain != NULL && !domain->idmap_require_sid_type) {
+			DBG_DEBUG("sid %s belonging to domain [%s] does not "
+				  "require resolution\n",
+				  sid_string_dbg(&state->non_cached[i]),
+				  domain->name);
+			domain_index = init_lsa_ref_domain_list(
+			    state, &state->idmap_doms, domain->name, &dom_sid);
+			if (domain_index == -1) {
+				tevent_req_oom(req);
+				return tevent_req_post(req, ev);
+			}
+			t->domain_index = domain_index;
+			continue;
+		}
+
 		DBG_DEBUG("sid %s requires resolution before mapping\n",
 			  sid_string_dbg(&state->non_cached[i]));
 		state->res_idx[state->num_non_resolved] = i;
-- 
2.9.3



More information about the samba-technical mailing list