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
;
100 requested_rangenum
= range
->rangenum
;
103 DEBUG(3, ("Invalid database argument: NULL"));
104 return NT_STATUS_INVALID_PARAMETER
;
108 DEBUG(3, ("Invalid range argument: NULL"));
109 return NT_STATUS_INVALID_PARAMETER
;
112 DEBUG(10, ("Adding new range for domain %s "
113 "(domain_range_index=%"PRIu32
")\n",
114 range
->domsid
, range
->domain_range_index
));
116 if (!idmap_autorid_validate_sid(range
->domsid
)) {
117 DEBUG(3, ("Invalid SID: %s\n", range
->domsid
));
118 return NT_STATUS_INVALID_PARAMETER
;
121 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
124 ret
= dbwrap_fetch_uint32_bystring(db
, keystr
, &stored_rangenum
);
126 if (NT_STATUS_IS_OK(ret
)) {
127 /* entry is already present*/
129 DEBUG(10, ("domain range already allocated - "
132 ret
= idmap_autorid_loadconfig(db
, &globalcfg
);
133 if (!NT_STATUS_IS_OK(ret
)) {
134 DEBUG(1, ("Fatal error while fetching "
135 "configuration: %s\n",
140 range
->rangenum
= stored_rangenum
;
141 range
->low_id
= globalcfg
.minvalue
142 + range
->rangenum
* globalcfg
.rangesize
;
144 range
->low_id
+ globalcfg
.rangesize
- 1;
149 if (stored_rangenum
!= requested_rangenum
) {
150 DEBUG(1, ("Error: requested rangenumber (%u) differs "
151 "from stored one (%u).\n",
152 requested_rangenum
, stored_rangenum
));
153 return NT_STATUS_UNSUCCESSFUL
;
156 DEBUG(10, ("Note: stored range agrees with requested "
161 /* fetch the current HWM */
162 ret
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
163 if (!NT_STATUS_IS_OK(ret
)) {
164 DEBUG(1, ("Fatal error while fetching current "
165 "HWM value: %s\n", nt_errstr(ret
)));
166 return NT_STATUS_INTERNAL_ERROR
;
169 mem_ctx
= talloc_stackframe();
171 ret
= idmap_autorid_loadconfig(db
, &globalcfg
);
172 if (!NT_STATUS_IS_OK(ret
)) {
173 DEBUG(1, ("Fatal error while fetching configuration: %s\n",
180 * automatically acquire the next range
182 requested_rangenum
= hwm
;
185 if (requested_rangenum
>= globalcfg
.maxranges
) {
186 DBG_WARNING("Not enough ranges available: New range %u can't "
187 "be allocated. Consider increasing the range "
192 (globalcfg
.maxranges
* globalcfg
.rangesize
),
193 globalcfg
.rangesize
);
194 ret
= NT_STATUS_NO_MEMORY
;
199 * Check that it is not yet taken.
200 * If the range is requested and < HWM, we need
201 * to check anyways, and otherwise, we also better
202 * check in order to prevent further corruption
203 * in case the db has been externally modified.
206 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
208 DEBUG(1, ("Talloc failed!\n"));
209 ret
= NT_STATUS_NO_MEMORY
;
213 if (dbwrap_exists(db
, string_term_tdb_data(numstr
))) {
214 DEBUG(1, ("Requested range '%s' is already in use.\n", numstr
));
216 if (requested_rangenum
< hwm
) {
217 ret
= NT_STATUS_INVALID_PARAMETER
;
219 ret
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
225 if (requested_rangenum
>= hwm
) {
227 * requested or automatic range >= HWM:
231 /* HWM always contains current max range + 1 */
232 increment
= requested_rangenum
+ 1 - hwm
;
234 /* increase the HWM */
235 ret
= dbwrap_change_uint32_atomic_bystring(db
, HWM
, &hwm
,
237 if (!NT_STATUS_IS_OK(ret
)) {
238 DEBUG(1, ("Fatal error while incrementing the HWM "
239 "value in the database: %s\n",
246 * store away the new mapping in both directions
249 ret
= dbwrap_store_uint32_bystring(db
, keystr
, requested_rangenum
);
250 if (!NT_STATUS_IS_OK(ret
)) {
251 DEBUG(1, ("Fatal error while storing new "
252 "domain->range assignment: %s\n", nt_errstr(ret
)));
256 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
258 ret
= NT_STATUS_NO_MEMORY
;
262 ret
= dbwrap_store_bystring(db
, numstr
,
263 string_term_tdb_data(keystr
), TDB_INSERT
);
265 if (!NT_STATUS_IS_OK(ret
)) {
266 DEBUG(1, ("Fatal error while storing new "
267 "domain->range assignment: %s\n", nt_errstr(ret
)));
271 DEBUG(5, ("%s new range #%d for domain %s "
272 "(domain_range_index=%"PRIu32
")\n",
273 (acquire
?"Acquired":"Stored"),
274 requested_rangenum
, keystr
,
275 range
->domain_range_index
));
277 range
->rangenum
= requested_rangenum
;
279 range
->low_id
= globalcfg
.minvalue
280 + range
->rangenum
* globalcfg
.rangesize
;
281 range
->high_id
= range
->low_id
+ globalcfg
.rangesize
- 1;
286 talloc_free(mem_ctx
);
290 static NTSTATUS
idmap_autorid_addrange(struct db_context
*db
,
291 struct autorid_range_config
*range
,
295 struct idmap_autorid_addrange_ctx ctx
;
297 ctx
.acquire
= acquire
;
300 status
= dbwrap_trans_do(db
, idmap_autorid_addrange_action
, &ctx
);
304 NTSTATUS
idmap_autorid_setrange(struct db_context
*db
,
306 uint32_t domain_range_index
,
310 struct autorid_range_config range
;
313 fstrcpy(range
.domsid
, domsid
);
314 range
.domain_range_index
= domain_range_index
;
315 range
.rangenum
= rangenum
;
317 status
= idmap_autorid_addrange(db
, &range
, false);
321 NTSTATUS
idmap_autorid_acquire_range(struct db_context
*db
,
322 struct autorid_range_config
*range
)
324 return idmap_autorid_addrange(db
, range
, true);
327 static NTSTATUS
idmap_autorid_getrange_int(struct db_context
*db
,
328 struct autorid_range_config
*range
)
330 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
331 struct autorid_global_config globalcfg
= {0};
334 if (db
== NULL
|| range
== NULL
) {
335 DEBUG(3, ("Invalid arguments received\n"));
339 if (!idmap_autorid_validate_sid(range
->domsid
)) {
340 DEBUG(3, ("Invalid SID: '%s'\n", range
->domsid
));
341 status
= NT_STATUS_INVALID_PARAMETER
;
345 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
348 DEBUG(10, ("reading domain range for key %s\n", keystr
));
349 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &(range
->rangenum
));
350 if (!NT_STATUS_IS_OK(status
)) {
351 DEBUG(1, ("Failed to read database record for key '%s': %s\n",
352 keystr
, nt_errstr(status
)));
356 status
= idmap_autorid_loadconfig(db
, &globalcfg
);
357 if (!NT_STATUS_IS_OK(status
)) {
358 DEBUG(1, ("Failed to read global configuration"));
361 range
->low_id
= globalcfg
.minvalue
362 + range
->rangenum
* globalcfg
.rangesize
;
363 range
->high_id
= range
->low_id
+ globalcfg
.rangesize
- 1;
368 NTSTATUS
idmap_autorid_getrange(struct db_context
*db
,
370 uint32_t domain_range_index
,
375 struct autorid_range_config range
;
377 if (rangenum
== NULL
) {
378 return NT_STATUS_INVALID_PARAMETER
;
382 fstrcpy(range
.domsid
, domsid
);
383 range
.domain_range_index
= domain_range_index
;
385 status
= idmap_autorid_getrange_int(db
, &range
);
386 if (!NT_STATUS_IS_OK(status
)) {
390 *rangenum
= range
.rangenum
;
392 if (low_id
!= NULL
) {
393 *low_id
= range
.low_id
;
399 NTSTATUS
idmap_autorid_get_domainrange(struct db_context
*db
,
400 struct autorid_range_config
*range
,
405 ret
= idmap_autorid_getrange_int(db
, range
);
406 if (!NT_STATUS_IS_OK(ret
)) {
407 DEBUG(10, ("Failed to read range config for '%s': %s\n",
408 range
->domsid
, nt_errstr(ret
)));
410 DEBUG(10, ("Not allocating new range for '%s' because "
411 "read-only is enabled.\n", range
->domsid
));
412 return NT_STATUS_NOT_FOUND
;
415 ret
= idmap_autorid_acquire_range(db
, range
);
418 DEBUG(10, ("Using range #%d for domain %s "
419 "(domain_range_index=%"PRIu32
", low_id=%"PRIu32
")\n",
420 range
->rangenum
, range
->domsid
, range
->domain_range_index
,
426 /* initialize the given HWM to 0 if it does not exist yet */
427 static NTSTATUS
idmap_autorid_init_hwm_action(struct db_context
*db
,
434 hwm
= (char *)private_data
;
436 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
437 if (NT_STATUS_IS_OK(status
)) {
438 DEBUG(1, ("HWM (%s) already initialized in autorid database "
439 "(value %"PRIu32
").\n", hwm
, hwmval
));
442 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
443 DEBUG(0, ("Error fetching HWM (%s) from autorid "
444 "database: %s\n", hwm
, nt_errstr(status
)));
448 status
= dbwrap_trans_store_uint32_bystring(db
, hwm
, 0);
449 if (!NT_STATUS_IS_OK(status
)) {
450 DEBUG(0, ("Error storing HWM (%s) in autorid database: %s\n",
451 hwm
, nt_errstr(status
)));
458 NTSTATUS
idmap_autorid_init_hwm(struct db_context
*db
, const char *hwm
)
463 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
464 if (NT_STATUS_IS_OK(status
)) {
465 DEBUG(1, ("HWM (%s) already initialized in autorid database "
466 "(value %"PRIu32
").\n", hwm
, hwmval
));
469 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
470 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
471 "database: %s\n", hwm
, nt_errstr(status
)));
475 status
= dbwrap_trans_do(db
, idmap_autorid_init_hwm_action
,
477 if (!NT_STATUS_IS_OK(status
)) {
478 DEBUG(0, ("Error initializing HWM (%s) in autorid database: "
479 "%s\n", hwm
, nt_errstr(status
)));
480 return NT_STATUS_INTERNAL_DB_ERROR
;
483 DEBUG(1, ("Initialized HWM (%s) in autorid database.\n", hwm
));
489 * Delete a domain#index <-> range mapping from the database.
490 * The mapping is specified by the sid and index.
491 * If force == true, invalid mapping records are deleted as far
492 * as possible, otherwise they are left untouched.
495 struct idmap_autorid_delete_range_by_sid_ctx
{
497 uint32_t domain_range_index
;
501 static NTSTATUS
idmap_autorid_delete_range_by_sid_action(struct db_context
*db
,
504 struct idmap_autorid_delete_range_by_sid_ctx
*ctx
=
505 (struct idmap_autorid_delete_range_by_sid_ctx
*)private_data
;
507 uint32_t domain_range_index
;
513 TALLOC_CTX
*frame
= talloc_stackframe();
514 bool is_valid_range_mapping
= true;
517 domsid
= ctx
->domsid
;
518 domain_range_index
= ctx
->domain_range_index
;
521 keystr
= idmap_autorid_build_keystr_talloc(frame
, domsid
,
523 if (keystr
== NULL
) {
524 status
= NT_STATUS_NO_MEMORY
;
528 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &rangenum
);
529 if (!NT_STATUS_IS_OK(status
)) {
533 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
534 if (range_keystr
== NULL
) {
535 status
= NT_STATUS_NO_MEMORY
;
539 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &data
);
540 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
541 DEBUG(1, ("Incomplete mapping %s -> %s: no backward mapping\n",
542 keystr
, range_keystr
));
543 is_valid_range_mapping
= false;
544 } else if (!NT_STATUS_IS_OK(status
)) {
545 DEBUG(1, ("Error fetching reverse mapping for %s -> %s: %s\n",
546 keystr
, range_keystr
, nt_errstr(status
)));
548 } else if (strncmp((const char *)data
.dptr
, keystr
, strlen(keystr
))
551 DEBUG(1, ("Invalid mapping: %s -> %s -> %s\n",
552 keystr
, range_keystr
, (const char *)data
.dptr
));
553 is_valid_range_mapping
= false;
556 if (!is_valid_range_mapping
&& !force
) {
557 DEBUG(10, ("Not deleting invalid mapping, since not in force "
559 status
= NT_STATUS_FILE_INVALID
;
563 status
= dbwrap_delete_bystring(db
, keystr
);
564 if (!NT_STATUS_IS_OK(status
)) {
565 DEBUG(1, ("Deletion of '%s' failed: %s\n",
566 keystr
, nt_errstr(status
)));
570 if (!is_valid_range_mapping
) {
574 status
= dbwrap_delete_bystring(db
, range_keystr
);
575 if (!NT_STATUS_IS_OK(status
)) {
576 DEBUG(1, ("Deletion of '%s' failed: %s\n",
577 range_keystr
, nt_errstr(status
)));
581 DEBUG(10, ("Deleted range mapping %s <--> %s\n", keystr
,
589 NTSTATUS
idmap_autorid_delete_range_by_sid(struct db_context
*db
,
591 uint32_t domain_range_index
,
595 struct idmap_autorid_delete_range_by_sid_ctx ctx
;
597 ctx
.domain_range_index
= domain_range_index
;
601 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_sid_action
,
607 * Delete a domain#index <-> range mapping from the database.
608 * The mapping is specified by the range number.
609 * If force == true, invalid mapping records are deleted as far
610 * as possible, otherwise they are left untouched.
612 struct idmap_autorid_delete_range_by_num_ctx
{
617 static NTSTATUS
idmap_autorid_delete_range_by_num_action(struct db_context
*db
,
620 struct idmap_autorid_delete_range_by_num_ctx
*ctx
=
621 (struct idmap_autorid_delete_range_by_num_ctx
*)private_data
;
627 TALLOC_CTX
*frame
= talloc_stackframe();
628 bool is_valid_range_mapping
= true;
631 rangenum
= ctx
->rangenum
;
634 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
635 if (range_keystr
== NULL
) {
636 status
= NT_STATUS_NO_MEMORY
;
642 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &val
);
643 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
644 DEBUG(10, ("Did not find range '%s' in database.\n",
647 } else if (!NT_STATUS_IS_OK(status
)) {
648 DEBUG(5, ("Error fetching rang key: %s\n", nt_errstr(status
)));
652 if (val
.dptr
== NULL
) {
653 DEBUG(1, ("Invalid mapping: %s -> empty value\n",
655 is_valid_range_mapping
= false;
657 uint32_t reverse_rangenum
= 0;
659 keystr
= (char *)val
.dptr
;
661 status
= dbwrap_fetch_uint32_bystring(db
, keystr
,
663 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
664 DEBUG(1, ("Incomplete mapping %s -> %s: "
665 "no backward mapping\n",
666 range_keystr
, keystr
));
667 is_valid_range_mapping
= false;
668 } else if (!NT_STATUS_IS_OK(status
)) {
669 DEBUG(1, ("Error fetching reverse mapping for "
671 range_keystr
, keystr
, nt_errstr(status
)));
673 } else if (rangenum
!= reverse_rangenum
) {
674 is_valid_range_mapping
= false;
678 if (!is_valid_range_mapping
&& !force
) {
679 DEBUG(10, ("Not deleting invalid mapping, since not in force "
681 status
= NT_STATUS_FILE_INVALID
;
685 status
= dbwrap_delete_bystring(db
, range_keystr
);
686 if (!NT_STATUS_IS_OK(status
)) {
687 DEBUG(1, ("Deletion of '%s' failed: %s\n",
688 range_keystr
, nt_errstr(status
)));
692 if (!is_valid_range_mapping
) {
696 status
= dbwrap_delete_bystring(db
, keystr
);
697 if (!NT_STATUS_IS_OK(status
)) {
698 DEBUG(1, ("Deletion of '%s' failed: %s\n",
699 keystr
, nt_errstr(status
)));
703 DEBUG(10, ("Deleted range mapping %s <--> %s\n", range_keystr
,
711 NTSTATUS
idmap_autorid_delete_range_by_num(struct db_context
*db
,
716 struct idmap_autorid_delete_range_by_num_ctx ctx
;
718 ctx
.rangenum
= rangenum
;
721 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_num_action
,
727 * Open and possibly create the database.
729 NTSTATUS
idmap_autorid_db_open(const char *path
,
731 struct db_context
**db
)
734 /* its already open */
738 /* Open idmap repository */
739 *db
= db_open(mem_ctx
, path
, 0, TDB_DEFAULT
, O_RDWR
| O_CREAT
, 0644,
740 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
743 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path
));
744 return NT_STATUS_UNSUCCESSFUL
;
751 * Initialize the high watermark records in the database.
753 NTSTATUS
idmap_autorid_init_hwms(struct db_context
*db
)
757 status
= idmap_autorid_init_hwm(db
, HWM
);
758 if (!NT_STATUS_IS_OK(status
)) {
762 status
= idmap_autorid_init_hwm(db
, ALLOC_HWM_UID
);
763 if (!NT_STATUS_IS_OK(status
)) {
767 status
= idmap_autorid_init_hwm(db
, ALLOC_HWM_GID
);
772 NTSTATUS
idmap_autorid_db_init(const char *path
,
774 struct db_context
**db
)
778 status
= idmap_autorid_db_open(path
, mem_ctx
, db
);
779 if (!NT_STATUS_IS_OK(status
)) {
783 status
= idmap_autorid_init_hwms(*db
);
789 struct idmap_autorid_fetch_config_state
{
794 static void idmap_autorid_config_parser(TDB_DATA key
, TDB_DATA value
,
797 struct idmap_autorid_fetch_config_state
*state
;
799 state
= (struct idmap_autorid_fetch_config_state
*)private_data
;
802 * strndup because we have non-nullterminated strings in the db
804 state
->configstr
= talloc_strndup(
805 state
->mem_ctx
, (const char *)value
.dptr
, value
.dsize
);
808 NTSTATUS
idmap_autorid_getconfigstr(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
813 struct idmap_autorid_fetch_config_state state
;
815 if (result
== NULL
) {
816 return NT_STATUS_INVALID_PARAMETER
;
819 key
= string_term_tdb_data(CONFIGKEY
);
821 state
.mem_ctx
= mem_ctx
;
822 state
.configstr
= NULL
;
824 status
= dbwrap_parse_record(db
, key
, idmap_autorid_config_parser
,
826 if (!NT_STATUS_IS_OK(status
)) {
827 DEBUG(1, ("Error while retrieving config: %s\n",
832 if (state
.configstr
== NULL
) {
833 DEBUG(1, ("Error while retrieving config\n"));
834 return NT_STATUS_NO_MEMORY
;
837 DEBUG(5, ("found CONFIG: %s\n", state
.configstr
));
839 *result
= state
.configstr
;
843 bool idmap_autorid_parse_configstr(const char *configstr
,
844 struct autorid_global_config
*cfg
)
846 unsigned long minvalue
, rangesize
, maxranges
;
848 if (sscanf(configstr
,
849 "minvalue:%lu rangesize:%lu maxranges:%lu",
850 &minvalue
, &rangesize
, &maxranges
) != 3) {
852 ("Found invalid configuration data. "
853 "Creating new config\n"));
857 cfg
->minvalue
= minvalue
;
858 cfg
->rangesize
= rangesize
;
859 cfg
->maxranges
= maxranges
;
864 NTSTATUS
idmap_autorid_loadconfig(struct db_context
*db
,
865 struct autorid_global_config
*result
)
867 struct autorid_global_config cfg
= {0};
870 char *configstr
= NULL
;
872 if (result
== NULL
) {
873 return NT_STATUS_INVALID_PARAMETER
;
876 status
= idmap_autorid_getconfigstr(db
, db
, &configstr
);
877 if (!NT_STATUS_IS_OK(status
)) {
881 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
882 TALLOC_FREE(configstr
);
884 return NT_STATUS_INVALID_PARAMETER
;
887 DEBUG(10, ("Loaded previously stored configuration "
888 "minvalue:%d rangesize:%d\n",
889 cfg
.minvalue
, cfg
.rangesize
));
896 NTSTATUS
idmap_autorid_saveconfig(struct db_context
*db
,
897 struct autorid_global_config
*cfg
)
900 struct autorid_global_config storedconfig
= {0};
901 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
905 TALLOC_CTX
*frame
= talloc_stackframe();
907 DEBUG(10, ("New configuration provided for storing is "
908 "minvalue:%d rangesize:%d maxranges:%d\n",
909 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
));
911 if (cfg
->rangesize
< 2000) {
912 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
916 if (cfg
->maxranges
== 0) {
917 DEBUG(1, ("An autorid maxranges value of 0 is invalid. "
918 "Must have at least one range available.\n"));
922 status
= idmap_autorid_loadconfig(db
, &storedconfig
);
923 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
924 DEBUG(5, ("No configuration found. Storing initial "
925 "configuration.\n"));
927 } else if (!NT_STATUS_IS_OK(status
)) {
928 DEBUG(1, ("Error loading configuration: %s\n",
933 /* did the minimum value or rangesize change? */
934 if ((storedconfig
.minvalue
!= cfg
->minvalue
) ||
935 (storedconfig
.rangesize
!= cfg
->rangesize
))
937 DEBUG(1, ("New configuration values for rangesize or "
938 "minimum uid value conflict with previously "
939 "used values! Not storing new config.\n"));
940 status
= NT_STATUS_INVALID_PARAMETER
;
944 status
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
945 if (!NT_STATUS_IS_OK(status
)) {
946 DEBUG(1, ("Fatal error while fetching current "
947 "HWM value: %s\n", nt_errstr(status
)));
948 status
= NT_STATUS_INTERNAL_ERROR
;
953 * has the highest uid value been reduced to setting that is not
954 * sufficient any more for already existing ranges?
956 if (hwm
> cfg
->maxranges
) {
957 DEBUG(1, ("New upper uid limit is too low to cover "
958 "existing mappings! Not storing new config.\n"));
959 status
= NT_STATUS_INVALID_PARAMETER
;
964 talloc_asprintf(frame
,
965 "minvalue:%u rangesize:%u maxranges:%u",
966 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
);
968 if (cfgstr
== NULL
) {
969 status
= NT_STATUS_NO_MEMORY
;
973 data
= string_tdb_data(cfgstr
);
975 status
= dbwrap_trans_store_bystring(db
, CONFIGKEY
, data
, TDB_REPLACE
);
982 NTSTATUS
idmap_autorid_saveconfigstr(struct db_context
*db
,
983 const char *configstr
)
987 struct autorid_global_config cfg
;
989 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
991 return NT_STATUS_INVALID_PARAMETER
;
994 status
= idmap_autorid_saveconfig(db
, &cfg
);
1000 * iteration: Work on all range mappings for a given domain
1003 struct domain_range_visitor_ctx
{
1005 NTSTATUS (*fn
)(struct db_context
*db
,
1009 void *private_data
);
1011 int count
; /* number of records worked on */
1014 static int idmap_autorid_visit_domain_range(struct db_record
*rec
,
1017 struct domain_range_visitor_ctx
*vi
;
1020 uint32_t range_index
= 0;
1021 uint32_t rangenum
= 0;
1022 TDB_DATA key
, value
;
1025 struct db_context
*db
;
1027 vi
= talloc_get_type_abort(private_data
,
1028 struct domain_range_visitor_ctx
);
1030 key
= dbwrap_record_get_key(rec
);
1033 * split string "<sid>[#<index>]" into sid string and index number
1036 domsid
= (char *)key
.dptr
;
1038 DEBUG(10, ("idmap_autorid_visit_domain_range: visiting key '%s'\n",
1041 sep
= strrchr(domsid
, '#');
1046 if (sscanf(index_str
, "%"SCNu32
, &range_index
) != 1) {
1047 DEBUG(10, ("Found separator '#' but '%s' is not a "
1048 "valid range index. Skipping record\n",
1054 if (!idmap_autorid_validate_sid(domsid
)) {
1055 DEBUG(10, ("String '%s' is not a valid sid. "
1056 "Skipping record.\n", domsid
));
1060 if ((vi
->domsid
!= NULL
) && (strcmp(domsid
, vi
->domsid
) != 0)) {
1061 DEBUG(10, ("key sid '%s' does not match requested sid '%s'.\n",
1062 domsid
, vi
->domsid
));
1066 value
= dbwrap_record_get_value(rec
);
1068 if (value
.dsize
!= sizeof(uint32_t)) {
1069 /* it might be a mapping of a well known sid */
1070 DEBUG(10, ("value size %u != sizeof(uint32_t) for sid '%s', "
1071 "skipping.\n", (unsigned)value
.dsize
, vi
->domsid
));
1075 rangenum
= IVAL(value
.dptr
, 0);
1077 db
= dbwrap_record_get_db(rec
);
1079 status
= vi
->fn(db
, domsid
, range_index
, rangenum
, vi
->private_data
);
1080 if (!NT_STATUS_IS_OK(status
)) {
1092 static NTSTATUS
idmap_autorid_iterate_domain_ranges_int(struct db_context
*db
,
1094 NTSTATUS (*fn
)(struct db_context
*db
,
1098 void *private_data
),
1101 NTSTATUS (*traverse
)(struct db_context
*db
,
1102 int (*f
)(struct db_record
*, void *),
1107 struct domain_range_visitor_ctx
*vi
;
1108 TALLOC_CTX
*frame
= talloc_stackframe();
1110 if (domsid
== NULL
) {
1111 DEBUG(10, ("No sid provided, operating on all ranges\n"));
1115 DEBUG(1, ("Error: missing visitor callback\n"));
1116 status
= NT_STATUS_INVALID_PARAMETER
;
1120 vi
= talloc_zero(frame
, struct domain_range_visitor_ctx
);
1122 status
= NT_STATUS_NO_MEMORY
;
1126 vi
->domsid
= domsid
;
1128 vi
->private_data
= private_data
;
1130 status
= traverse(db
, idmap_autorid_visit_domain_range
, vi
, NULL
);
1131 if (!NT_STATUS_IS_OK(status
)) {
1135 if (count
!= NULL
) {
1144 NTSTATUS
idmap_autorid_iterate_domain_ranges(struct db_context
*db
,
1146 NTSTATUS (*fn
)(struct db_context
*db
,
1150 void *private_data
),
1156 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1167 NTSTATUS
idmap_autorid_iterate_domain_ranges_read(struct db_context
*db
,
1169 NTSTATUS (*fn
)(struct db_context
*db
,
1179 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1184 dbwrap_traverse_read
);
1191 * Delete all ranges configured for a given domain
1194 struct delete_domain_ranges_visitor_ctx
{
1198 static NTSTATUS
idmap_autorid_delete_domain_ranges_visitor(
1199 struct db_context
*db
,
1201 uint32_t domain_range_index
,
1205 struct delete_domain_ranges_visitor_ctx
*ctx
;
1208 ctx
= (struct delete_domain_ranges_visitor_ctx
*)private_data
;
1210 status
= idmap_autorid_delete_range_by_sid(
1211 db
, domsid
, domain_range_index
, ctx
->force
);
1215 struct idmap_autorid_delete_domain_ranges_ctx
{
1218 int count
; /* output: count records operated on */
1221 static NTSTATUS
idmap_autorid_delete_domain_ranges_action(struct db_context
*db
,
1224 struct idmap_autorid_delete_domain_ranges_ctx
*ctx
;
1225 struct delete_domain_ranges_visitor_ctx visitor_ctx
;
1229 ctx
= (struct idmap_autorid_delete_domain_ranges_ctx
*)private_data
;
1231 ZERO_STRUCT(visitor_ctx
);
1232 visitor_ctx
.force
= ctx
->force
;
1234 status
= idmap_autorid_iterate_domain_ranges(db
,
1236 idmap_autorid_delete_domain_ranges_visitor
,
1239 if (!NT_STATUS_IS_OK(status
)) {
1245 return NT_STATUS_OK
;
1248 NTSTATUS
idmap_autorid_delete_domain_ranges(struct db_context
*db
,
1254 struct idmap_autorid_delete_domain_ranges_ctx ctx
;
1257 ctx
.domsid
= domsid
;
1260 status
= dbwrap_trans_do(db
, idmap_autorid_delete_domain_ranges_action
,
1262 if (!NT_STATUS_IS_OK(status
)) {
1268 return NT_STATUS_OK
;