[PATCH] idmap autorid extension to support rid greater than rangesize

Michael Adam obnox at samba.org
Thu Apr 25 17:49:23 MDT 2013


Hi Abhidnya and Christian,

On 2013-04-16 at 14:12 +0200, Michael Adam wrote:
> On 2013-04-16 at 13:57 +0200, Christian Ambach wrote:
> > Michael, would you review the patchset please?
> 
> Yep, will do!

I finally found the time to review the patches.
Firstly, it is great to have multi-range-support in idmap_autorid!

Secondly, I have to admit that it took me a long time and gave me
some head aches to understand what was really going on. I found the
naming "multiplier" especially confusing. And while a big
advantage of Abhidnya's patch is that it is fairly minimal,
it leaves a lot of variables at their old names that simply do
not really apply any more.

So as a result of my thoughts about the formulas, I have added
some patches on top of the original patches, that rework the
idmap_autorid code to a state that I think makes the formulas
much more intitive and understandable.

Find the patches in my master-autorid branch
https://gitweb.samba.org/?p=obnox/samba/samba-obnox.git;a=shortlog;h=refs/heads/master-autorid
and also attached in git format.

The outcome is this:

instad of

  id = minvalue + rangesize * domainnum + rid - rangesize * multiplier

we now have

  id = reduced_rid + range_low_id

with

  reduced_rid = rid % rangesize
  range_low_id = minvalue + range_number * rangesize

and range_number the new name for domainnum.
The range_number is associated to the pair
domain_sid and domain_range_index with
domain_range_index = rid / rangesize the new name for multiplier.
(Note that reduced_rid = rid - domain_range_index * rangesize.)

and instead of

  rid = id - minvalue - range * rangesize + rangesize * multiplier

we now have

  rid = reduced_rid  +  domain_range_index * rangesize

with

  reduced_rid = (id - minvalue) % rangesize

and domain_range_index the new name for multiplier which
is obtained from the db with the domain sid by giving the
range_number which is (id - minvalue) / rangesize

The effect is identical, but I think this is much clearer.
What do you think?
If you are ok with this, I suggest that we push the whole
patchset together.

Cheers - Michael

-------------- next part --------------
From 51426eb9bbe0b8ba60157fca6f25e734c47bc615 Mon Sep 17 00:00:00 2001
From: Christian Ambach <ambi at samba.org>
Date: Tue, 9 Apr 2013 23:10:16 +0200
Subject: [PATCH 01/15] lib/replace: prefer inttypes.h over stdint.h

according to C99 7.8, inttypes.h should include stdint.h so prefer inttypes.h
and fall back to stdint.h (and our own definitions of PRI*) only when inttypes.h
could not be found

Signed-off-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/replace/replace.h |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/replace/replace.h b/lib/replace/replace.h
index 9774da4..2262a8b 100644
--- a/lib/replace/replace.h
+++ b/lib/replace/replace.h
@@ -46,14 +46,14 @@
 #endif
 
 
-#ifdef HAVE_STDINT_H
+#ifdef HAVE_INTTYPES_H
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#elif HAVE_STDINT_H
 #include <stdint.h>
 /* force off HAVE_INTTYPES_H so that roken doesn't try to include both,
    which causes a warning storm on irix */
 #undef HAVE_INTTYPES_H
-#elif HAVE_INTTYPES_H
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
 #endif
 
 #ifdef HAVE_MALLOC_H
-- 
1.7.9.5


From a650a3ea7023dbf1e6a5e17a2a42c48ef7c3f655 Mon Sep 17 00:00:00 2001
From: Christian Ambach <ambi at samba.org>
Date: Tue, 16 Apr 2013 10:56:29 +0200
Subject: [PATCH 02/15] lib/replace: add SCNx macros

we already have PRI*, but the corresponding SCN* were missing

Signed-off-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/replace/replace.h |   39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/lib/replace/replace.h b/lib/replace/replace.h
index 2262a8b..c0b7997 100644
--- a/lib/replace/replace.h
+++ b/lib/replace/replace.h
@@ -108,6 +108,45 @@
 # define PRIu64		__PRI64_PREFIX "u"
 #endif
 
+#ifndef SCNd8
+# define SCNd8		"hhd"
+#endif
+#ifndef SCNd16
+# define SCNd16		"hd"
+#endif
+#ifndef SCNd32
+# define SCNd32		"d"
+#endif
+#ifndef SCNd64
+# define SCNd64		__PRI64_PREFIX "d"
+#endif
+
+#ifndef SCNi8
+# define SCNi8		"hhi"
+#endif
+#ifndef SCNi16
+# define SCNi16		"hi"
+#endif
+#ifndef SCNi32
+# define SCNi32		"i"
+#endif
+#ifndef SCNi64
+# define SCNi64		__PRI64_PREFIX "i"
+#endif
+
+#ifndef SCNu8
+# define SCNu8		"hhu"
+#endif
+#ifndef SCNu16
+# define SCNu16		"hu"
+#endif
+#ifndef SCNu32
+# define SCNu32		"u"
+#endif
+#ifndef SCNu64
+# define SCNu64		__PRI64_PREFIX "u"
+#endif
+
 #ifdef HAVE_BSD_STRING_H
 #include <bsd/string.h>
 #endif
-- 
1.7.9.5


From 48afeca203bb8ecfe425175f97a64af1351553af Mon Sep 17 00:00:00 2001
From: Christian Ambach <ambi at samba.org>
Date: Tue, 16 Apr 2013 12:39:39 +0200
Subject: [PATCH 03/15] s3:lib fix wrong usage of PRIu64 in sscanf

Signed-off-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 source3/lib/util_str.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index aa77d75..314c7ea 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -852,7 +852,7 @@ uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
 	while (*p && isspace(*p))
 		p++;
 
