[PATCH] winbindd: idmap backend allocates id for unknown SID

Ralph Boehme slow at samba.org
Mon Jun 27 09:14:46 UTC 2016


Hi!

Attached is a patch for bug in winbindd:
<https://bugzilla.samba.org/show_bug.cgi?id=11961>

Passed a private autobuild. Please review&push if ok. Thanks!

Cheerio!
-slow
-------------- next part --------------
From f2dd20fa28484bbaca566938c3f67431996cb10d Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 24 Jun 2016 18:31:45 +0200
Subject: [PATCH 1/4] winbindd/idmap_rfc2307: fix a crash

map->map is NULL if lookupsid failed.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11961

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/idmap_rfc2307.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/source3/winbindd/idmap_rfc2307.c b/source3/winbindd/idmap_rfc2307.c
index 1b5aad9..34cc5cd 100644
--- a/source3/winbindd/idmap_rfc2307.c
+++ b/source3/winbindd/idmap_rfc2307.c
@@ -675,9 +675,7 @@ again:
 			break;
 
 		default:
-			DEBUG(10, ("Nothing to do for SID %s, "
-				   "previous name lookup failed\n",
-				   sid_string_dbg(map->map->sid)));
+			break;
 		}
 
 		if (!fltr_usr || !fltr_grp) {
-- 
2.5.0


From 5389e39ec5b105449dfc336cb36314d53ba96895 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 24 Jun 2016 15:16:42 +0200
Subject: [PATCH 2/4] winbindd: in wb_lookupsids return domain name if we have
 it

When doing a SID to xid mapping for an unknown SID, the idmap child gets
passed a lsa_RefDomainList with an empty domain name (ie ""). This is
coming from LsaLookupSids() and causes the mapping request to end up in
the default idmap domain.

Example request with domain name "":

  wbint_Sids2UnixIDs: struct wbint_Sids2UnixIDs
     in: struct wbint_Sids2UnixIDs
         domains                  : *
             domains: struct lsa_RefDomainList
                 count                    : 0x00000001 (1)
                 domains                  : *
                     domains: ARRAY(1)
                         domains: struct lsa_DomainInfo
                             name: struct lsa_StringLarge
                                 length                   : 0x0000 (0)
                                 size                     : 0x0002 (2)
                                 string                   : *
                                     string                   : ''
                             sid                      : *
                                 sid                      : S-1-5-21-3152989960-574718769-2188965058
                 max_size                 : 0x00000020 (32)
         ids                      : *
             ids: struct wbint_TransIDArray
                 num_ids                  : 0x00000001 (1)
                 ids: ARRAY(1)
                     ids: struct wbint_TransID
                         type                     : ID_TYPE_NOT_SPECIFIED (0)
                         domain_index             : 0x00000000 (0)
                         rid                      : 0x000029aa (66666)
                         xid: struct unixid
                             id                       : 0xffffffff (4294967295)
                             type                     : ID_TYPE_NOT_SPECIFIED (0)

In _wbint_Sids2UnixIDs() we call idmap_find_domain_with_sid() with the
domain name "" and this triggers use of the default idmap domain which
in case of idmap_autorid will allocate an id from a idmap_autorid range.

If we know the domain, ensure we return it for SIDs were the SID was not
found but the domain of the SID was found. Callers like sids2xids depend
on the domain name and returning an empty string "" for valid domain can
trigger unwanted idmap range allocations.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11961

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/winbindd/wb_lookupsids.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/wb_lookupsids.c b/source3/winbindd/wb_lookupsids.c
index 8c5f9db..573a870 100644
--- a/source3/winbindd/wb_lookupsids.c
+++ b/source3/winbindd/wb_lookupsids.c
@@ -72,6 +72,8 @@ struct wb_lookupsids_state {
 	 * wbint_LookupSid. Preallocated with num_sids.
 	 */
 	uint32_t *single_sids;
+	/* Pointer into the "domains" array above*/
+	struct wb_lookupsids_domain **single_domains;
 	uint32_t num_single_sids;
 	uint32_t single_sids_done;
 
@@ -127,6 +129,12 @@ struct tevent_req *wb_lookupsids_send(TALLOC_CTX *mem_ctx,
 	if (tevent_req_nomem(state->single_sids, req)) {
 		return tevent_req_post(req, ev);
 	}
+	state->single_domains = talloc_zero_array(state,
+						  struct wb_lookupsids_domain *,
+						  num_sids);
+	if (tevent_req_nomem(state->single_domains, req)) {
+		return tevent_req_post(req, ev);
+	}
 
 	state->res_domains = talloc_zero(state, struct lsa_RefDomainList);
 	if (tevent_req_nomem(state->res_domains, req)) {
@@ -455,6 +463,7 @@ static void wb_lookupsids_done(struct tevent_req *subreq)
 
 			state->single_sids[state->num_single_sids] =
 				res_sid_index;
+			state->single_domains[state->num_single_sids] = d;
 			state->num_single_sids += 1;
 		}
 		state->domains_done += 1;
@@ -514,9 +523,27 @@ static void wb_lookupsids_single_done(struct tevent_req *subreq)
 				   &domain_name, &name);
 	TALLOC_FREE(subreq);
 	if (!NT_STATUS_IS_OK(status)) {
+		struct wb_lookupsids_domain *wb_domain;
+
 		type = SID_NAME_UNKNOWN;
 
-		domain_name = talloc_strdup(talloc_tos(), "");
+		wb_domain = state->single_domains[state->single_sids_done];
+		if (wb_domain != NULL) {
+			/*
+			 * If the lookupsid failed because the rid not
+			 * found in a domain and we have a reference
+			 * to the lookup domain, use the name from
+			 * there.
+			 *
+			 * Callers like sid2xid will use the domain
+			 * name in the idmap backend to figure out
+			 * which domain to use in processing.
+			 */
+			domain_name = talloc_strdup(talloc_tos(),
+						    wb_domain->domain->name);
+		} else {
+			domain_name = talloc_strdup(talloc_tos(), "");
+		}
 		if (tevent_req_nomem(domain_name, req)) {
 			return;
 		}
-- 
2.5.0


From 2f138129f5f3667c96617b6b0c5ccfde6b2932b3 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 24 Jun 2016 18:33:01 +0200
Subject: [PATCH 3/4] selftest: make autorid the default idmap backend in
 admember_rfc2307

This is needed for a new test in the next commit. Exisiting tests aren't
affected by this, at least a private autobuild passed with this
change.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11961

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 selftest/target/Samba3.pm | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 2ac953d..61ec986 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -464,6 +464,9 @@ sub setup_admember_rfc2307($$$$)
 	security = ads
         workgroup = $dcvars->{DOMAIN}
         realm = $dcvars->{REALM}
+        idmap config * : backend = autorid
+        idmap config * : range = 1000000-1999999
+        idmap config * : rangesize = 100000
         idmap config $dcvars->{DOMAIN} : backend = rfc2307
         idmap config $dcvars->{DOMAIN} : range = 2000000-2999999
         idmap config $dcvars->{DOMAIN} : ldap_server = ad
-- 
2.5.0


From c9abc50379514fbdfb04936f471a196489af397b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 12 Jun 2016 19:03:11 +0200
Subject: [PATCH 4/4] selftest: test idmap backend id allocation for unknown
 SIDS

If an SID is is not found becaues the RID doesn't exist in a domain and
the domain is configured to use a non-allocating idmap backend like
idmap_ad or idmap_rfc2307, winbindd must not return a mapping for the
SID.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11961

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 nsswitch/tests/test_idmap_nss.sh | 41 ++++++++++++++++++++++++++++++++++++++++
 source3/selftest/tests.py        |  4 +++-
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100755 nsswitch/tests/test_idmap_nss.sh

diff --git a/nsswitch/tests/test_idmap_nss.sh b/nsswitch/tests/test_idmap_nss.sh
new file mode 100755
index 0000000..999bccb
--- /dev/null
+++ b/nsswitch/tests/test_idmap_nss.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Test id mapping with unknown SID and non-allocating idmap backend
+if [ $# -lt 1 ]; then
+	echo Usage: $0 DOMAIN
+	exit 1
+fi
+
+DOMAIN="$1"
+
+wbinfo="$VALGRIND $BINDIR/wbinfo"
+
+failed=0
+
+. `dirname $0`/../../testprogs/blackbox/subunit.sh
+
+testit "wbinfo returns domain SID" $wbinfo -n "@$DOMAIN" || exit 1
+DOMAIN_SID=$($wbinfo -n "@$DOMAIN" | cut -f 1 -d " ")
+echo "Domain $DOMAIN has SID $DOMAIN_SID"
+
+# Find an unused uid and SID
+RID=66666
+while true ; do
+    id $RID
+    if [ $? -ne 0 ] ; then
+	$wbinfo -s $DOMAIN_SID\\$RID
+	if [ $? -ne 0 ] ; then
+	    break
+	fi
+    fi
+    RID=$(expr $RID + 1)
+done
+
+echo "Using non-existing SID $DOMAIN_SID-$RID to check no id allocation is done by the backend"
+
+out="$($wbinfo --sids-to-unix-ids=$DOMAIN_SID-$RID)"
+echo "wbinfo returned: $out"
+test "$out" = "$DOMAIN_SID-$RID -> unmapped"
+ret=$?
+testit "wbinfo SID to xid returns unmapped for unknown SID" test $ret -eq 0 || failed=$(expr $failed + 1)
+
+exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 371ec2a..c6ef9e8 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -306,7 +306,7 @@ rpc = ["rpc.authcontext", "rpc.samba3.bind", "rpc.samba3.srvsvc", "rpc.samba3.sh
 
 local = ["local.nss"]
 
-idmap = [ "idmap.rfc2307" ]
+idmap = ["idmap.rfc2307", "idmap.alloc"]
 
 rap = ["rap.basic", "rap.rpc", "rap.printing", "rap.sam"]
 
@@ -371,6 +371,8 @@ for t in tests:
         plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD')
     elif t == "idmap.rfc2307":
         plantestsuite(t, "ad_member_rfc2307", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_rfc2307.sh"), '$DOMAIN', 'Administrator', '2000000', 'Guest', '2000001', '"Domain Users"', '2000002', 'DnsAdmins', '2000003', 'ou=idmap,dc=samba,dc=example,dc=com', '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD'])
+    elif t == "idmap.alloc":
+        plantestsuite(t, "ad_member_rfc2307", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_nss.sh"), '$DOMAIN'])
     elif t == "raw.acls":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/nfs4acl_simple -U$USERNAME%$PASSWORD', description='nfs4acl_xattr-simple')
-- 
2.5.0



More information about the samba-technical mailing list