2 * idmap_autorid_tdb: This file contains common code used by
3 * idmap_autorid and net idmap autorid utilities. The common
4 * code provides functions for performing various operations
7 * Copyright (C) Christian Ambach, 2010-2012
8 * Copyright (C) Atul Kulkarni, 2013
9 * Copyright (C) Michael Adam, 2012-2013
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 #include "idmap_autorid_tdb.h"
27 #include "../libcli/security/dom_sid.h"
28 #include "lib/util/string_wrappers.h"
31 * Build the database keystring for getting a range
32 * belonging to a domain sid and a range index.
34 static void idmap_autorid_build_keystr(const char *domsid
,
35 uint32_t domain_range_index
,
38 if (domain_range_index
> 0) {
39 fstr_sprintf(keystr
, "%s#%"PRIu32
,
40 domsid
, domain_range_index
);
42 fstrcpy(keystr
, domsid
);
46 static char *idmap_autorid_build_keystr_talloc(TALLOC_CTX
*mem_ctx
,
48 uint32_t domain_range_index
)
52 if (domain_range_index
> 0) {
53 keystr
= talloc_asprintf(mem_ctx
, "%s#%"PRIu32
, domsid
,
56 keystr
= talloc_strdup(mem_ctx
, domsid
);
63 static bool idmap_autorid_validate_sid(const char *sid
)
65 struct dom_sid ignore
;
70 if (strcmp(sid
, ALLOC_RANGE
) == 0) {
74 return dom_sid_parse(sid
, &ignore
);
77 struct idmap_autorid_addrange_ctx
{
78 struct autorid_range_config
*range
;
82 static NTSTATUS
idmap_autorid_addrange_action(struct db_context
*db
,
85 struct idmap_autorid_addrange_ctx
*ctx
;
86 uint32_t requested_rangenum
, stored_rangenum
;
87 struct autorid_range_config
*range
;
92 struct autorid_global_config globalcfg
= {0};
95 TALLOC_CTX
*mem_ctx
= NULL
;
97 ctx
= (struct idmap_autorid_addrange_ctx
*)private_data
;
99 acquire
= ctx
->acquire
;
102 DEBUG(3, ("Invalid database argument: NULL\n"));
103 return NT_STATUS_INVALID_PARAMETER
;
107 DEBUG(3, ("Invalid range argument: NULL\n"));
108 return NT_STATUS_INVALID_PARAMETER
;
111 requested_rangenum
= range
->rangenum
;
113 DEBUG(10, ("Adding new range for domain %s "
114 "(domain_range_index=%"PRIu32
")\n",
115 range
->domsid
, range
->domain_range_index
));
117 if (!idmap_autorid_validate_sid(range
->domsid
)) {
118 DEBUG(3, ("Invalid SID: %s\n", range
->domsid
));
119 return NT_STATUS_INVALID_PARAMETER
;
122 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
125 ret
= dbwrap_fetch_uint32_bystring(db
, keystr
, &stored_rangenum
);
127 if (NT_STATUS_IS_OK(ret
)) {
128 /* entry is already present*/
130 DEBUG(10, ("domain range already allocated - "
133 ret
= idmap_autorid_loadconfig(db
, &globalcfg
);
134 if (!NT_STATUS_IS_OK(ret
)) {
135 DEBUG(1, ("Fatal error while fetching "
136 "configuration: %s\n",
141 range
->rangenum
= stored_rangenum
;
142 range
->low_id
= globalcfg
.minvalue
143 + range
->rangenum
* globalcfg
.rangesize
;
145 range
->low_id
+ globalcfg
.rangesize
- 1;
150 if (stored_rangenum
!= requested_rangenum
) {
151 DEBUG(1, ("Error: requested rangenumber (%u) differs "
152 "from stored one (%u).\n",
153 requested_rangenum
, stored_rangenum
));
154 return NT_STATUS_UNSUCCESSFUL
;
157 DEBUG(10, ("Note: stored range agrees with requested "
162 /* fetch the current HWM */
163 ret
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
164 if (!NT_STATUS_IS_OK(ret
)) {
165 DEBUG(1, ("Fatal error while fetching current "
166 "HWM value: %s\n", nt_errstr(ret
)));
167 return NT_STATUS_INTERNAL_ERROR
;
170 mem_ctx
= talloc_stackframe();
172 ret
= idmap_autorid_loadconfig(db
, &globalcfg
);
173 if (!NT_STATUS_IS_OK(ret
)) {
174 DEBUG(1, ("Fatal error while fetching configuration: %s\n",
181 * automatically acquire the next range
183 requested_rangenum
= hwm
;
186 if (requested_rangenum
>= globalcfg
.maxranges
) {
187 DBG_WARNING("Not enough ranges available: New range %u can't "
188 "be allocated. Consider increasing the range "
193 (globalcfg
.maxranges
* globalcfg
.rangesize
),
194 globalcfg
.rangesize
);
195 ret
= NT_STATUS_NO_MEMORY
;
200 * Check that it is not yet taken.
201 * If the range is requested and < HWM, we need
202 * to check anyways, and otherwise, we also better
203 * check in order to prevent further corruption
204 * in case the db has been externally modified.
207 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
209 DEBUG(1, ("Talloc failed!\n"));
210 ret
= NT_STATUS_NO_MEMORY
;
214 if (dbwrap_exists(db
, string_term_tdb_data(numstr
))) {
215 DEBUG(1, ("Requested range '%s' is already in use.\n", numstr
));
217 if (requested_rangenum
< hwm
) {
218 ret
= NT_STATUS_INVALID_PARAMETER
;
220 ret
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
226 if (requested_rangenum
>= hwm
) {
228 * requested or automatic range >= HWM:
232 /* HWM always contains current max range + 1 */
233 increment
= requested_rangenum
+ 1 - hwm
;
235 /* increase the HWM */
236 ret
= dbwrap_change_uint32_atomic_bystring(db
, HWM
, &hwm
,
238 if (!NT_STATUS_IS_OK(ret
)) {
239 DEBUG(1, ("Fatal error while incrementing the HWM "
240 "value in the database: %s\n",
247 * store away the new mapping in both directions
250 ret
= dbwrap_store_uint32_bystring(db
, keystr
, requested_rangenum
);
251 if (!NT_STATUS_IS_OK(ret
)) {
252 DEBUG(1, ("Fatal error while storing new "
253 "domain->range assignment: %s\n", nt_errstr(ret
)));
257 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
259 ret
= NT_STATUS_NO_MEMORY
;
263 ret
= dbwrap_store_bystring(db
, numstr
,
264 string_term_tdb_data(keystr
), TDB_INSERT
);
266 if (!NT_STATUS_IS_OK(ret
)) {
267 DEBUG(1, ("Fatal error while storing new "
268 "domain->range assignment: %s\n", nt_errstr(ret
)));
272 DEBUG(5, ("%s new range #%d for domain %s "
273 "(domain_range_index=%"PRIu32
")\n",
274 (acquire
?"Acquired":"Stored"),
275 requested_rangenum
, keystr
,
276 range
->domain_range_index
));
278 range
->rangenum
= requested_rangenum
;
280 range
->low_id
= globalcfg
.minvalue
281 + range
->rangenum
* globalcfg
.rangesize
;
282 range
->high_id
= range
->low_id
+ globalcfg
.rangesize
- 1;
287 talloc_free(mem_ctx
);
291 static NTSTATUS
idmap_autorid_addrange(struct db_context
*db
,
292 struct autorid_range_config
*range
,
296 struct idmap_autorid_addrange_ctx ctx
;
298 ctx
.acquire
= acquire
;
301 status
= dbwrap_trans_do(db
, idmap_autorid_addrange_action
, &ctx
);
305 NTSTATUS
idmap_autorid_setrange(struct db_context
*db
,
307 uint32_t domain_range_index
,
311 struct autorid_range_config range
;
314 fstrcpy(range
.domsid
, domsid
);
315 range
.domain_range_index
= domain_range_index
;
316 range
.rangenum
= rangenum
;
318 status
= idmap_autorid_addrange(db
, &range
, false);
322 NTSTATUS
idmap_autorid_acquire_range(struct db_context
*db
,
323 struct autorid_range_config
*range
)
325 return idmap_autorid_addrange(db
, range
, true);
328 static NTSTATUS
idmap_autorid_getrange_int(struct db_context
*db
,
329 struct autorid_range_config
*range
)
331 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
332 struct autorid_global_config globalcfg
= {0};
335 if (db
== NULL
|| range
== NULL
) {
336 DEBUG(3, ("Invalid arguments received\n"));
340 if (!idmap_autorid_validate_sid(range
->domsid
)) {
341 DEBUG(3, ("Invalid SID: '%s'\n", range
->domsid
));
342 status
= NT_STATUS_INVALID_PARAMETER
;
346 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
349 DEBUG(10, ("reading domain range for key %s\n", keystr
));
350 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &(range
->rangenum
));
351 if (!NT_STATUS_IS_OK(status
)) {
352 DEBUG(1, ("Failed to read database record for key '%s': %s\n",
353 keystr
, nt_errstr(status
)));
357 status
= idmap_autorid_loadconfig(db
, &globalcfg
);
358 if (!NT_STATUS_IS_OK(status
)) {
359 DEBUG(1, ("Failed to read global configuration\n"));
362 range
->low_id
= globalcfg
.minvalue
363 + range
->rangenum
* globalcfg
.rangesize
;
364 range
->high_id
= range
->low_id
+ globalcfg
.rangesize
- 1;
369 NTSTATUS
idmap_autorid_getrange(struct db_context
*db
,
371 uint32_t domain_range_index
,
376 struct autorid_range_config range
;
378 if (rangenum
== NULL
) {
379 return NT_STATUS_INVALID_PARAMETER
;
383 fstrcpy(range
.domsid
, domsid
);
384 range
.domain_range_index
= domain_range_index
;
386 status
= idmap_autorid_getrange_int(db
, &range
);
387 if (!NT_STATUS_IS_OK(status
)) {
391 *rangenum
= range
.rangenum
;
393 if (low_id
!= NULL
) {
394 *low_id
= range
.low_id
;
400 NTSTATUS
idmap_autorid_get_domainrange(struct db_context
*db
,
401 struct autorid_range_config
*range
,
406 ret
= idmap_autorid_getrange_int(db
, range
);
407 if (!NT_STATUS_IS_OK(ret
)) {
408 DEBUG(10, ("Failed to read range config for '%s': %s\n",
409 range
->domsid
, nt_errstr(ret
)));
411 DEBUG(10, ("Not allocating new range for '%s' because "
412 "read-only is enabled.\n", range
->domsid
));
413 return NT_STATUS_NOT_FOUND
;
416 ret
= idmap_autorid_acquire_range(db
, range
);
419 DEBUG(10, ("Using range #%d for domain %s "
420 "(domain_range_index=%"PRIu32
", low_id=%"PRIu32
")\n",
421 range
->rangenum
, range
->domsid
, range
->domain_range_index
,
427 /* initialize the given HWM to 0 if it does not exist yet */
428 static NTSTATUS
idmap_autorid_init_hwm_action(struct db_context
*db
,
435 hwm
= (char *)private_data
;
437 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
438 if (NT_STATUS_IS_OK(status
)) {
439 DEBUG(1, ("HWM (%s) already initialized in autorid database "
440 "(value %"PRIu32
").\n", hwm
, hwmval
));
443 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
444 DEBUG(0, ("Error fetching HWM (%s) from autorid "
445 "database: %s\n", hwm
, nt_errstr(status
)));
449 status
= dbwrap_trans_store_uint32_bystring(db
, hwm
, 0);
450 if (!NT_STATUS_IS_OK(status
)) {
451 DEBUG(0, ("Error storing HWM (%s) in autorid database: %s\n",
452 hwm
, nt_errstr(status
)));
459 NTSTATUS
idmap_autorid_init_hwm(struct db_context
*db
, const char *hwm
)
464 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
465 if (NT_STATUS_IS_OK(status
)) {
466 DEBUG(1, ("HWM (%s) already initialized in autorid database "
467 "(value %"PRIu32
").\n", hwm
, hwmval
));
470 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
471 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
472 "database: %s\n", hwm
, nt_errstr(status
)));
476 status
= dbwrap_trans_do(db
, idmap_autorid_init_hwm_action
,
478 if (!NT_STATUS_IS_OK(status
)) {
479 DEBUG(0, ("Error initializing HWM (%s) in autorid database: "
480 "%s\n", hwm
, nt_errstr(status
)));
481 return NT_STATUS_INTERNAL_DB_ERROR
;
484 DEBUG(1, ("Initialized HWM (%s) in autorid database.\n", hwm
));
490 * Delete a domain#index <-> range mapping from the database.
491 * The mapping is specified by the sid and index.
492 * If force == true, invalid mapping records are deleted as far
493 * as possible, otherwise they are left untouched.
496 struct idmap_autorid_delete_range_by_sid_ctx
{
498 uint32_t domain_range_index
;
502 static NTSTATUS
idmap_autorid_delete_range_by_sid_action(struct db_context
*db
,
505 struct idmap_autorid_delete_range_by_sid_ctx
*ctx
=
506 (struct idmap_autorid_delete_range_by_sid_ctx
*)private_data
;
508 uint32_t domain_range_index
;
514 TALLOC_CTX
*frame
= talloc_stackframe();
515 bool is_valid_range_mapping
= true;
518 domsid
= ctx
->domsid
;
519 domain_range_index
= ctx
->domain_range_index
;
522 keystr
= idmap_autorid_build_keystr_talloc(frame
, domsid
,
524 if (keystr
== NULL
) {
525 status
= NT_STATUS_NO_MEMORY
;
529 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &rangenum
);
530 if (!NT_STATUS_IS_OK(status
)) {
534 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
535 if (range_keystr
== NULL
) {
536 status
= NT_STATUS_NO_MEMORY
;
540 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &data
);
541 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
542 DEBUG(1, ("Incomplete mapping %s -> %s: no backward mapping\n",
543 keystr
, range_keystr
));
544 is_valid_range_mapping
= false;
545 } else if (!NT_STATUS_IS_OK(status
)) {
546 DEBUG(1, ("Error fetching reverse mapping for %s -> %s: %s\n",
547 keystr
, range_keystr
, nt_errstr(status
)));
549 } else if (strncmp((const char *)data
.dptr
, keystr
, strlen(keystr
))
552 DEBUG(1, ("Invalid mapping: %s -> %s -> %s\n",
553 keystr
, range_keystr
, (const char *)data
.dptr
));
554 is_valid_range_mapping
= false;
557 if (!is_valid_range_mapping
&& !force
) {
558 DEBUG(10, ("Not deleting invalid mapping, since not in force "
560 status
= NT_STATUS_FILE_INVALID
;
564 status
= dbwrap_delete_bystring(db
, keystr
);
565 if (!NT_STATUS_IS_OK(status
)) {
566 DEBUG(1, ("Deletion of '%s' failed: %s\n",
567 keystr
, nt_errstr(status
)));
571 if (!is_valid_range_mapping
) {
575 status
= dbwrap_delete_bystring(db
, range_keystr
);
576 if (!NT_STATUS_IS_OK(status
)) {
577 DEBUG(1, ("Deletion of '%s' failed: %s\n",
578 range_keystr
, nt_errstr(status
)));
582 DEBUG(10, ("Deleted range mapping %s <--> %s\n", keystr
,
590 NTSTATUS
idmap_autorid_delete_range_by_sid(struct db_context
*db
,
592 uint32_t domain_range_index
,
596 struct idmap_autorid_delete_range_by_sid_ctx ctx
;
598 ctx
.domain_range_index
= domain_range_index
;
602 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_sid_action
,
608 * Delete a domain#index <-> range mapping from the database.
609 * The mapping is specified by the range number.
610 * If force == true, invalid mapping records are deleted as far
611 * as possible, otherwise they are left untouched.
613 struct idmap_autorid_delete_range_by_num_ctx
{
618 static NTSTATUS
idmap_autorid_delete_range_by_num_action(struct db_context
*db
,
621 struct idmap_autorid_delete_range_by_num_ctx
*ctx
=
622 (struct idmap_autorid_delete_range_by_num_ctx
*)private_data
;
628 TALLOC_CTX
*frame
= talloc_stackframe();
629 bool is_valid_range_mapping
= true;
632 rangenum
= ctx
->rangenum
;
635 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
636 if (range_keystr
== NULL
) {
637 status
= NT_STATUS_NO_MEMORY
;
643 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &val
);
644 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
645 DEBUG(10, ("Did not find range '%s' in database.\n",
648 } else if (!NT_STATUS_IS_OK(status
)) {
649 DEBUG(5, ("Error fetching rang key: %s\n", nt_errstr(status
)));
653 if (val
.dptr
== NULL
) {
654 DEBUG(1, ("Invalid mapping: %s -> empty value\n",
656 is_valid_range_mapping
= false;
658 uint32_t reverse_rangenum
= 0;
660 keystr
= (char *)val
.dptr
;
662 status
= dbwrap_fetch_uint32_bystring(db
, keystr
,
664 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
665 DEBUG(1, ("Incomplete mapping %s -> %s: "
666 "no backward mapping\n",
667 range_keystr
, keystr
));
668 is_valid_range_mapping
= false;
669 } else if (!NT_STATUS_IS_OK(status
)) {
670 DEBUG(1, ("Error fetching reverse mapping for "
672 range_keystr
, keystr
, nt_errstr(status
)));
674 } else if (rangenum
!= reverse_rangenum
) {
675 is_valid_range_mapping
= false;
679 if (!is_valid_range_mapping
&& !force
) {
680 DEBUG(10, ("Not deleting invalid mapping, since not in force "
682 status
= NT_STATUS_FILE_INVALID
;
686 status
= dbwrap_delete_bystring(db
, range_keystr
);
687 if (!NT_STATUS_IS_OK(status
)) {
688 DEBUG(1, ("Deletion of '%s' failed: %s\n",
689 range_keystr
, nt_errstr(status
)));
693 if (!is_valid_range_mapping
) {
697 status
= dbwrap_delete_bystring(db
, keystr
);
698 if (!NT_STATUS_IS_OK(status
)) {
699 DEBUG(1, ("Deletion of '%s' failed: %s\n",
700 keystr
, nt_errstr(status
)));
704 DEBUG(10, ("Deleted range mapping %s <--> %s\n", range_keystr
,
712 NTSTATUS
idmap_autorid_delete_range_by_num(struct db_context
*db
,
717 struct idmap_autorid_delete_range_by_num_ctx ctx
;
719 ctx
.rangenum
= rangenum
;
722 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_num_action
,
728 * Open and possibly create the database.
730 NTSTATUS
idmap_autorid_db_open(const char *path
,
732 struct db_context
**db
)
735 /* its already open */
739 /* Open idmap repository */
740 *db
= db_open(mem_ctx
, path
, 0, TDB_DEFAULT
, O_RDWR
| O_CREAT
, 0644,
741 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
744 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path
));
745 return NT_STATUS_UNSUCCESSFUL
;
752 * Initialize the high watermark records in the database.
754 NTSTATUS
idmap_autorid_init_hwms(struct db_context
*db
)
758 status
= idmap_autorid_init_hwm(db
, HWM
);
759 if (!NT_STATUS_IS_OK(status
)) {
763 status
= idmap_autorid_init_hwm(db
, ALLOC_HWM_UID
);
764 if (!NT_STATUS_IS_OK(status
)) {
768 status
= idmap_autorid_init_hwm(db
, ALLOC_HWM_GID
);
773 NTSTATUS
idmap_autorid_db_init(const char *path
,
775 struct db_context
**db
)
779 status
= idmap_autorid_db_open(path
, mem_ctx
, db
);
780 if (!NT_STATUS_IS_OK(status
)) {
784 status
= idmap_autorid_init_hwms(*db
);
790 struct idmap_autorid_fetch_config_state
{
795 static void idmap_autorid_config_parser(TDB_DATA key
, TDB_DATA value
,
798 struct idmap_autorid_fetch_config_state
*state
;
800 state
= (struct idmap_autorid_fetch_config_state
*)private_data
;
803 * strndup because we have non-nullterminated strings in the db
805 state
->configstr
= talloc_strndup(
806 state
->mem_ctx
, (const char *)value
.dptr
, value
.dsize
);
809 NTSTATUS
idmap_autorid_getconfigstr(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
814 struct idmap_autorid_fetch_config_state state
;
816 if (result
== NULL
) {
817 return NT_STATUS_INVALID_PARAMETER
;
820 key
= string_term_tdb_data(CONFIGKEY
);
822 state
.mem_ctx
= mem_ctx
;
823 state
.configstr
= NULL
;
825 status
= dbwrap_parse_record(db
, key
, idmap_autorid_config_parser
,
827 if (!NT_STATUS_IS_OK(status
)) {
828 DEBUG(1, ("Error while retrieving config: %s\n",
833 if (state
.configstr
== NULL
) {
834 DEBUG(1, ("Error while retrieving config\n"));
835 return NT_STATUS_NO_MEMORY
;
838 DEBUG(5, ("found CONFIG: %s\n", state
.configstr
));
840 *result
= state
.configstr
;
844 bool idmap_autorid_parse_configstr(const char *configstr
,
845 struct autorid_global_config
*cfg
)
847 unsigned long minvalue
, rangesize
, maxranges
;
849 if (sscanf(configstr
,
850 "minvalue:%lu rangesize:%lu maxranges:%lu",
851 &minvalue
, &rangesize
, &maxranges
) != 3) {
853 ("Found invalid configuration data. "
854 "Creating new config\n"));
858 cfg
->minvalue
= minvalue
;
859 cfg
->rangesize
= rangesize
;
860 cfg
->maxranges
= maxranges
;
865 NTSTATUS
idmap_autorid_loadconfig(struct db_context
*db
,
866 struct autorid_global_config
*result
)
868 struct autorid_global_config cfg
= {0};
871 char *configstr
= NULL
;
873 if (result
== NULL
) {
874 return NT_STATUS_INVALID_PARAMETER
;
877 status
= idmap_autorid_getconfigstr(db
, db
, &configstr
);
878 if (!NT_STATUS_IS_OK(status
)) {
882 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
883 TALLOC_FREE(configstr
);
885 return NT_STATUS_INVALID_PARAMETER
;
888 DEBUG(10, ("Loaded previously stored configuration "
889 "minvalue:%d rangesize:%d\n",
890 cfg
.minvalue
, cfg
.rangesize
));
897 NTSTATUS
idmap_autorid_saveconfig(struct db_context
*db
,
898 struct autorid_global_config
*cfg
)
901 struct autorid_global_config storedconfig
= {0};
902 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
906 TALLOC_CTX
*frame
= talloc_stackframe();
908 DEBUG(10, ("New configuration provided for storing is "
909 "minvalue:%d rangesize:%d maxranges:%d\n",
910 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
));
912 if (cfg
->rangesize
< 2000) {
913 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
917 if (cfg
->maxranges
== 0) {
918 DEBUG(1, ("An autorid maxranges value of 0 is invalid. "
919 "Must have at least one range available.\n"));
923 status
= idmap_autorid_loadconfig(db
, &storedconfig
);
924 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
925 DEBUG(5, ("No configuration found. Storing initial "
926 "configuration.\n"));
928 } else if (!NT_STATUS_IS_OK(status
)) {
929 DEBUG(1, ("Error loading configuration: %s\n",
934 /* did the minimum value or rangesize change? */
935 if ((storedconfig
.minvalue
!= cfg
->minvalue
) ||
936 (storedconfig
.rangesize
!= cfg
->rangesize
))
938 DEBUG(1, ("New configuration values for rangesize or "
939 "minimum uid value conflict with previously "
940 "used values! Not storing new config.\n"));
941 status
= NT_STATUS_INVALID_PARAMETER
;
945 status
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
946 if (!NT_STATUS_IS_OK(status
)) {
947 DEBUG(1, ("Fatal error while fetching current "
948 "HWM value: %s\n", nt_errstr(status
)));
949 status
= NT_STATUS_INTERNAL_ERROR
;
954 * has the highest uid value been reduced to setting that is not
955 * sufficient any more for already existing ranges?
957 if (hwm
> cfg
->maxranges
) {
958 DEBUG(1, ("New upper uid limit is too low to cover "
959 "existing mappings! Not storing new config.\n"));
960 status
= NT_STATUS_INVALID_PARAMETER
;
965 talloc_asprintf(frame
,
966 "minvalue:%u rangesize:%u maxranges:%u",
967 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
);
969 if (cfgstr
== NULL
) {
970 status
= NT_STATUS_NO_MEMORY
;
974 data
= string_tdb_data(cfgstr
);
976 status
= dbwrap_trans_store_bystring(db
, CONFIGKEY
, data
, TDB_REPLACE
);
983 NTSTATUS
idmap_autorid_saveconfigstr(struct db_context
*db
,
984 const char *configstr
)
988 struct autorid_global_config cfg
;
990 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
992 return NT_STATUS_INVALID_PARAMETER
;
995 status
= idmap_autorid_saveconfig(db
, &cfg
);
1001 * iteration: Work on all range mappings for a given domain
1004 struct domain_range_visitor_ctx
{
1006 NTSTATUS (*fn
)(struct db_context
*db
,
1010 void *private_data
);
1012 int count
; /* number of records worked on */
1015 static int idmap_autorid_visit_domain_range(struct db_record
*rec
,
1018 struct domain_range_visitor_ctx
*vi
;
1021 uint32_t range_index
= 0;
1022 uint32_t rangenum
= 0;
1023 TDB_DATA key
, value
;
1026 struct db_context
*db
;
1028 vi
= talloc_get_type_abort(private_data
,
1029 struct domain_range_visitor_ctx
);
1031 key
= dbwrap_record_get_key(rec
);
1034 * split string "<sid>[#<index>]" into sid string and index number
1037 domsid
= (char *)key
.dptr
;
1039 DEBUG(10, ("idmap_autorid_visit_domain_range: visiting key '%s'\n",
1042 sep
= strrchr(domsid
, '#');
1047 if (sscanf(index_str
, "%"SCNu32
, &range_index
) != 1) {
1048 DEBUG(10, ("Found separator '#' but '%s' is not a "
1049 "valid range index. Skipping record\n",
1055 if (!idmap_autorid_validate_sid(domsid
)) {
1056 DEBUG(10, ("String '%s' is not a valid sid. "
1057 "Skipping record.\n", domsid
));
1061 if ((vi
->domsid
!= NULL
) && (strcmp(domsid
, vi
->domsid
) != 0)) {
1062 DEBUG(10, ("key sid '%s' does not match requested sid '%s'.\n",
1063 domsid
, vi
->domsid
));
1067 value
= dbwrap_record_get_value(rec
);
1069 if (value
.dsize
!= sizeof(uint32_t)) {
1070 /* it might be a mapping of a well known sid */
1071 DEBUG(10, ("value size %u != sizeof(uint32_t) for sid '%s', "
1072 "skipping.\n", (unsigned)value
.dsize
, vi
->domsid
));
1076 rangenum
= IVAL(value
.dptr
, 0);
1078 db
= dbwrap_record_get_db(rec
);
1080 status
= vi
->fn(db
, domsid
, range_index
, rangenum
, vi
->private_data
);
1081 if (!NT_STATUS_IS_OK(status
)) {
1093 static NTSTATUS
idmap_autorid_iterate_domain_ranges_int(struct db_context
*db
,
1095 NTSTATUS (*fn
)(struct db_context
*db
,
1099 void *private_data
),
1102 NTSTATUS (*traverse
)(struct db_context
*db
,
1103 int (*f
)(struct db_record
*, void *),
1108 struct domain_range_visitor_ctx
*vi
;
1109 TALLOC_CTX
*frame
= talloc_stackframe();
1111 if (domsid
== NULL
) {
1112 DEBUG(10, ("No sid provided, operating on all ranges\n"));
1116 DEBUG(1, ("Error: missing visitor callback\n"));
1117 status
= NT_STATUS_INVALID_PARAMETER
;
1121 vi
= talloc_zero(frame
, struct domain_range_visitor_ctx
);
1123 status
= NT_STATUS_NO_MEMORY
;
1127 vi
->domsid
= domsid
;
1129 vi
->private_data
= private_data
;
1131 status
= traverse(db
, idmap_autorid_visit_domain_range
, vi
, NULL
);
1132 if (!NT_STATUS_IS_OK(status
)) {
1136 if (count
!= NULL
) {
1145 NTSTATUS
idmap_autorid_iterate_domain_ranges(struct db_context
*db
,
1147 NTSTATUS (*fn
)(struct db_context
*db
,
1151 void *private_data
),
1157 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1168 NTSTATUS
idmap_autorid_iterate_domain_ranges_read(struct db_context
*db
,
1170 NTSTATUS (*fn
)(struct db_context
*db
,
1180 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1185 dbwrap_traverse_read
);
1192 * Delete all ranges configured for a given domain
1195 struct delete_domain_ranges_visitor_ctx
{
1199 static NTSTATUS
idmap_autorid_delete_domain_ranges_visitor(
1200 struct db_context
*db
,
1202 uint32_t domain_range_index
,
1206 struct delete_domain_ranges_visitor_ctx
*ctx
;
1209 ctx
= (struct delete_domain_ranges_visitor_ctx
*)private_data
;
1211 status
= idmap_autorid_delete_range_by_sid(
1212 db
, domsid
, domain_range_index
, ctx
->force
);
1216 struct idmap_autorid_delete_domain_ranges_ctx
{
1219 int count
; /* output: count records operated on */
1222 static NTSTATUS
idmap_autorid_delete_domain_ranges_action(struct db_context
*db
,
1225 struct idmap_autorid_delete_domain_ranges_ctx
*ctx
;
1226 struct delete_domain_ranges_visitor_ctx visitor_ctx
;
1230 ctx
= (struct idmap_autorid_delete_domain_ranges_ctx
*)private_data
;
1232 ZERO_STRUCT(visitor_ctx
);
1233 visitor_ctx
.force
= ctx
->force
;
1235 status
= idmap_autorid_iterate_domain_ranges(db
,
1237 idmap_autorid_delete_domain_ranges_visitor
,
1240 if (!NT_STATUS_IS_OK(status
)) {
1246 return NT_STATUS_OK
;
1249 NTSTATUS
idmap_autorid_delete_domain_ranges(struct db_context
*db
,
1255 struct idmap_autorid_delete_domain_ranges_ctx ctx
;
1258 ctx
.domsid
= domsid
;
1261 status
= dbwrap_trans_do(db
, idmap_autorid_delete_domain_ranges_action
,
1263 if (!NT_STATUS_IS_OK(status
)) {
1269 return NT_STATUS_OK
;