-	sscanf(p,"%"PRIu64,&val);
+	sscanf(p,"%"SCNu64,&val);
 	if (entptr) {
 		while (*p && isdigit(*p))
 			p++;
-- 
1.7.9.5


From 7cb71a7dfb7027646528cc06ee3b808a56b07cea Mon Sep 17 00:00:00 2001
From: Christian Ambach <ambi at samba.org>
Date: Tue, 16 Apr 2013 12:39:55 +0200
Subject: [PATCH 04/15] s3:utils fix wrong usage of PRIu64 in sscanf

Signed-off-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 source3/utils/smbcquotas.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c
index 7363d6b..b875b1e 100644
--- a/source3/utils/smbcquotas.c
+++ b/source3/utils/smbcquotas.c
@@ -187,7 +187,9 @@ static int parse_quota_set(TALLOC_CTX *ctx,
 
 	switch (todo) {
 		case PARSE_LIM:
-			if (sscanf(p,"%"PRIu64"/%"PRIu64,&pqt->softlim,&pqt->hardlim)!=2) {
+			if (sscanf(p,"%"SCNu64"/%"SCNu64,&pqt->softlim,
+			    &pqt->hardlim) != 2)
+			{
 				return -1;
 			}
 
-- 
1.7.9.5


From 2f7827d0f02351c2c4f31382fdf1ef7c6ebeab8d Mon Sep 17 00:00:00 2001
From: Abhidnya Joshi <achirmul at in.ibm.com>
Date: Wed, 10 Apr 2013 16:26:07 +0530
Subject: [PATCH 05/15] s3:winbindd/autorid multiple range support

when a mapping request for a RID comes in that is larger
than the rangesize, allocate an extension range to be able
to map this one

This is especially important for large installations which
might have large RIDs being used in a trusted domain that
the administrator was not aware of when planning for autorid
usage and so those objects could not be mapped up to now.
As it is not possible to change the rangesize after the first
start of autorid, this would lead to big trouble.

Signed-off-by: Abhidnya Joshi <achirmul at in.ibm.com>
Reviewed-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   55 +++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 0747916..87833ba 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -51,7 +51,9 @@ struct autorid_global_config {
 
 struct autorid_domain_config {
 	fstring sid;
+	fstring keystr;
 	uint32_t domainnum;
+	uint32_t multiplier;
 	struct autorid_global_config *globalcfg;
 };
 
@@ -68,14 +70,15 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 
 	cfg = (struct autorid_domain_config *)private_data;
 
-	ret = dbwrap_fetch_uint32_bystring(db, cfg->sid, &(cfg->domainnum));
+	ret = dbwrap_fetch_uint32_bystring(db, cfg->keystr, &(cfg->domainnum));
 
 	if (NT_STATUS_IS_OK(ret)) {
 		/* entry is already present*/
 		return ret;
 	}
 
-	DEBUG(10, ("Acquiring new range for domain %s\n", cfg->sid));
+	DEBUG(10, ("Acquiring new range for domain %s (multiplier=%"PRIu32")\n",
+		   cfg->sid, cfg->multiplier));
 
 	/* fetch the current HWM */
 	ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
@@ -102,7 +105,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	/* store away the new mapping in both directions */
-	ret = dbwrap_store_uint32_bystring(db, cfg->sid, domainnum);
+	ret = dbwrap_store_uint32_bystring(db, cfg->keystr, domainnum);
 	if (!NT_STATUS_IS_OK(ret)) {
 		DEBUG(1, ("Fatal error while storing new "
 			  "domain->range assignment!\n"));
@@ -116,7 +119,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	ret = dbwrap_store_bystring(db, numstr,
-			string_term_tdb_data(cfg->sid), TDB_INSERT);
+			string_term_tdb_data(cfg->keystr), TDB_INSERT);
 
 	talloc_free(numstr);
 	if (!NT_STATUS_IS_OK(ret)) {
@@ -124,8 +127,9 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 			  "new domain->range assignment!\n"));
 		goto error;
 	}
-	DEBUG(5, ("Acquired new range #%d for domain %s\n",
-		  domainnum, cfg->sid));
+	DEBUG(5, ("Acquired new range #%d for domain %s "
+		  "(multiplier=%"PRIu32")\n", domainnum, cfg->keystr,
+		  cfg->multiplier));
 
 	cfg->domainnum = domainnum;
 
@@ -146,7 +150,14 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
 	 * if it is not found create a mapping in a transaction unless
 	 * read-only mode has been set
 	 */
-	ret = dbwrap_fetch_uint32_bystring(autorid_db, dom->sid,
+	if (dom->multiplier > 0) {
+		snprintf(dom->keystr, FSTRING_LEN, "%s#%"PRIu32, dom->sid,
+			dom->multiplier);
+	} else {
+		fstrcpy(dom->keystr, dom->sid);
+	}
+
+	ret = dbwrap_fetch_uint32_bystring(autorid_db, dom->keystr,
 					   &(dom->domainnum));
 
 	if (!NT_STATUS_IS_OK(ret)) {
@@ -157,8 +168,8 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
 			      idmap_autorid_get_domainrange_action, dom);
 	}
 
-	DEBUG(10, ("Using range #%d for domain %s\n", dom->domainnum,
-		   dom->sid));
+	DEBUG(10, ("Using range #%d for domain %s (multiplier=%"PRIu32")\n",
+		   dom->domainnum, dom->sid, dom->multiplier));
 
 	return ret;
 }
@@ -244,11 +255,13 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 					struct id_map *map)
 {
 	uint32_t range;
+	uint32_t multiplier = 0;
 	TDB_DATA data = tdb_null;
 	char *keystr;
 	struct dom_sid sid;
 	NTSTATUS status;
 	bool ok;
+	const char *q = NULL;
 
 	/* can this be one of our ids? */
 	if (map->xid.id < cfg->minvalue) {
@@ -298,16 +311,23 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 		return idmap_autorid_map_id_to_sid(dom, map);
 	}
 
-	ok = string_to_sid(&sid, (const char *)data.dptr);
+	ok = dom_sid_parse_endp((const char *)data.dptr, &sid, &q);
 	TALLOC_FREE(data.dptr);
 	if (!ok) {
 		map->status = ID_UNKNOWN;
 		return NT_STATUS_OK;
 	}
+	if (q != NULL)
+		if (sscanf(q+1, "%"SCNu32, &multiplier) != 1) {
+			DEBUG(10, ("Multiplier not found! "
+				   "ignoring mapping request\n"));
+			map->status = ID_UNKNOWN;
+			return NT_STATUS_OK;
+		}
 
 	sid_compose(map->sid, &sid,
 		    (map->xid.id - cfg->minvalue -
-		     range * cfg->rangesize));
+		     range * cfg->rangesize + (cfg->rangesize * multiplier)));
 
 	/* We **really** should have some way of validating
 	   the SID exists and is the correct type here.  But
@@ -331,15 +351,9 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 
 	sid_peek_rid(map->sid, &rid);
 
-	/* if the rid is higher than the size of the range, we cannot map it */
-	if (rid >= global->rangesize) {
-		map->status = ID_UNKNOWN;
-		DEBUG(2, ("RID %d is larger then size of range (%d), "
-			  "user cannot be mapped\n", rid, global->rangesize));
-		return NT_STATUS_UNSUCCESSFUL;
-	}
 	map->xid.id = global->minvalue +
