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 {
102 struct autorid_range_config {
106 uint32_t domain_range_index;
108 struct autorid_global_config *globalcfg;
111 /* handle to the tdb storing domain <-> range assignments */
112 static struct db_context *autorid_db;
114 static bool ignore_builtin = false;
116 static NTSTATUS idmap_autorid_get_domainrange_action(struct db_context *db,
120 uint32_t rangenum, hwm;
122 struct autorid_range_config *range;
124 range = (struct autorid_range_config *)private_data;
126 ret = dbwrap_fetch_uint32_bystring(db, range->keystr,
129 if (NT_STATUS_IS_OK(ret)) {
130 /* entry is already present*/
134 DEBUG(10, ("Acquiring new range for domain %s "
135 "(domain_range_index=%"PRIu32")\n",
136 range->domsid, range->domain_range_index));
138 /* fetch the current HWM */
139 ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
140 if (!NT_STATUS_IS_OK(ret)) {
141 DEBUG(1, ("Fatal error while fetching current "
142 "HWM value: %s\n", nt_errstr(ret)));
143 ret = NT_STATUS_INTERNAL_ERROR;
147 /* do we have a range left? */
148 if (hwm >= range->globalcfg->maxranges) {
149 DEBUG(1, ("No more domain ranges available!\n"));
150 ret = NT_STATUS_NO_MEMORY;
154 /* increase the HWM */
155 ret = dbwrap_change_uint32_atomic_bystring(db, HWM, &rangenum, 1);
156 if (!NT_STATUS_IS_OK(ret)) {
157 DEBUG(1, ("Fatal error while fetching a new "
158 "domain range value!\n"));
162 /* store away the new mapping in both directions */
163 ret = dbwrap_store_uint32_bystring(db, range->keystr, rangenum);
164 if (!NT_STATUS_IS_OK(ret)) {
165 DEBUG(1, ("Fatal error while storing new "
166 "domain->range assignment!\n"));
170 numstr = talloc_asprintf(db, "%u", rangenum);
172 ret = NT_STATUS_NO_MEMORY;
176 ret = dbwrap_store_bystring(db, numstr,
177 string_term_tdb_data(range->keystr), TDB_INSERT);
180 if (!NT_STATUS_IS_OK(ret)) {
181 DEBUG(1, ("Fatal error while storing "
182 "new domain->range assignment!\n"));
185 DEBUG(5, ("Acquired new range #%d for domain %s "
186 "(domain_range_index=%"PRIu32")\n", rangenum, range->keystr,
187 range->domain_range_index));
189 range->rangenum = rangenum;
198 static NTSTATUS idmap_autorid_get_domainrange(struct db_context *db,
199 struct autorid_range_config *range,
205 * try to find mapping without locking the database,
206 * if it is not found create a mapping in a transaction unless
207 * read-only mode has been set
209 if (range->domain_range_index > 0) {
210 snprintf(range->keystr, FSTRING_LEN, "%s#%"PRIu32,
211 range->domsid, range->domain_range_index);
213 fstrcpy(range->keystr, range->domsid);
216 ret = dbwrap_fetch_uint32_bystring(db, range->keystr,
219 if (!NT_STATUS_IS_OK(ret)) {
221 return NT_STATUS_NOT_FOUND;
223 ret = dbwrap_trans_do(db,
224 idmap_autorid_get_domainrange_action, range);
227 range->low_id = range->globalcfg->minvalue
228 + range->rangenum * range->globalcfg->rangesize;
230 DEBUG(10, ("Using range #%d for domain %s "
231 "(domain_range_index=%"PRIu32", low_id=%"PRIu32")\n",
232 range->rangenum, range->domsid, range->domain_range_index,
238 static NTSTATUS idmap_autorid_allocate_id(struct idmap_domain *dom,
239 struct unixid *xid) {
242 struct idmap_tdb_common_context *commoncfg;
243 struct autorid_global_config *globalcfg;
244 struct autorid_range_config range;
247 talloc_get_type_abort(dom->private_data,
248 struct idmap_tdb_common_context);
250 globalcfg = talloc_get_type(commoncfg->private_data,
251 struct autorid_global_config);
253 if (dom->read_only) {
254 DEBUG(3, ("Backend is read-only, refusing "
255 "new allocation request\n"));
256 return NT_STATUS_UNSUCCESSFUL;
259 /* fetch the range for the allocation pool */
263 range.globalcfg = globalcfg;
264 fstrcpy(range.domsid, ALLOC_RANGE);
266 ret = idmap_autorid_get_domainrange(autorid_db, &range, dom->read_only);
268 if (!NT_STATUS_IS_OK(ret)) {
269 DEBUG(3, ("Could not determine range for allocation pool, "
270 "check previous messages for reason\n"));
274 ret = idmap_tdb_common_get_new_id(dom, xid);
276 if (!NT_STATUS_IS_OK(ret)) {
277 DEBUG(1, ("Fatal error while allocating new ID!\n"));
281 xid->id = xid->id + range.low_id;
283 DEBUG(10, ("Returned new %s %d from allocation range\n",
284 (xid->type==ID_TYPE_UID)?"uid":"gid", xid->id));
290 * map a SID to xid using the idmap_tdb like pool
292 static NTSTATUS idmap_autorid_map_id_to_sid(struct idmap_domain *dom,
297 /* look out for the mapping */
298 ret = idmap_tdb_common_unixid_to_sid(dom, map);
300 if (NT_STATUS_IS_OK(ret)) {
301 map->status = ID_MAPPED;
305 map->status = ID_UNKNOWN;
307 DEBUG(10, ("no ID->SID mapping for %d could be found\n", map->xid.id));
312 static NTSTATUS idmap_autorid_id_to_sid(struct autorid_global_config *cfg,
313 struct idmap_domain *dom,
316 uint32_t range_number;
317 uint32_t domain_range_index = 0;
318 uint32_t normalized_id;
319 uint32_t reduced_rid;
321 TDB_DATA data = tdb_null;
323 struct dom_sid domsid;
326 const char *q = NULL;
328 /* can this be one of our ids? */
329 if (map->xid.id < cfg->minvalue) {
330 DEBUG(10, ("id %d is lower than minimum value, "
331 "ignoring mapping request\n", map->xid.id));
332 map->status = ID_UNKNOWN;
336 if (map->xid.id > (cfg->minvalue + cfg->rangesize * cfg->maxranges)) {
337 DEBUG(10, ("id %d is outside of maximum id value, "
338 "ignoring mapping request\n", map->xid.id));
339 map->status = ID_UNKNOWN;
343 /* determine the range of this uid */
345 normalized_id = map->xid.id - cfg->minvalue;
346 range_number = normalized_id / cfg->rangesize;
348 keystr = talloc_asprintf(talloc_tos(), "%u", range_number);
350 return NT_STATUS_NO_MEMORY;
353 status = dbwrap_fetch_bystring(autorid_db, talloc_tos(), keystr, &data);
356 if (!NT_STATUS_IS_OK(status)) {
357 DEBUG(4, ("id %d belongs to range %d which does not have "
358 "domain mapping, ignoring mapping request\n",
359 map->xid.id, range_number));
360 TALLOC_FREE(data.dptr);
361 map->status = ID_UNKNOWN;
365 if (strncmp((const char *)data.dptr,
367 strlen(ALLOC_RANGE)) == 0) {
369 * this is from the alloc range, check if there is a mapping
371 DEBUG(5, ("id %d belongs to allocation range, "
372 "checking for mapping\n",
374 TALLOC_FREE(data.dptr);
375 return idmap_autorid_map_id_to_sid(dom, map);
378 ok = dom_sid_parse_endp((const char *)data.dptr, &domsid, &q);
379 TALLOC_FREE(data.dptr);
381 map->status = ID_UNKNOWN;
385 if (sscanf(q+1, "%"SCNu32, &domain_range_index) != 1) {
386 DEBUG(10, ("Domain range index not found, "
387 "ignoring mapping request\n"));
388 map->status = ID_UNKNOWN;
392 reduced_rid = normalized_id % cfg->rangesize;
393 rid = reduced_rid + domain_range_index * cfg->rangesize;
395 sid_compose(map->sid, &domsid, rid);
397 /* We **really** should have some way of validating
398 the SID exists and is the correct type here. But
399 that is a deficiency in the idmap_rid design. */
401 map->status = ID_MAPPED;
402 map->xid.type = ID_TYPE_BOTH;
407 /**********************************
408 Single sid to id lookup function.
409 **********************************/
411 static NTSTATUS idmap_autorid_sid_to_id(struct autorid_global_config *global,
412 struct autorid_range_config *range,
416 uint32_t reduced_rid;
418 sid_peek_rid(map->sid, &rid);
420 reduced_rid = rid % global->rangesize;
422 map->xid.id = reduced_rid + range->low_id;
423 map->xid.type = ID_TYPE_BOTH;
425 /* We **really** should have some way of validating
426 the SID exists and is the correct type here. But
427 that is a deficiency in the idmap_rid design. */
429 map->status = ID_MAPPED;
434 /**********************************
435 lookup a set of unix ids.
436 **********************************/
438 static NTSTATUS idmap_autorid_unixids_to_sids(struct idmap_domain *dom,
441 struct idmap_tdb_common_context *commoncfg;
442 struct autorid_global_config *globalcfg;
448 /* initialize the status to avoid surprise */
449 for (i = 0; ids[i]; i++) {
450 ids[i]->status = ID_UNKNOWN;
455 talloc_get_type_abort(dom->private_data,
456 struct idmap_tdb_common_context);
458 globalcfg = talloc_get_type(commoncfg->private_data,
459 struct autorid_global_config);
461 for (i = 0; ids[i]; i++) {
463 ret = idmap_autorid_id_to_sid(globalcfg, dom, ids[i]);
465 if ((!NT_STATUS_IS_OK(ret)) &&
466 (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
467 /* some fatal error occurred, log it */
468 DEBUG(3, ("Unexpected error resolving an ID "
469 " (%d)\n", ids[i]->xid.id));
473 if (NT_STATUS_IS_OK(ret) && ids[i]->status == ID_MAPPED) {
479 if (num_tomap == num_mapped) {
481 } else if (num_mapped == 0) {
482 return NT_STATUS_NONE_MAPPED;
485 return STATUS_SOME_UNMAPPED;
493 * map a SID to xid using the idmap_tdb like pool
495 static NTSTATUS idmap_autorid_map_sid_to_id(struct idmap_domain *dom,
497 struct idmap_tdb_common_context *ctx)
502 /* see if we already have a mapping */
503 ret = idmap_tdb_common_sid_to_unixid(dom, map);
505 if (NT_STATUS_IS_OK(ret)) {
506 map->status = ID_MAPPED;
510 /* bad things happened */
511 if (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
512 DEBUG(1, ("Looking up SID->ID mapping for %s failed\n",
513 sid_string_dbg(map->sid)));
517 if (dom->read_only) {
518 DEBUG(3, ("Not allocating new mapping for %s, because backend "
519 "is read-only\n", sid_string_dbg(map->sid)));
520 return NT_STATUS_NONE_MAPPED;
523 DEBUG(10, ("Creating new mapping in pool for %s\n",
524 sid_string_dbg(map->sid)));
526 /* create new mapping */
527 res = dbwrap_transaction_start(ctx->db);
529 DEBUG(2, ("transaction_start failed\n"));
530 return NT_STATUS_INTERNAL_DB_CORRUPTION;
533 ret = idmap_tdb_common_new_mapping(dom, map);
535 map->status = (NT_STATUS_IS_OK(ret))?ID_MAPPED:ID_UNMAPPED;
537 if (!NT_STATUS_IS_OK(ret)) {
538 if (dbwrap_transaction_cancel(ctx->db) != 0) {
539 smb_panic("Cancelling transaction failed");
544 res = dbwrap_transaction_commit(ctx->db);
549 DEBUG(2, ("transaction_commit failed\n"));
550 return NT_STATUS_INTERNAL_DB_CORRUPTION;
554 /**********************************
555 lookup a set of sids.
556 **********************************/
558 static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom,
561 struct idmap_tdb_common_context *commoncfg;
562 struct autorid_global_config *global;
568 /* initialize the status to avoid surprise */
569 for (i = 0; ids[i]; i++) {
570 ids[i]->status = ID_UNKNOWN;
575 talloc_get_type_abort(dom->private_data,
576 struct idmap_tdb_common_context);
578 global = talloc_get_type(commoncfg->private_data,
579 struct autorid_global_config);
581 for (i = 0; ids[i]; i++) {
582 struct winbindd_tdc_domain *domain;
583 struct autorid_range_config range;
585 struct dom_sid domainsid;
589 DEBUG(10, ("Trying to map %s\n", sid_string_dbg(ids[i]->sid)));
591 sid_copy(&domainsid, ids[i]->sid);
592 if (!sid_split_rid(&domainsid, &rid)) {
593 DEBUG(4, ("Could not determine domain SID from %s, "
594 "ignoring mapping request\n",
595 sid_string_dbg(ids[i]->sid)));
599 /* is this a well-known SID? */
601 if (sid_check_is_wellknown_domain(&domainsid, NULL)) {
603 DEBUG(10, ("SID %s is well-known, using pool\n",
604 sid_string_dbg(ids[i]->sid)));
606 ret = idmap_autorid_map_sid_to_id(dom, ids[i],
609 if (!NT_STATUS_IS_OK(ret) &&
610 !NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
611 DEBUG(3, ("Unexpected error resolving "
613 sid_string_dbg(ids[i]->sid)));
617 if (ids[i]->status == ID_MAPPED) {
624 /* BUILTIN is passdb's job */
625 if (dom_sid_equal(&domainsid, &global_sid_Builtin) &&
627 DEBUG(10, ("Ignoring request for BUILTIN domain\n"));
632 * Check if the domain is around
634 domain = wcache_tdc_fetch_domainbysid(talloc_tos(),
636 if (domain == NULL) {
637 DEBUG(10, ("Ignoring unknown domain sid %s\n",
638 sid_string_dbg(&domainsid)));
643 range.globalcfg = global;
644 sid_to_fstring(range.domsid, &domainsid);
646 /* Calculate domain_range_index for multi-range support */
647 range.domain_range_index = rid / (global->rangesize);
649 ret = idmap_autorid_get_domainrange(autorid_db, &range,
652 /* read-only mode and a new domain range would be required? */
653 if (NT_STATUS_EQUAL(ret, NT_STATUS_NOT_FOUND) &&
655 DEBUG(10, ("read-only is enabled, did not allocate "
656 "new range for domain %s\n",
657 sid_string_dbg(&domainsid)));
661 if (!NT_STATUS_IS_OK(ret)) {
662 DEBUG(3, ("Could not determine range for domain, "
663 "check previous messages for reason\n"));
667 ret = idmap_autorid_sid_to_id(global, &range, ids[i]);
669 if ((!NT_STATUS_IS_OK(ret)) &&
670 (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) {
671 /* some fatal error occurred, log it */
672 DEBUG(3, ("Unexpected error resolving a SID (%s)\n",
673 sid_string_dbg(ids[i]->sid)));
677 if (NT_STATUS_IS_OK(ret)) {
682 if (num_tomap == num_mapped) {
684 } else if (num_mapped == 0) {
685 return NT_STATUS_NONE_MAPPED;
688 return STATUS_SOME_UNMAPPED;
695 /* initialize the given HWM to 0 if it does not exist yet */
696 static NTSTATUS idmap_autorid_init_hwm(struct db_context *db, const char *hwm)
701 status = dbwrap_fetch_uint32_bystring(db, hwm, &hwmval);
702 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
703 status = dbwrap_trans_store_int32_bystring(db, hwm, 0);
704 if (!NT_STATUS_IS_OK(status)) {
706 ("Unable to initialise HWM (%s) in autorid "
707 "database: %s\n", hwm, nt_errstr(status)));
708 return NT_STATUS_INTERNAL_DB_ERROR;
710 } else if (!NT_STATUS_IS_OK(status)) {
711 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
712 "database: %s\n", hwm, nt_errstr(status)));
720 * open and initialize the database which stores the ranges for the domains
722 static NTSTATUS idmap_autorid_db_init(const char *path,
724 struct db_context **db)
729 /* its already open */
733 /* Open idmap repository */
734 *db = db_open(mem_ctx, path, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644,
735 DBWRAP_LOCK_ORDER_1);
738 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path));
739 return NT_STATUS_UNSUCCESSFUL;
742 /* Initialize high water mark for the currently used range to 0 */
744 status = idmap_autorid_init_hwm(*db, HWM);
745 NT_STATUS_NOT_OK_RETURN(status);
747 status = idmap_autorid_init_hwm(*db, ALLOC_HWM_UID);
748 NT_STATUS_NOT_OK_RETURN(status);
750 status = idmap_autorid_init_hwm(*db, ALLOC_HWM_GID);
755 static struct autorid_global_config *idmap_autorid_loadconfig(struct db_context *db,
760 struct autorid_global_config *cfg;
761 unsigned long minvalue, rangesize, maxranges;
764 status = dbwrap_fetch_bystring(db, ctx, CONFIGKEY, &data);
766 if (!NT_STATUS_IS_OK(status)) {
767 DEBUG(10, ("No saved config found\n"));
771 cfg = talloc_zero(ctx, struct autorid_global_config);
776 if (sscanf((char *)data.dptr,
777 "minvalue:%lu rangesize:%lu maxranges:%lu",
778 &minvalue, &rangesize, &maxranges) != 3) {
780 ("Found invalid configuration data"
781 "creating new config\n"));
785 cfg->minvalue = minvalue;
786 cfg->rangesize = rangesize;
787 cfg->maxranges = maxranges;
789 DEBUG(10, ("Loaded previously stored configuration "
790 "minvalue:%d rangesize:%d\n",
791 cfg->minvalue, cfg->rangesize));
797 static NTSTATUS idmap_autorid_saveconfig(struct db_context *db,
798 struct autorid_global_config *cfg)
806 talloc_asprintf(talloc_tos(),
807 "minvalue:%u rangesize:%u maxranges:%u",
808 cfg->minvalue, cfg->rangesize, cfg->maxranges);
811 return NT_STATUS_NO_MEMORY;
814 data = string_tdb_data(cfgstr);
816 status = dbwrap_trans_store_bystring(db, CONFIGKEY, data, TDB_REPLACE);
823 static NTSTATUS idmap_autorid_preallocate_wellknown(struct idmap_domain *dom)
825 const char *groups[] = { "S-1-1-0", "S-1-2-0", "S-1-2-1",
826 "S-1-3-0", "S-1-3-1", "S-1-3-2", "S-1-3-3", "S-1-3-4",
827 "S-1-5-1", "S-1-5-2", "S-1-5-3", "S-1-5-4", "S-1-5-6",
828 "S-1-5-7", "S-1-5-8", "S-1-5-9", "S-1-5-10", "S-1-5-11",
829 "S-1-5-12", "S-1-5-13", "S-1-5-14", "S-1-5-15",
830 "S-1-5-17", "S-1-5-18", "S-1-5-19", "S-1-5-20"
833 struct id_map **maps;
837 if (dom->read_only) {
841 num = ARRAY_SIZE(groups);
843 maps = talloc_array(talloc_tos(), struct id_map*, num+1);
845 return NT_STATUS_NO_MEMORY;
848 for (i = 0; i < num; i++) {
849 maps[i] = talloc(maps, struct id_map);
850 if (maps[i] == NULL) {
852 return NT_STATUS_NO_MEMORY;
854 maps[i]->xid.type = ID_TYPE_GID;
855 maps[i]->sid = dom_sid_parse_talloc(maps, groups[i]);
860 status = idmap_autorid_sids_to_unixids(dom, maps);
862 DEBUG(10,("Preallocation run finished with status %s\n",
867 return NT_STATUS_IS_OK(status)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
870 static NTSTATUS idmap_autorid_initialize(struct idmap_domain *dom)
872 struct idmap_tdb_common_context *commonconfig;
873 struct autorid_global_config *config;
874 struct autorid_global_config *storedconfig = NULL;
878 if (!strequal(dom->name, "*")) {
879 DEBUG(0, ("idmap_autorid_initialize: Error: autorid configured "
880 "for domain '%s'. But autorid can only be used for "
881 "the default idmap configuration.\n", dom->name));
882 return NT_STATUS_INVALID_PARAMETER;
885 commonconfig = talloc_zero(dom, struct idmap_tdb_common_context);
887 DEBUG(0, ("Out of memory!\n"));
888 return NT_STATUS_NO_MEMORY;
891 commonconfig->rw_ops = talloc_zero(commonconfig, struct idmap_rw_ops);
892 if (commonconfig->rw_ops == NULL) {
893 DEBUG(0, ("Out of memory!\n"));
894 return NT_STATUS_NO_MEMORY;
897 config = talloc_zero(commonconfig, struct autorid_global_config);
899 DEBUG(0, ("Out of memory!\n"));
900 return NT_STATUS_NO_MEMORY;
903 status = idmap_autorid_db_init(state_path("autorid.tdb"),
904 NULL, /* TALLOC_CTX */
906 if (!NT_STATUS_IS_OK(status)) {
910 config->minvalue = dom->low_id;
911 config->rangesize = lp_parm_int(-1, "idmap config *",
912 "rangesize", 100000);
914 if (config->rangesize < 2000) {
915 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
916 status = NT_STATUS_INVALID_PARAMETER;
920 config->maxranges = (dom->high_id - dom->low_id + 1) /
923 if (config->maxranges == 0) {
924 DEBUG(1, ("allowed uid range is smaller then rangesize, "
925 "increase uid range or decrease rangesize\n"));
926 status = NT_STATUS_INVALID_PARAMETER;
930 /* check if the high-low limit is a multiple of the rangesize */
931 if ((dom->high_id - dom->low_id + 1) % config->rangesize != 0) {
932 DEBUG(5, ("High uid-low uid difference of %d "
933 "is not a multiple of the rangesize %d, "
934 "limiting ranges to lower boundary number of %d\n",
935 (dom->high_id - dom->low_id + 1), config->rangesize,
939 DEBUG(10, ("Current configuration in config is "
940 "minvalue:%d rangesize:%d maxranges:%d\n",
941 config->minvalue, config->rangesize, config->maxranges));
943 /* read previously stored config and current HWM */
944 storedconfig = idmap_autorid_loadconfig(autorid_db, talloc_tos());
946 status = dbwrap_fetch_uint32_bystring(autorid_db, HWM, &hwm);
947 if (!NT_STATUS_IS_OK(status)) {
948 DEBUG(1, ("Fatal error while fetching current "
949 "HWM value: %s\n", nt_errstr(status)));
950 status = NT_STATUS_INTERNAL_ERROR;
954 /* did the minimum value or rangesize change? */
956 ((storedconfig->minvalue != config->minvalue) ||
957 (storedconfig->rangesize != config->rangesize))) {
958 DEBUG(1, ("New configuration values for rangesize or "
959 "minimum uid value conflict with previously "
960 "used values! Aborting initialization\n"));
961 status = NT_STATUS_INVALID_PARAMETER;
966 * has the highest uid value been reduced to setting that is not
967 * sufficient any more for already existing ranges?
969 if (hwm > config->maxranges) {
970 DEBUG(1, ("New upper uid limit is too low to cover "
971 "existing mappings! Aborting initialization\n"));
972 status = NT_STATUS_INVALID_PARAMETER;
976 status = idmap_autorid_saveconfig(autorid_db, config);
978 if (!NT_STATUS_IS_OK(status)) {
979 DEBUG(1, ("Failed to store configuration data!\n"));
983 DEBUG(5, ("%d domain ranges with a size of %d are available\n",
984 config->maxranges, config->rangesize));
986 ignore_builtin = lp_parm_bool(-1, "idmap config *",
987 "ignore builtin", false);
989 /* fill the TDB common configuration */
990 commonconfig->private_data = config;
992 commonconfig->db = autorid_db;
993 commonconfig->max_id = config->rangesize -1;
994 commonconfig->hwmkey_uid = ALLOC_HWM_UID;
995 commonconfig->hwmkey_gid = ALLOC_HWM_GID;
996 commonconfig->rw_ops->get_new_id = idmap_autorid_allocate_id;
997 commonconfig->rw_ops->set_mapping = idmap_tdb_common_set_mapping;
999 dom->private_data = commonconfig;
1001 /* preallocate well-known SIDs in the pool */
1002 status = idmap_autorid_preallocate_wellknown(dom);
1007 talloc_free(config);
1010 talloc_free(storedconfig);
1016 Close the idmap tdb instance
1018 static struct idmap_methods autorid_methods = {
1019 .init = idmap_autorid_initialize,
1020 .unixids_to_sids = idmap_autorid_unixids_to_sids,
1021 .sids_to_unixids = idmap_autorid_sids_to_unixids,
1022 .allocate_id = idmap_autorid_allocate_id
1025 NTSTATUS samba_init_module(void)
1027 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
1028 "autorid", &autorid_methods);