2 * idmap_autorid: static map between Active Directory/NT RIDs
3 * and RFC 2307 accounts
5 * based on the idmap_rid module, but this module defines the ranges
6 * for the domains by automatically allocating a range for each domain
8 * Copyright (C) Christian Ambach, 2010-2012
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 * This module allocates ranges for domains to be used in a
27 * algorithmic mode like idmap_rid. Multiple ranges are supported
28 * for a single domain: If a rid exceeds the range size, a matching
29 * range is allocated to hold the rid's id.
31 * Here are the formulas applied:
34 * For a sid of the form domain_sid-rid, we have
36 * rid = reduced_rid + domain_range_index * range_size
39 * reduced_rid := rid % range_size
40 * domain_range_index := rid / range_size
42 * And reduced_rid fits into a range.
44 * In the database, we associate a range_number to
45 * the pair domain_sid,domain_range_index.
47 * Now the unix id for the given sid calculates as:
49 * id = reduced_rid + range_low_id
53 * range_low_id = low_id + range_number * range_size
56 * The inverse calculation goes like this:
58 * Given a unix id, let
60 * normalized_id := id - low_id
61 * reduced_rid := normalized_id % range_size
62 * range_number = normalized_id / range_size
66 * id = reduced_rid + low_id + range_number * range_size
68 * From the database, get the domain_sid,domain_range_index pair
69 * belonging to the range_number (if there is already one).
71 * Then the rid for the unix id calculates as:
73 * rid = reduced_rid + domain_range_index * range_size
77 #include "system/filesys.h"
79 #include "dbwrap/dbwrap.h"
80 #include "dbwrap/dbwrap_open.h"
83 #include "../libcli/security/dom_sid.h"
85 #include "winbindd/idmap_tdb_common.h"
88 #define DBGC_CLASS DBGC_IDMAP
90 #define HWM "NEXT RANGE"
91 #define ALLOC_HWM_UID "NEXT ALLOC UID"
92 #define ALLOC_HWM_GID "NEXT ALLOC GID"
93 #define ALLOC_RANGE "ALLOC"
94 #define CONFIGKEY "CONFIG"
96 struct autorid_global_config {
103 struct autorid_range_config {
107 uint32_t domain_range_index;
109 struct autorid_global_config *globalcfg;
112 /* handle to the tdb storing domain <-> range assignments */
113 static struct db_context *autorid_db;
115 static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
119 uint32_t rangenum, hwm;
121 struct autorid_range_config *range;
123 range = (struct autorid_range_config *)private_data;
125 ret = dbwrap_fetch_uint32_bystring(db, range->keystr,
128 if (NT_STATUS_IS_OK(ret)) {
129 /* entry is already present*/
133 DEBUG(10, ("Acquiring new range for domain %s "
134 "(domain_range_index=%"PRIu32")\n",
135 range->domsid, range->domain_range_index));
137 /* fetch the current HWM */
138 ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
139 if (!NT_STATUS_IS_OK(ret)) {
140 DEBUG(1, ("Fatal error while fetching current "
141 "HWM value: %s\n", nt_errstr(ret)));
142 ret = NT_STATUS_INTERNAL_ERROR;
146 /* do we have a range left? */
147 if (hwm >= range->globalcfg->maxranges) {
148 DEBUG(1, ("No more domain ranges available!\n"));
149 ret = NT_STATUS_NO_MEMORY;
153 /* increase the HWM */
154 ret = dbwrap_change_uint32_atomic_bystring(db, HWM, &rangenum, 1);
155 if (!NT_STATUS_IS_OK(ret)) {
156 DEBUG(1, ("Fatal error while fetching a new "
157 "domain range value!\n"));
161 /* store away the new mapping in both directions */
162 ret = dbwrap_store_uint32_bystring(db, range->keystr, rangenum);
163 if (!NT_STATUS_IS_OK(ret)) {
164 DEBUG(1, ("Fatal error while storing new "
165 "domain->range assignment!\n"));
169 numstr = talloc_asprintf(db, "%u", rangenum);
171 ret = NT_STATUS_NO_MEMORY;
175 ret = dbwrap_store_bystring(db, numstr,
176 string_term_tdb_data(range->keystr), TDB_INSERT);
179 if (!NT_STATUS_IS_OK(ret)) {
180 DEBUG(1, ("Fatal error while storing "
181 "new domain->range assignment!\n"));
184 DEBUG(5, ("Acquired new range #%d for domain %s "
185 "(domain_range_index=%"PRIu32")\n", rangenum, range->keystr,
186 range->domain_range_index));
188 range->rangenum = rangenum;
197 static NTSTATUS idmap_autorid_get_domainrange(struct db_context *db,
198 struct autorid_range_config *range,
204 * try to find mapping without locking the database,
205 * if it is not found create a mapping in a transaction unless
206 * read-only mode has been set
208 if (range->domain_range_index > 0) {
209 snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32,
210 range->domsid, range->domain_range_index);
212 fstrcpy(range->keystr, range->domsid);
215 ret = dbwrap_fetch_uint32_bystring(db, range->keystr,
218 if (!NT_STATUS_IS_OK(ret)) {
220 return NT_STATUS_NOT_FOUND;
222 ret = dbwrap_trans_do(db,
223 idmap_autorid_get_domainrange_action, range);
226 range->low_id = range->globalcfg->minvalue
227 + range->rangenum * range->globalcfg->rangesize;
229 DEBUG(10, ("Using range #%d for domain %s "
230 "(domain_range_index=%"PRIu32", low_id=%"PRIu32")\n",
231 range->rangenum, range->domsid, range->domain_range_index,
237 static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
238 struct unixid *xid) {
241 struct idmap_tdb_common_context *commoncfg;
242 struct autorid_global_config *globalcfg;
243 struct autorid_range_config range;
246 talloc_get_type_abort(dom->private_data,
247 struct idmap_tdb_common_context);
249 globalcfg = talloc_get_type(commoncfg->private_data,
250 struct autorid_global_config);
252 if (dom->read_only) {
253 DEBUG(3, ("Backend is read-only, refusing "
254 "new allocation request\n"));
255 return NT_STATUS_UNSUCCESSFUL;
258 /* fetch the range for the allocation pool */
262 range.globalcfg = globalcfg;
263 fstrcpy(range.domsid, ALLOC_RANGE);
265 ret = idmap_autorid_get_domainrange(autorid_db, &range, dom->read_only);
267 if (!NT_STATUS_IS_OK(ret)) {
268 DEBUG(3, ("Could not determine range for allocation pool, "
269 "check previous messages for reason\n"));
273 ret = idmap_tdb_common_get_new_id(dom, xid);
275 if (!NT_STATUS_IS_OK(ret)) {
276 DEBUG(1, ("Fatal error while allocating new ID!\n"));
280 xid->id = xid->id + range.low_id;
282 DEBUG(10, ("Returned new %s %d from allocation range\n",
283 (xid->type==ID_TYPE_UID)?"uid":"gid", xid->id));
289 * map a SID to xid using the idmap_tdb like pool
291 static NTSTATUS idmap_autorid_map_id_to_sid(struct idmap_domain *dom,
296 /* look out for the mapping */
297 ret = idmap_tdb_common_unixid_to_sid(dom, map);
299 if (NT_STATUS_IS_OK(ret)) {
300 map->status = ID_MAPPED;
304 map->status = ID_UNKNOWN;
306 DEBUG(10, ("no ID->SID mapping for %d could be found\n", map->xid.id));
311 static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
312 struct idmap_domain *dom,
315 uint32_t range_number;
316 uint32_t domain_range_index = 0;
317 uint32_t normalized_id;
318 uint32_t reduced_rid;
320 TDB_DATA data = tdb_null;
322 struct dom_sid domsid;
325 const char *q = NULL;
327 /* can this be one of our ids? */
328 if (map->xid.id < cfg->minvalue) {
329 DEBUG(10, ("id %d is lower than minimum value, "
330 "ignoring mapping request\n", map->xid.id));
331 map->status = ID_UNKNOWN;
335 if (map->xid.id > (cfg->minvalue + cfg->rangesize * cfg->maxranges)) {
336 DEBUG(10, ("id %d is outside of maximum id value, "
337 "ignoring mapping request\n", map->xid.id));
338 map->status = ID_UNKNOWN;
342 /* determine the range of this uid */
344 normalized_id = map->xid.id - cfg->minvalue;
345 range_number = normalized_id / cfg->rangesize;
347 keystr = talloc_asprintf(talloc_tos(), "%u", range_number);
349 return NT_STATUS_NO_MEMORY;
352 status = dbwrap_fetch_bystring(autorid_db, talloc_tos(), keystr, &data);
355 if (!NT_STATUS_IS_OK(status)) {
356 DEBUG(4, ("id %d belongs to range %d which does not have "
357 "domain mapping, ignoring mapping request\n",
358 map->xid.id, range_number));
359 TALLOC_FREE(data.dptr);
360 map->status = ID_UNKNOWN;
364 if (strncmp((const char *)data.dptr,
366 strlen(ALLOC_RANGE)) == 0) {
368 * this is from the alloc range, check if there is a mapping
370 DEBUG(5, ("id %d belongs to allocation range, "
371 "checking for mapping\n",
373 TALLOC_FREE(data.dptr);
374 return idmap_autorid_map_id_to_sid(dom, map);
377 ok = dom_sid_parse_endp((const char *)data.dptr, &domsid, &q);
378 TALLOC_FREE(data.dptr);
380 map->status = ID_UNKNOWN;
384 if (sscanf(q+1, "%"SCNu32, &domain_range_index) != 1) {
385 DEBUG(10, ("Domain range index not found, "
386 "ignoring mapping request\n"));
387 map->status = ID_UNKNOWN;
391 reduced_rid = normalized_id % cfg->rangesize;
392 rid = reduced_rid + domain_range_index * cfg->rangesize;
394 sid_compose(map->sid, &domsid, rid);
396 /* We **really** should have some way of validating
397 the SID exists and is the correct type here. But
398 that is a deficiency in the idmap_rid design. */
400 map->status = ID_MAPPED;
401 map->xid.type = ID_TYPE_BOTH;
406 /**********************************
407 Single sid to id lookup function.
408 **********************************/
410 static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
411 struct autorid_range_config *range,
415 uint32_t reduced_rid;
417 sid_peek_rid(map->sid, &rid);
419 reduced_rid = rid % global->rangesize;
421 map->xid.id = reduced_rid + range->low_id;
422 map->xid.type = ID_TYPE_BOTH;
424 /* We **really** should have some way of validating
425 the SID exists and is the correct type here. But
426 that is a deficiency in the idmap_rid design. */
428 map->status = ID_MAPPED;
433 /**********************************
434 lookup a set of unix ids.
435 **********************************/
437 static NTSTATUS idmap_autorid_unixids_to_sids(struct idmap_domain *dom,
440 struct idmap_tdb_common_context *commoncfg;
441 struct autorid_global_config *globalcfg;
447 /* initialize the status to avoid surprise */
448 for (i = 0; ids[i]; i++) {
449 ids[i]->status = ID_UNKNOWN;
454 talloc_get_type_abort(dom->private_data,
455 struct idmap_tdb_common_context);
457 globalcfg = talloc_get_type(commoncfg->private_data,
458 struct autorid_global_config);
460 for (i = 0; ids[i]; i++) {
462 ret = idmap_autorid_id_to_sid(globalcfg, dom, ids[i]);
464 if ((!NT_STATUS_IS_OK(ret)) &&
465 (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
466 /* some fatal error occurred, log it */
467 DEBUG(3, ("Unexpected error resolving an ID "
468 " (%d)\n", ids[i]->xid.id));
472 if (NT_STATUS_IS_OK(ret) && ids[i]->status == ID_MAPPED) {
478 if (num_tomap == num_mapped) {
480 } else if (num_mapped == 0) {
481 return NT_STATUS_NONE_MAPPED;
484 return STATUS_SOME_UNMAPPED;
492 * map a SID to xid using the idmap_tdb like pool
494 static NTSTATUS idmap_autorid_map_sid_to_id(struct idmap_domain *dom,
496 struct idmap_tdb_common_context *ctx)
501 /* see if we already have a mapping */
502 ret = idmap_tdb_common_sid_to_unixid(dom, map);
504 if (NT_STATUS_IS_OK(ret)) {
505 map->status = ID_MAPPED;
509 /* bad things happened */
510 if (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
511 DEBUG(1, ("Looking up SID->ID mapping for %s failed\n",
512 sid_string_dbg(map->sid)));
516 if (dom->read_only) {
517 DEBUG(3, ("Not allocating new mapping for %s, because backend "
518 "is read-only\n", sid_string_dbg(map->sid)));
519 return NT_STATUS_NONE_MAPPED;
522 DEBUG(10, ("Creating new mapping in pool for %s\n",
523 sid_string_dbg(map->sid)));
525 /* create new mapping */
526 res = dbwrap_transaction_start(ctx->db);
528 DEBUG(2, ("transaction_start failed\n"));
529 return NT_STATUS_INTERNAL_DB_CORRUPTION;
532 ret = idmap_tdb_common_new_mapping(dom, map);
534 map->status = (NT_STATUS_IS_OK(ret))?ID_MAPPED:ID_UNMAPPED;
536 if (!NT_STATUS_IS_OK(ret)) {
537 if (dbwrap_transaction_cancel(ctx->db) != 0) {
538 smb_panic("Cancelling transaction failed");
543 res = dbwrap_transaction_commit(ctx->db);
548 DEBUG(2, ("transaction_commit failed\n"));
549 return NT_STATUS_INTERNAL_DB_CORRUPTION;
553 /**********************************
554 lookup a set of sids.
555 **********************************/
557 static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
560 struct idmap_tdb_common_context *commoncfg;
561 struct autorid_global_config *global;
567 /* initialize the status to avoid surprise */
568 for (i = 0; ids[i]; i++) {
569 ids[i]->status = ID_UNKNOWN;
574 talloc_get_type_abort(dom->private_data,
575 struct idmap_tdb_common_context);
577 global = talloc_get_type(commoncfg->private_data,
578 struct autorid_global_config);
580 for (i = 0; ids[i]; i++) {
581 struct winbindd_tdc_domain *domain;
582 struct autorid_range_config range;
584 struct dom_sid domainsid;
588 DEBUG(10, ("Trying to map %s\n", sid_string_dbg(ids[i]->sid)));
590 sid_copy(&domainsid, ids[i]->sid);
591 if (!sid_split_rid(&domainsid, &rid)) {
592 DEBUG(4, ("Could not determine domain SID from %s, "
593 "ignoring mapping request\n",
594 sid_string_dbg(ids[i]->sid)));
598 /* is this a well-known SID? */
600 if (sid_check_is_wellknown_domain(&domainsid, NULL)) {
602 DEBUG(10, ("SID %s is well-known, using pool\n",
603 sid_string_dbg(ids[i]->sid)));
605 ret = idmap_autorid_map_sid_to_id(dom, ids[i],
608 if (!NT_STATUS_IS_OK(ret) &&
609 !NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
610 DEBUG(3, ("Unexpected error resolving "
612 sid_string_dbg(ids[i]->sid)));
616 if (ids[i]->status == ID_MAPPED) {
623 /* BUILTIN is passdb's job */
624 if (dom_sid_equal(&domainsid, &global_sid_Builtin) &&
625 global->ignore_builtin) {
626 DEBUG(10, ("Ignoring request for BUILTIN domain\n"));
631 * Check if the domain is around
633 domain = wcache_tdc_fetch_domainbysid(talloc_tos(),
635 if (domain == NULL) {
636 DEBUG(10, ("Ignoring unknown domain sid %s\n",
637 sid_string_dbg(&domainsid)));
642 range.globalcfg = global;
643 sid_to_fstring(range.domsid, &domainsid);
645 /* Calculate domain_range_index for multi-range support */
646 range.domain_range_index = rid / (global->rangesize);
648 ret = idmap_autorid_get_domainrange(autorid_db, &range,
651 /* read-only mode and a new domain range would be required? */
652 if (NT_STATUS_EQUAL(ret, NT_STATUS_NOT_FOUND) &&
654 DEBUG(10, ("read-only is enabled, did not allocate "
655 "new range for domain %s\n",
656 sid_string_dbg(&domainsid)));
660 if (!NT_STATUS_IS_OK(ret)) {
661 DEBUG(3, ("Could not determine range for domain, "
662 "check previous messages for reason\n"));
666 ret = idmap_autorid_sid_to_id(global, &range, ids[i]);
668 if ((!NT_STATUS_IS_OK(ret)) &&
669 (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
670 /* some fatal error occurred, log it */
671 DEBUG(3, ("Unexpected error resolving a SID (%s)\n",
672 sid_string_dbg(ids[i]->sid)));
676 if (NT_STATUS_IS_OK(ret)) {
681 if (num_tomap == num_mapped) {
683 } else if (num_mapped == 0) {
684 return NT_STATUS_NONE_MAPPED;
687 return STATUS_SOME_UNMAPPED;
694 /* initialize the given HWM to 0 if it does not exist yet */
695 static NTSTATUS idmap_autorid_init_hwm(struct db_context *db, const char *hwm)
700 status = dbwrap_fetch_uint32_bystring(db, hwm, &hwmval);
701 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
702 status = dbwrap_trans_store_int32_bystring(db, hwm, 0);
703 if (!NT_STATUS_IS_OK(status)) {
705 ("Unable to initialise HWM (%s) in autorid "
706 "database: %s\n", hwm, nt_errstr(status)));
707 return NT_STATUS_INTERNAL_DB_ERROR;
709 } else if (!NT_STATUS_IS_OK(status)) {
710 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
711 "database: %s\n", hwm, nt_errstr(status)));
719 * open and initialize the database which stores the ranges for the domains
721 static NTSTATUS idmap_autorid_db_init(void)
726 /* its already open */
730 /* Open idmap repository */
731 autorid_db = db_open(NULL, state_path("autorid.tdb"), 0,
732 TDB_DEFAULT, O_RDWR | O_CREAT, 0644,
733 DBWRAP_LOCK_ORDER_1);
736 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n",
737 state_path("autorid.tdb")));
738 return NT_STATUS_UNSUCCESSFUL;
741 /* Initialize high water mark for the currently used range to 0 */
743 status = idmap_autorid_init_hwm(autorid_db, HWM);
744 NT_STATUS_NOT_OK_RETURN(status);
746 status = idmap_autorid_init_hwm(autorid_db, ALLOC_HWM_UID);
747 NT_STATUS_NOT_OK_RETURN(status);
749 status = idmap_autorid_init_hwm(autorid_db, ALLOC_HWM_GID);
754 static struct autorid_global_config *idmap_autorid_loadconfig(struct db_context *db,
759 struct autorid_global_config *cfg;
760 unsigned long minvalue, rangesize, maxranges;
763 status = dbwrap_fetch_bystring(db, ctx, CONFIGKEY, &data);
765 if (!NT_STATUS_IS_OK(status)) {
766 DEBUG(10, ("No saved config found\n"));
770 cfg = talloc_zero(ctx, struct autorid_global_config);
775 if (sscanf((char *)data.dptr,
776 "minvalue:%lu rangesize:%lu maxranges:%lu",
777 &minvalue, &rangesize, &maxranges) != 3) {
779 ("Found invalid configuration data"
780 "creating new config\n"));
784 cfg->minvalue = minvalue;
785 cfg->rangesize = rangesize;
786 cfg->maxranges = maxranges;
788 DEBUG(10, ("Loaded previously stored configuration "
789 "minvalue:%d rangesize:%d\n",
790 cfg->minvalue, cfg->rangesize));
796 static NTSTATUS idmap_autorid_saveconfig(struct db_context *db,
797 struct autorid_global_config *cfg)
805 talloc_asprintf(talloc_tos(),
806 "minvalue:%u rangesize:%u maxranges:%u",
807 cfg->minvalue, cfg->rangesize, cfg->maxranges);
810 return NT_STATUS_NO_MEMORY;
813 data = string_tdb_data(cfgstr);
815 status = dbwrap_trans_store_bystring(db, CONFIGKEY, data, TDB_REPLACE);
822 static NTSTATUS idmap_autorid_preallocate_wellknown(struct idmap_domain *dom)
824 const char *groups[] = { "S-1-1-0", "S-1-2-0", "S-1-2-1",
825 "S-1-3-0", "S-1-3-1", "S-1-3-2", "S-1-3-3", "S-1-3-4",
826 "S-1-5-1", "S-1-5-2", "S-1-5-3", "S-1-5-4", "S-1-5-6",
827 "S-1-5-7", "S-1-5-8", "S-1-5-9", "S-1-5-10", "S-1-5-11",
828 "S-1-5-12", "S-1-5-13", "S-1-5-14", "S-1-5-15",
829 "S-1-5-17", "S-1-5-18", "S-1-5-19", "S-1-5-20"
832 struct id_map **maps;
836 if (dom->read_only) {
840 num = ARRAY_SIZE(groups);
842 maps = talloc_array(talloc_tos(), struct id_map*, num+1);
844 return NT_STATUS_NO_MEMORY;
847 for (i = 0; i < num; i++) {
848 maps[i] = talloc(maps, struct id_map);
849 if (maps[i] == NULL) {
851 return NT_STATUS_NO_MEMORY;
853 maps[i]->xid.type = ID_TYPE_GID;
854 maps[i]->sid = dom_sid_parse_talloc(maps, groups[i]);
859 status = idmap_autorid_sids_to_unixids(dom, maps);
861 DEBUG(10,("Preallocation run finished with status %s\n",
866 return NT_STATUS_IS_OK(status)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
869 static NTSTATUS idmap_autorid_initialize(struct idmap_domain *dom)
871 struct idmap_tdb_common_context *commonconfig;
872 struct autorid_global_config *config;
873 struct autorid_global_config *storedconfig = NULL;
877 if (!strequal(dom->name, "*")) {
878 DEBUG(0, ("idmap_autorid_initialize: Error: autorid configured "
879 "for domain '%s'. But autorid can only be used for "
880 "the default idmap configuration.\n", dom->name));
881 return NT_STATUS_INVALID_PARAMETER;
884 commonconfig = talloc_zero(dom, struct idmap_tdb_common_context);
886 DEBUG(0, ("Out of memory!\n"));
887 return NT_STATUS_NO_MEMORY;
890 commonconfig->rw_ops = talloc_zero(commonconfig, struct idmap_rw_ops);
891 if (commonconfig->rw_ops == NULL) {
892 DEBUG(0, ("Out of memory!\n"));
893 return NT_STATUS_NO_MEMORY;
896 config = talloc_zero(commonconfig, struct autorid_global_config);
898 DEBUG(0, ("Out of memory!\n"));
899 return NT_STATUS_NO_MEMORY;
902 status = idmap_autorid_db_init();
903 if (!NT_STATUS_IS_OK(status)) {
907 config->minvalue = dom->low_id;
908 config->rangesize = lp_parm_int(-1, "idmap config *",
909 "rangesize", 100000);
911 if (config->rangesize < 2000) {
912 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
913 status = NT_STATUS_INVALID_PARAMETER;
917 config->maxranges = (dom->high_id - dom->low_id + 1) /
920 if (config->maxranges == 0) {
921 DEBUG(1, ("allowed uid range is smaller then rangesize, "
922 "increase uid range or decrease rangesize\n"));
923 status = NT_STATUS_INVALID_PARAMETER;
927 /* check if the high-low limit is a multiple of the rangesize */
928 if ((dom->high_id - dom->low_id + 1) % config->rangesize != 0) {
929 DEBUG(5, ("High uid-low uid difference of %d "
930 "is not a multiple of the rangesize %d, "
931 "limiting ranges to lower boundary number of %d\n",
932 (dom->high_id - dom->low_id + 1), config->rangesize,
936 DEBUG(10, ("Current configuration in config is "
937 "minvalue:%d rangesize:%d maxranges:%d\n",
938 config->minvalue, config->rangesize, config->maxranges));
940 /* read previously stored config and current HWM */
941 storedconfig = idmap_autorid_loadconfig(autorid_db, talloc_tos());
943 status = dbwrap_fetch_uint32_bystring(autorid_db, HWM, &hwm);
944 if (!NT_STATUS_IS_OK(status)) {
945 DEBUG(1, ("Fatal error while fetching current "
946 "HWM value: %s\n", nt_errstr(status)));
947 status = NT_STATUS_INTERNAL_ERROR;
951 /* did the minimum value or rangesize change? */
953 ((storedconfig->minvalue != config->minvalue) ||
954 (storedconfig->rangesize != config->rangesize))) {
955 DEBUG(1, ("New configuration values for rangesize or "
956 "minimum uid value conflict with previously "
957 "used values! Aborting initialization\n"));
958 status = NT_STATUS_INVALID_PARAMETER;
963 * has the highest uid value been reduced to setting that is not
964 * sufficient any more for already existing ranges?
966 if (hwm > config->maxranges) {
967 DEBUG(1, ("New upper uid limit is too low to cover "
968 "existing mappings! Aborting initialization\n"));
969 status = NT_STATUS_INVALID_PARAMETER;
973 status = idmap_autorid_saveconfig(autorid_db, config);
975 if (!NT_STATUS_IS_OK(status)) {
976 DEBUG(1, ("Failed to store configuration data!\n"));
980 DEBUG(5, ("%d domain ranges with a size of %d are available\n",
981 config->maxranges, config->rangesize));
983 config->ignore_builtin = lp_parm_bool(-1, "idmap config *",
984 "ignore builtin", false);
986 /* fill the TDB common configuration */
987 commonconfig->private_data = config;
989 commonconfig->db = autorid_db;
990 commonconfig->max_id = config->rangesize -1;
991 commonconfig->hwmkey_uid = ALLOC_HWM_UID;
992 commonconfig->hwmkey_gid = ALLOC_HWM_GID;
993 commonconfig->rw_ops->get_new_id = idmap_autorid_allocate_id;
994 commonconfig->rw_ops->set_mapping = idmap_tdb_common_set_mapping;
996 dom->private_data = commonconfig;
998 /* preallocate well-known SIDs in the pool */
999 status = idmap_autorid_preallocate_wellknown(dom);
1004 talloc_free(config);
1007 talloc_free(storedconfig);
1013 Close the idmap tdb instance
1015 static struct idmap_methods autorid_methods = {
1016 .init = idmap_autorid_initialize,
1017 .unixids_to_sids = idmap_autorid_unixids_to_sids,
1018 .sids_to_unixids = idmap_autorid_sids_to_unixids,
1019 .allocate_id = idmap_autorid_allocate_id
1022 NTSTATUS samba_init_module(void)
1024 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
1025 "autorid", &autorid_methods);