-	    (global->rangesize * domain->domainnum)+rid;
+	    (global->rangesize * domain->domainnum) + rid -
+	    (global->rangesize * domain->multiplier);
 	map->xid.type = ID_TYPE_BOTH;
 
 	/* We **really** should have some way of validating
@@ -563,6 +577,9 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
 		domaincfg.globalcfg = global;
 		sid_to_fstring(domaincfg.sid, &domainsid);
 
+		/* Calculate multiplier for multi-range support */
+		domaincfg.multiplier = rid / (global->rangesize);
+
 		ret = idmap_autorid_get_domainrange(&domaincfg, dom->read_only);
 
 		/* read-only mode and a new domain range would be required? */
-- 
1.7.9.5


From e4c0331ead80577ba8913f55d7b0b53f4373abd0 Mon Sep 17 00:00:00 2001
From: Abhidnya Joshi <achirmul at in.ibm.com>
Date: Tue, 16 Apr 2013 16:41:45 +0530
Subject: [PATCH 06/15] docs-xml: manpage update for autorid multirange
 support

Signed-off-by: Abhidnya Joshi <achirmul at in.ibm.com>
Reviewed-by: Christian Ambach <ambi at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 docs-xml/manpages/idmap_autorid.8.xml |   34 +++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/docs-xml/manpages/idmap_autorid.8.xml b/docs-xml/manpages/idmap_autorid.8.xml
index ed698e9..8ce281d 100644
--- a/docs-xml/manpages/idmap_autorid.8.xml
+++ b/docs-xml/manpages/idmap_autorid.8.xml
@@ -40,17 +40,21 @@
 		<varlistentry>
 		<term>rangesize = numberofidsperdomain</term>
 		<listitem><para>
-			Defines the available number of uids/gids per domain. The
-			minimum needed value is 2000. SIDs with RIDs larger than this
-			value cannot be mapped, are ignored and the corresponding map
-			is discarded. Choose this value carefully, as this should
-			not be changed after the first ranges for domains have been
-			defined, otherwise mappings between domains will get intermixed
-			leading to unpredictable results. Please note that RIDs in Windows
-			Domains usually start with 500 for builtin users and 1000
-			for regular users. As the parameter cannot be changed later, please
-			plan accordingly for your expected number of users in a domain
-			with safety margins.
+			Defines the number of uids/gids available per
+			domain range. The minimum needed value is 2000.
+			SIDs with RIDs larger than this value will be mapped
+			into extension ranges depending upon number of available
+			ranges. If the autorid backend runs out of available
+			ranges, mapping requests for new domains (or new
+			extension ranges for domains already known) are ignored
+			and the corresponding map is discarded.
+			</para>
+			<para>
+			Example: with rangesize set to 10000, users/groups with
+			a RID up to 10000 will be put into the first range for the
+			domain. When attempting to map the an object with a RID
+			of 25000, an extension range will be allocated that
+			will then be used to map all RIDs from 20000-29999.
 			</para>
 			<para>One range will be used for local users and groups and for
 			non-domain well-known SIDs like Everyone (S-1-1-0) or Creator Owner (S-1-3-0).
@@ -85,6 +89,7 @@
 		The Unix ID for a RID is calculated this way:
 		<programlisting>
 			ID = IDMAP UID LOW VALUE + DOMAINRANGENUMBER * RANGESIZE + RID
+			- (MULTIPLIER * RANGESIZE)
 		</programlisting>
 	</para>
 	<para>
@@ -92,15 +97,20 @@
 		given Unix ID is this:
 		<programlisting>
 			RID = ID - IDMAP UID LOW VALUE - DOMAINRANGENUMBER * RANGESIZE
+			+ (MULTIPLIER * RANGESIZE)
 		</programlisting>
 	</para>
+	<para>
+		MULTIPLIER is calculated as FLOOR(RID / RANGESIZE).
+	</para>
 </refsect1>
 
 <refsect1>
 	<title>EXAMPLES</title>
 	<para>
 		This example shows you the minimal configuration that will
-		work for the principial domain and 19 trusted domains.
+		work for the principial domain and 19 trusted domains / range
+		extensions.
 	</para>
 
 	<programlisting>
-- 
1.7.9.5


From a95dcbc0e2d85085975e6836250e6a2aa0a7cac3 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 13:56:03 +0200
Subject: [PATCH 07/15] s3:idmap:autorid: rename domainnum to rangenum

Now ranges don't correspond to domains any more, but
multiple ranges are associated to a domain. So the name
is misleading.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 87833ba..41ea655 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -52,7 +52,7 @@ struct autorid_global_config {
 struct autorid_domain_config {
 	fstring sid;
 	fstring keystr;
-	uint32_t domainnum;
+	uint32_t rangenum;
 	uint32_t multiplier;
 	struct autorid_global_config *globalcfg;
 };
@@ -64,13 +64,13 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 					      void *private_data)
 {
 	NTSTATUS ret;
-	uint32_t domainnum, hwm;
+	uint32_t rangenum, hwm;
 	char *numstr;
 	struct autorid_domain_config *cfg;
 
 	cfg = (struct autorid_domain_config *)private_data;
 
-	ret = dbwrap_fetch_uint32_bystring(db, cfg->keystr, &(cfg->domainnum));
+	ret = dbwrap_fetch_uint32_bystring(db, cfg->keystr, &(cfg->rangenum));
 
 	if (NT_STATUS_IS_OK(ret)) {
 		/* entry is already present*/
@@ -97,7 +97,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	/* increase the HWM */
-	ret = dbwrap_change_uint32_atomic_bystring(db, HWM, &domainnum, 1);
+	ret = dbwrap_change_uint32_atomic_bystring(db, HWM, &rangenum, 1);
 	if (!NT_STATUS_IS_OK(ret)) {
 		DEBUG(1, ("Fatal error while fetching a new "
 			  "domain range value!\n"));
@@ -105,14 +105,14 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	/* store away the new mapping in both directions */
-	ret = dbwrap_store_uint32_bystring(db, cfg->keystr, domainnum);
+	ret = dbwrap_store_uint32_bystring(db, cfg->keystr, rangenum);
 	if (!NT_STATUS_IS_OK(ret)) {
 		DEBUG(1, ("Fatal error while storing new "
 			  "domain->range assignment!\n"));
 		goto error;
 	}
 
-	numstr = talloc_asprintf(db, "%u", domainnum);
+	numstr = talloc_asprintf(db, "%u", rangenum);
 	if (!numstr) {
 		ret = NT_STATUS_NO_MEMORY;
 		goto error;
@@ -128,10 +128,10 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 		goto error;
 	}
 	DEBUG(5, ("Acquired new range #%d for domain %s "
-		  "(multiplier=%"PRIu32")\n", domainnum, cfg->keystr,
+		  "(multiplier=%"PRIu32")\n", rangenum, cfg->keystr,
 		  cfg->multiplier));
 
-	cfg->domainnum = domainnum;
+	cfg->rangenum = rangenum;
 
 	return NT_STATUS_OK;
 
@@ -158,7 +158,7 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
 	}
 
 	ret = dbwrap_fetch_uint32_bystring(autorid_db, dom->keystr,
-					   &(dom->domainnum));
+					   &(dom->rangenum));
 
 	if (!NT_STATUS_IS_OK(ret)) {
 		if (read_only) {
@@ -169,7 +169,7 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
 	}
 
 	DEBUG(10, ("Using range #%d for domain %s (multiplier=%"PRIu32")\n",
-		   dom->domainnum, dom->sid, dom->multiplier));
+		   dom->rangenum, dom->sid, dom->multiplier));
 
 	return ret;
 }
@@ -218,7 +218,7 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
 	}
 
 	xid->id = globalcfg->minvalue +
-		  globalcfg->rangesize * domaincfg.domainnum +
+		  globalcfg->rangesize * domaincfg.rangenum +
 		  xid->id;
 
 	DEBUG(10, ("Returned new %s %d from allocation range\n",
@@ -352,7 +352,7 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 	sid_peek_rid(map->sid, &rid);
 
 	map->xid.id = global->minvalue +
-	    (global->rangesize * domain->domainnum) + rid -
+	    (global->rangesize * domain->rangenum) + rid -
 	    (global->rangesize * domain->multiplier);
 	map->xid.type = ID_TYPE_BOTH;
 
-- 
1.7.9.5


From d4845244ebf871b8009641730fe4aaec10e1aa40 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 19:04:56 +0200
Subject: [PATCH 08/15] s3:idmap:autorid: rename autorid_domain_config -->
 autorid_range_config and instances to "range"

This describes it better with the new support for multiple ranges for domains.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   72 +++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 36 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 41ea655..5cfdf85 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -49,7 +49,7 @@ struct autorid_global_config {
 	bool ignore_builtin;
 };
 
-struct autorid_domain_config {
+struct autorid_range_config {
 	fstring sid;
 	fstring keystr;
 	uint32_t rangenum;
@@ -66,11 +66,11 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	NTSTATUS ret;
 	uint32_t rangenum, hwm;
 	char *numstr;
-	struct autorid_domain_config *cfg;
+	struct autorid_range_config *range;
 
-	cfg = (struct autorid_domain_config *)private_data;
+	range = (struct autorid_range_config *)private_data;
 
-	ret = dbwrap_fetch_uint32_bystring(db, cfg->keystr, &(cfg->rangenum));
+	ret = dbwrap_fetch_uint32_bystring(db, range->keystr, &(range->rangenum));
 
 	if (NT_STATUS_IS_OK(ret)) {
 		/* entry is already present*/
@@ -78,7 +78,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	DEBUG(10, ("Acquiring new range for domain %s (multiplier=%"PRIu32")\n",
-		   cfg->sid, cfg->multiplier));
+		   range->sid, range->multiplier));
 
 	/* fetch the current HWM */
 	ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
@@ -90,7 +90,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	/* do we have a range left? */
-	if (hwm >= cfg->globalcfg->maxranges) {
+	if (hwm >= range->globalcfg->maxranges) {
 		DEBUG(1, ("No more domain ranges available!\n"));
 		ret = NT_STATUS_NO_MEMORY;
 		goto error;
@@ -105,7 +105,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	/* store away the new mapping in both directions */
-	ret = dbwrap_store_uint32_bystring(db, cfg->keystr, rangenum);
+	ret = dbwrap_store_uint32_bystring(db, range->keystr, rangenum);
 	if (!NT_STATUS_IS_OK(ret)) {
 		DEBUG(1, ("Fatal error while storing new "
 			  "domain->range assignment!\n"));
@@ -119,7 +119,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	ret = dbwrap_store_bystring(db, numstr,
-			string_term_tdb_data(cfg->keystr), TDB_INSERT);
+			string_term_tdb_data(range->keystr), TDB_INSERT);
 
 	talloc_free(numstr);
 	if (!NT_STATUS_IS_OK(ret)) {
@@ -128,10 +128,10 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 		goto error;
 	}
 	DEBUG(5, ("Acquired new range #%d for domain %s "
-		  "(multiplier=%"PRIu32")\n", rangenum, cfg->keystr,
-		  cfg->multiplier));
+		  "(multiplier=%"PRIu32")\n", rangenum, range->keystr,
+		  range->multiplier));
 
-	cfg->rangenum = rangenum;
+	range->rangenum = rangenum;
 
 	return NT_STATUS_OK;
 
@@ -140,7 +140,7 @@ error:
 
 }
 
-static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
+static NTSTATUS idmap_autorid_get_domainrange(struct autorid_range_config *range,
 					      bool read_only)
 {
 	NTSTATUS ret;
@@ -150,26 +150,26 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_domain_config *dom,
 	 * if it is not found create a mapping in a transaction unless
 	 * read-only mode has been set
 	 */
-	if (dom->multiplier > 0) {
-		snprintf(dom->keystr, FSTRING_LEN, "%s#%"PRIu32, dom->sid,
-			dom->multiplier);
+	if (range->multiplier > 0) {
+		snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32, range->sid,
+			range->multiplier);
 	} else {
-		fstrcpy(dom->keystr, dom->sid);
+		fstrcpy(range->keystr, range->sid);
 	}
 
-	ret = dbwrap_fetch_uint32_bystring(autorid_db, dom->keystr,
-					   &(dom->rangenum));
+	ret = dbwrap_fetch_uint32_bystring(autorid_db, range->keystr,
+					   &(range->rangenum));
 
 	if (!NT_STATUS_IS_OK(ret)) {
 		if (read_only) {
 			return NT_STATUS_NOT_FOUND;
 		}
 		ret = dbwrap_trans_do(autorid_db,
-			      idmap_autorid_get_domainrange_action, dom);
+			      idmap_autorid_get_domainrange_action, range);
 	}
 
 	DEBUG(10, ("Using range #%d for domain %s (multiplier=%"PRIu32")\n",
-		   dom->rangenum, dom->sid, dom->multiplier));
+		   range->rangenum, range->sid, range->multiplier));
 
 	return ret;
 }
@@ -180,7 +180,7 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
 	NTSTATUS ret;
 	struct idmap_tdb_common_context *commoncfg;
 	struct autorid_global_config *globalcfg;
-	struct autorid_domain_config domaincfg;
+	struct autorid_range_config range;
 
 	commoncfg =
 	    talloc_get_type_abort(dom->private_data,
@@ -197,12 +197,12 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
 
 	/* fetch the range for the allocation pool */
 
-	ZERO_STRUCT(domaincfg);
+	ZERO_STRUCT(range);
 
-	domaincfg.globalcfg = globalcfg;
-	fstrcpy(domaincfg.sid, ALLOC_RANGE);
+	range.globalcfg = globalcfg;
+	fstrcpy(range.sid, ALLOC_RANGE);
 
-	ret = idmap_autorid_get_domainrange(&domaincfg, dom->read_only);
+	ret = idmap_autorid_get_domainrange(&range, dom->read_only);
 
 	if (!NT_STATUS_IS_OK(ret)) {
 		DEBUG(3, ("Could not determine range for allocation pool, "
@@ -218,7 +218,7 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
 	}
 
 	xid->id = globalcfg->minvalue +
-		  globalcfg->rangesize * domaincfg.rangenum +
+		  globalcfg->rangesize * range.rangenum +
 		  xid->id;
 
 	DEBUG(10, ("Returned new %s %d from allocation range\n",
@@ -344,7 +344,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 **********************************/
 
 static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
-					struct autorid_domain_config *domain,
+					struct autorid_range_config *range,
 					struct id_map *map)
 {
 	uint32_t rid;
@@ -352,8 +352,8 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 	sid_peek_rid(map->sid, &rid);
 
 	map->xid.id = global->minvalue +
-	    (global->rangesize * domain->rangenum) + rid -
-	    (global->rangesize * domain->multiplier);
+	    (global->rangesize * range->rangenum) + rid -
+	    (global->rangesize * range->multiplier);
 	map->xid.type = ID_TYPE_BOTH;
 
 	/* We **really** should have some way of validating
@@ -514,11 +514,11 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
 
 	for (i = 0; ids[i]; i++) {
 		struct winbindd_tdc_domain *domain;
-		struct autorid_domain_config domaincfg;
+		struct autorid_range_config range;
 		uint32_t rid;
 		struct dom_sid domainsid;
 
-		ZERO_STRUCT(domaincfg);
+		ZERO_STRUCT(range);
 
 		DEBUG(10, ("Trying to map %s\n", sid_string_dbg(ids[i]->sid)));
 
@@ -574,13 +574,13 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
 		}
 		TALLOC_FREE(domain);
 
-		domaincfg.globalcfg = global;
-		sid_to_fstring(domaincfg.sid, &domainsid);
+		range.globalcfg = global;
+		sid_to_fstring(range.sid, &domainsid);
 
 		/* Calculate multiplier for multi-range support */
-		domaincfg.multiplier = rid / (global->rangesize);
+		range.multiplier = rid / (global->rangesize);
 
-		ret = idmap_autorid_get_domainrange(&domaincfg, dom->read_only);
+		ret = idmap_autorid_get_domainrange(&range, dom->read_only);
 
 		/* read-only mode and a new domain range would be required? */
 		if (NT_STATUS_EQUAL(ret, NT_STATUS_NOT_FOUND) &&
@@ -597,7 +597,7 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
 			goto failure;
 		}
 
-		ret = idmap_autorid_sid_to_id(global, &domaincfg, ids[i]);
+		ret = idmap_autorid_sid_to_id(global, &range, ids[i]);
 
 		if ((!NT_STATUS_IS_OK(ret)) &&
 		    (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
-- 
1.7.9.5


From f2a04a543db72a13b92754e3170885b714f3e7b4 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 19:13:45 +0200
Subject: [PATCH 09/15] s3:idmap:autorid: rename autorid_range_config.sid to
 domsid, along with instances

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 5cfdf85..1b0a37a 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -50,7 +50,7 @@ struct autorid_global_config {
 };
 
 struct autorid_range_config {
-	fstring sid;
+	fstring domsid;
 	fstring keystr;
 	uint32_t rangenum;
 	uint32_t multiplier;
@@ -78,7 +78,7 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 	}
 
 	DEBUG(10, ("Acquiring new range for domain %s (multiplier=%"PRIu32")\n",
-		   range->sid, range->multiplier));
+		   range->domsid, range->multiplier));
 
 	/* fetch the current HWM */
 	ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
@@ -150,11 +150,11 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_range_config *range
 	 * if it is not found create a mapping in a transaction unless
 	 * read-only mode has been set
 	 */
-	if (range->multiplier > 0) {
-		snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32, range->sid,
-			range->multiplier);
+	if (range->domain_range_index > 0) {
+		snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32,
+			 range->domsid, range->multiplier);
 	} else {
-		fstrcpy(range->keystr, range->sid);
+		fstrcpy(range->keystr, range->domsid);
 	}
 
 	ret = dbwrap_fetch_uint32_bystring(autorid_db, range->keystr,
@@ -169,7 +169,7 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_range_config *range
 	}
 
 	DEBUG(10, ("Using range #%d for domain %s (multiplier=%"PRIu32")\n",
-		   range->rangenum, range->sid, range->multiplier));
+		   range->rangenum, range->domsid, range->multiplier));
 
 	return ret;
 }
@@ -200,7 +200,7 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
 	ZERO_STRUCT(range);
 
 	range.globalcfg = globalcfg;
-	fstrcpy(range.sid, ALLOC_RANGE);
+	fstrcpy(range.domsid, ALLOC_RANGE);
 
 	ret = idmap_autorid_get_domainrange(&range, dom->read_only);
 
@@ -258,7 +258,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 	uint32_t multiplier = 0;
 	TDB_DATA data = tdb_null;
 	char *keystr;
-	struct dom_sid sid;
+	struct dom_sid domsid;
 	NTSTATUS status;
 	bool ok;
 	const char *q = NULL;
@@ -311,7 +311,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 		return idmap_autorid_map_id_to_sid(dom, map);
 	}
 
-	ok = dom_sid_parse_endp((const char *)data.dptr, &sid, &q);
+	ok = dom_sid_parse_endp((const char *)data.dptr, &domsid, &q);
 	TALLOC_FREE(data.dptr);
 	if (!ok) {
 		map->status = ID_UNKNOWN;
@@ -325,7 +325,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 			return NT_STATUS_OK;
 		}
 
-	sid_compose(map->sid, &sid,
+	sid_compose(map->sid, &domsid,
 		    (map->xid.id - cfg->minvalue -
 		     range * cfg->rangesize + (cfg->rangesize * multiplier)));
 
@@ -575,7 +575,7 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
 		TALLOC_FREE(domain);
 
 		range.globalcfg = global;
-		sid_to_fstring(range.sid, &domainsid);
+		sid_to_fstring(range.domsid, &domainsid);
 
 		/* Calculate multiplier for multi-range support */
 		range.multiplier = rid / (global->rangesize);
-- 
1.7.9.5


From 5b502b2cf1508e3f14101d1bd8f7a009f272ccd3 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 19:18:27 +0200
Subject: [PATCH 10/15] s3:idmap:autorid: rename range.multiplier to
 domain_range_index

The name multiplier is very confusing (at least for me).
This is an index that is used to reference the various
per-domain ranges.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 1b0a37a..95ed6e0 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -53,7 +53,7 @@ struct autorid_range_config {
 	fstring domsid;
 	fstring keystr;
 	uint32_t rangenum;
-	uint32_t multiplier;
+	uint32_t domain_range_index;
 	struct autorid_global_config *globalcfg;
 };
 
@@ -77,8 +77,9 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 		return ret;
 	}
 
-	DEBUG(10, ("Acquiring new range for domain %s (multiplier=%"PRIu32")\n",
-		   range->domsid, range->multiplier));
+	DEBUG(10, ("Acquiring new range for domain %s "
+		   "(domain_range_index=%"PRIu32")\n",
+		   range->domsid, range->domain_range_index));
 
 	/* fetch the current HWM */
 	ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
@@ -128,8 +129,8 @@ static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
 		goto error;
 	}
 	DEBUG(5, ("Acquired new range #%d for domain %s "
-		  "(multiplier=%"PRIu32")\n", rangenum, range->keystr,
-		  range->multiplier));
+		  "(domain_range_index=%"PRIu32")\n", rangenum, range->keystr,
+		  range->domain_range_index));
 
 	range->rangenum = rangenum;
 
@@ -152,7 +153,7 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_range_config *range
 	 */
 	if (range->domain_range_index > 0) {
 		snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32,
-			 range->domsid, range->multiplier);
+			 range->domsid, range->domain_range_index);
 	} else {
 		fstrcpy(range->keystr, range->domsid);
 	}
@@ -168,8 +169,9 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_range_config *range
 			      idmap_autorid_get_domainrange_action, range);
 	}
 
-	DEBUG(10, ("Using range #%d for domain %s (multiplier=%"PRIu32")\n",
-		   range->rangenum, range->domsid, range->multiplier));
+	DEBUG(10, ("Using range #%d for domain %s "
+		   "(domain_range_index=%"PRIu32")\n",
+		   range->rangenum, range->domsid, range->domain_range_index));
 
 	return ret;
 }
@@ -255,7 +257,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 					struct id_map *map)
 {
 	uint32_t range;
-	uint32_t multiplier = 0;
+	uint32_t domain_range_index = 0;
 	TDB_DATA data = tdb_null;
 	char *keystr;
 	struct dom_sid domsid;
@@ -318,7 +320,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 		return NT_STATUS_OK;
 	}
 	if (q != NULL)
-		if (sscanf(q+1, "%"SCNu32, &multiplier) != 1) {
+		if (sscanf(q+1, "%"SCNu32, &domain_range_index) != 1) {
 			DEBUG(10, ("Multiplier not found! "
 				   "ignoring mapping request\n"));
 			map->status = ID_UNKNOWN;
@@ -327,7 +329,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 
 	sid_compose(map->sid, &domsid,
 		    (map->xid.id - cfg->minvalue -
-		     range * cfg->rangesize + (cfg->rangesize * multiplier)));
+		     range * cfg->rangesize + (cfg->rangesize * domain_range_index)));
 
 	/* We **really** should have some way of validating
 	   the SID exists and is the correct type here.  But
@@ -353,7 +355,7 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 
 	map->xid.id = global->minvalue +
 	    (global->rangesize * range->rangenum) + rid -
-	    (global->rangesize * range->multiplier);
+	    (global->rangesize * range->domain_range_index);
 	map->xid.type = ID_TYPE_BOTH;
 
 	/* We **really** should have some way of validating
@@ -577,8 +579,8 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
 		range.globalcfg = global;
 		sid_to_fstring(range.domsid, &domainsid);
 
-		/* Calculate multiplier for multi-range support */
-		range.multiplier = rid / (global->rangesize);
+		/* Calculate domain_range_index for multi-range support */
+		range.domain_range_index = rid / (global->rangesize);
 
 		ret = idmap_autorid_get_domainrange(&range, dom->read_only);
 
-- 
1.7.9.5


From d3b3dea7b659fb7fdcc6b5be6628ec830ab2f660 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 19:47:00 +0200
Subject: [PATCH 11/15] s3:idmap:autorid: make calculation in
 idmap_autorid_sid_to_id much more obvious

This is my attempt to make the sid->unix-id calculation much more obvious.
Especially with the introduction of the multi-range support an the originally
named "multiplier", the calculation

id = low_id + range_size * domain_number + rid - range_size * multiplier

was rather opaque to me.

What really happens here is this:
The rid is split into a reduced_rid part that is < rangesize and
a multiple of rangesize. This is given by the formula

rid = rid % range_size + (rid / range_size) * range_size

We define
 reduced_rid := rid % range_size
and
 domain_range_index := rid / range_size ( == the original multiplier)

and the original formula is equivalent to:

id = reduced_rid + low_id + range_number * range_size;

and reads

id = reduced_rid + range_minvalue

if we set range_minvalue := low_id + range_number * range_size.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 95ed6e0..adf995c 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -350,12 +350,15 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 					struct id_map *map)
 {
 	uint32_t rid;
+	uint32_t reduced_rid;
+	uint32_t range_start;
 
 	sid_peek_rid(map->sid, &rid);
 
-	map->xid.id = global->minvalue +
-	    (global->rangesize * range->rangenum) + rid -
-	    (global->rangesize * range->domain_range_index);
+	reduced_rid = rid % global->rangesize;
+	range_start = global->minvalue + range->rangenum * global->rangesize;
+
+	map->xid.id = reduced_rid + range_start;
 	map->xid.type = ID_TYPE_BOTH;
 
 	/* We **really** should have some way of validating
-- 
1.7.9.5


From 99d743c609a0ef5f26302dea13bb3d6b36222404 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 20:12:39 +0200
Subject: [PATCH 12/15] s3:idmap:autorid: calculate the range's low_id in
 idmap_autorid_get_domainrange()

This way, the calculation needs to be don only in one central place and
the formulas get simpler.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index adf995c..1453a59 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -54,6 +54,7 @@ struct autorid_range_config {
 	fstring keystr;
 	uint32_t rangenum;
 	uint32_t domain_range_index;
+	uint32_t low_id;
 	struct autorid_global_config *globalcfg;
 };
 
@@ -169,6 +170,9 @@ static NTSTATUS idmap_autorid_get_domainrange(struct autorid_range_config *range
 			      idmap_autorid_get_domainrange_action, range);
 	}
 
+	range->low_id = range->globalcfg->minvalue
+		      + range->rangenum * range->globalcfg->rangesize;
+
 	DEBUG(10, ("Using range #%d for domain %s "
 		   "(domain_range_index=%"PRIu32")\n",
 		   range->rangenum, range->domsid, range->domain_range_index));
@@ -219,9 +223,7 @@ static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
 		return ret;
 	}
 
-	xid->id = globalcfg->minvalue +
-		  globalcfg->rangesize * range.rangenum +
-		  xid->id;
+	xid->id = xid->id + range.low_id;
 
 	DEBUG(10, ("Returned new %s %d from allocation range\n",
 		   (xid->type==ID_TYPE_UID)?"uid":"gid", xid->id));
@@ -351,14 +353,12 @@ static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
 {
 	uint32_t rid;
 	uint32_t reduced_rid;
-	uint32_t range_start;
 
 	sid_peek_rid(map->sid, &rid);
 
 	reduced_rid = rid % global->rangesize;
-	range_start = global->minvalue + range->rangenum * global->rangesize;
 
-	map->xid.id = reduced_rid + range_start;
+	map->xid.id = reduced_rid + range->low_id;
 	map->xid.type = ID_TYPE_BOTH;
 
 	/* We **really** should have some way of validating
-- 
1.7.9.5


From a381e19750cb493973321f864f34b46dfcce90d5 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 25 Apr 2013 20:24:36 +0200
Subject: [PATCH 13/15] s3:idmap:autorid: simplify the id->sid calculation

To make it more intutive.

rid = reduced_rid + domain_range_index * range_size

where

reduced_rid = (id - id_low) % range_size

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 1453a59..7a7ef56 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -258,8 +258,11 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 					struct idmap_domain *dom,
 					struct id_map *map)
 {
-	uint32_t range;
+	uint32_t range_number;
 	uint32_t domain_range_index = 0;
+	uint32_t normalized_id;
+	uint32_t reduced_rid;
+	uint32_t rid;
 	TDB_DATA data = tdb_null;
 	char *keystr;
 	struct dom_sid domsid;
@@ -283,9 +286,11 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 	}
 
 	/* determine the range of this uid */
-	range = ((map->xid.id - cfg->minvalue) / cfg->rangesize);
 
-	keystr = talloc_asprintf(talloc_tos(), "%u", range);
+	normalized_id = map->xid.id - cfg->minvalue;
+	range_number = normalized_id / cfg->rangesize;
+
+	keystr = talloc_asprintf(talloc_tos(), "%u", range_number);
 	if (!keystr) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -296,7 +301,7 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(4, ("id %d belongs to range %d which does not have "
 			  "domain mapping, ignoring mapping request\n",
-			  map->xid.id, range));
+			  map->xid.id, range_number));
 		TALLOC_FREE(data.dptr);
 		map->status = ID_UNKNOWN;
 		return NT_STATUS_OK;
@@ -329,9 +334,10 @@ static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
 			return NT_STATUS_OK;
 		}
 
-	sid_compose(map->sid, &domsid,
-		    (map->xid.id - cfg->minvalue -
-		     range * cfg->rangesize + (cfg->rangesize * domain_range_index)));
+	reduced_rid = normalized_id % cfg->rangesize;
+	rid = reduced_rid + domain_range_index * cfg->rangesize;
+
+	sid_compose(map->sid, &domsid, rid);
 
 	/* We **really** should have some way of validating
 	   the SID exists and is the correct type here.  But
-- 
1.7.9.5


From 342651b2963d06dce84c597804b96aad9eb799a6 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 26 Apr 2013 00:52:49 +0200
Subject: [PATCH 14/15] s3:idmap:autorid: add a comment block explaining the
 calculations

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/winbindd/idmap_autorid.c |   51 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c
index 7a7ef56..20293d3 100644
--- a/source3/winbindd/idmap_autorid.c
+++ b/source3/winbindd/idmap_autorid.c
@@ -22,6 +22,57 @@
  *
  */
 
+/*
+ * This module allocates ranges for domains to be used in a
+ * algorithmic mode like idmap_rid. Multiple ranges are supported
+ * for a single domain: If a rid exceeds the range size, a matching
+ * range is allocated to hold the rid's id.
+ *
+ * Here are the formulas applied:
+ *
+ *
+ * For a sid of the form domain_sid-rid, we have
+ *
+ *   rid = reduced_rid + domain_range_index * range_size
+ *
+ * with
+ *   reduced_rid := rid % range_size
+ *   domain_range_index := rid / range_size
+ *
+ * And reduced_rid fits into a range.
+ *
+ * In the database, we associate a range_number to
+ * the pair domain_sid,domain_range_index.
+ *
+ * Now the unix id for the given sid calculates as:
+ *
+ *   id = reduced_rid + range_low_id
+ *
+ * with
+ *
+ *   range_low_id = low_id + range_number * range_size
+ *
+ *
+ * The inverse calculation goes like this:
+ *
+ * Given a unix id, let
+ *
+ *   normalized_id := id - low_id
+ *   reduced_rid := normalized_id % range_size
+ *   range_number = normalized_id / range_size
+ *
+ * Then we have
+ *
+ *   id = reduced_rid + low_id + range_number * range_size
+ *
+ * From the database, get the domain_sid,domain_range_index pair
+ * belonging to the range_number (if there is already one).
+ *
+ * Then the rid for the unix id calculates as:
+ *
+ *   rid = reduced_rid + domain_range_index * range_size
+ */
+
 #include "includes.h"
 #include "system/filesys.h"
 #include "winbindd.h"
-- 
1.7.9.5


From 6571df1cadd742384d6da0a87288a0f33c6f3cf7 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 26 Apr 2013 01:06:58 +0200
Subject: [PATCH 15/15] docs: update the description of the formulas in the
 idmap_autorid manpage

Signed-off-by: Michael Adam <obnox at samba.org>
---
 docs-xml/manpages/idmap_autorid.8.xml |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/docs-xml/manpages/idmap_autorid.8.xml b/docs-xml/manpages/idmap_autorid.8.xml
index 8ce281d..c35f903 100644
--- a/docs-xml/manpages/idmap_autorid.8.xml
+++ b/docs-xml/manpages/idmap_autorid.8.xml
@@ -88,20 +88,20 @@
 	<para>
 		The Unix ID for a RID is calculated this way:
 		<programlisting>
-			ID = IDMAP UID LOW VALUE + DOMAINRANGENUMBER * RANGESIZE + RID
-			- (MULTIPLIER * RANGESIZE)
+			ID =  REDUCED RID + IDMAP RANGE LOW VALUE + RANGE NUMBER * RANGE SIZE
 		</programlisting>
+		where REDUCED RID = RID % RANGE_SIZE
+		and a DOMAIN RANGE INDEX = RID / RANGE_SIZE is used together with the
+		domain sid to determine the RANGE NUMBER (stored in the database).
 	</para>
 	<para>
 		Correspondingly, the formula for calculating the RID for a
 		given Unix ID is this:
 		<programlisting>
-			RID = ID - IDMAP UID LOW VALUE - DOMAINRANGENUMBER * RANGESIZE
-			+ (MULTIPLIER * RANGESIZE)
+			RID = (ID - LOW ID) % RANGE SIZE + DOMAIN RANGE INDEX * RANGE SIZE
 		</programlisting>
-	</para>
-	<para>
-		MULTIPLIER is calculated as FLOOR(RID / RANGESIZE).
+		Where the DOMAIN RANGE INDEX is retrieved from the database along with the
+		domain sid by the RANGE NUMBER = (ID - LOW ID) / RANGE SIZE .
 	</para>
 </refsect1>
 
-- 
1.7.9.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 206 bytes
Desc: Digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20130426/25678953/attachment.pgp>


More information about the samba-technical mailing list