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"
30 * Build the database keystring for getting a range
31 * belonging to a domain sid and a range index.
33 static void idmap_autorid_build_keystr(const char *domsid
,
34 uint32_t domain_range_index
,
37 if (domain_range_index
> 0) {
38 fstr_sprintf(keystr
, "%s#%"PRIu32
,
39 domsid
, domain_range_index
);
41 fstrcpy(keystr
, domsid
);
45 static char *idmap_autorid_build_keystr_talloc(TALLOC_CTX
*mem_ctx
,
47 uint32_t domain_range_index
)
51 if (domain_range_index
> 0) {
52 keystr
= talloc_asprintf(mem_ctx
, "%s#%"PRIu32
, domsid
,
55 keystr
= talloc_strdup(mem_ctx
, domsid
);
62 static bool idmap_autorid_validate_sid(const char *sid
)
64 struct dom_sid ignore
;
69 if (strcmp(sid
, ALLOC_RANGE
) == 0) {
73 return dom_sid_parse(sid
, &ignore
);
76 struct idmap_autorid_addrange_ctx
{
77 struct autorid_range_config
*range
;
81 static NTSTATUS
idmap_autorid_addrange_action(struct db_context
*db
,
84 struct idmap_autorid_addrange_ctx
*ctx
;
85 uint32_t requested_rangenum
, stored_rangenum
;
86 struct autorid_range_config
*range
;
91 struct autorid_global_config
*globalcfg
;
94 TALLOC_CTX
*mem_ctx
= NULL
;
96 ctx
= (struct idmap_autorid_addrange_ctx
*)private_data
;
98 acquire
= ctx
->acquire
;
99 requested_rangenum
= range
->rangenum
;
102 DEBUG(3, ("Invalid database argument: NULL"));
103 return NT_STATUS_INVALID_PARAMETER
;
107 DEBUG(3, ("Invalid range argument: NULL"));
108 return NT_STATUS_INVALID_PARAMETER
;
111 DEBUG(10, ("Adding new range for domain %s "
112 "(domain_range_index=%"PRIu32
")\n",
113 range
->domsid
, range
->domain_range_index
));
115 if (!idmap_autorid_validate_sid(range
->domsid
)) {
116 DEBUG(3, ("Invalid SID: %s\n", range
->domsid
));
117 return NT_STATUS_INVALID_PARAMETER
;
120 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
123 ret
= dbwrap_fetch_uint32_bystring(db
, keystr
, &stored_rangenum
);
125 if (NT_STATUS_IS_OK(ret
)) {
126 /* entry is already present*/
128 DEBUG(10, ("domain range already allocated - "
133 if (stored_rangenum
!= requested_rangenum
) {
134 DEBUG(1, ("Error: requested rangenumber (%u) differs "
135 "from stored one (%u).\n",
136 requested_rangenum
, stored_rangenum
));
137 return NT_STATUS_UNSUCCESSFUL
;
140 DEBUG(10, ("Note: stored range agrees with requested "
145 /* fetch the current HWM */
146 ret
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
147 if (!NT_STATUS_IS_OK(ret
)) {
148 DEBUG(1, ("Fatal error while fetching current "
149 "HWM value: %s\n", nt_errstr(ret
)));
150 return NT_STATUS_INTERNAL_ERROR
;
153 mem_ctx
= talloc_stackframe();
155 ret
= idmap_autorid_loadconfig(db
, mem_ctx
, &globalcfg
);
156 if (!NT_STATUS_IS_OK(ret
)) {
157 DEBUG(1, ("Fatal error while fetching configuration: %s\n",
164 * automatically acquire the next range
166 requested_rangenum
= hwm
;
169 if (requested_rangenum
>= globalcfg
->maxranges
) {
170 DEBUG(1, ("Not enough ranges available: New range %u must be "
171 "smaller than configured maximum number of ranges "
173 requested_rangenum
, globalcfg
->maxranges
));
174 ret
= NT_STATUS_NO_MEMORY
;
179 * Check that it is not yet taken.
180 * If the range is requested and < HWM, we need
181 * to check anyways, and otherwise, we also better
182 * check in order to prevent further corruption
183 * in case the db has been externally modified.
186 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
188 ret
= NT_STATUS_NO_MEMORY
;
192 if (dbwrap_exists(db
, string_term_tdb_data(numstr
))) {
193 DEBUG(1, ("Requested range '%s' is already in use.\n", numstr
));
195 if (requested_rangenum
< hwm
) {
196 ret
= NT_STATUS_INVALID_PARAMETER
;
198 ret
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
204 if (requested_rangenum
>= hwm
) {
206 * requested or automatic range >= HWM:
210 /* HWM always contains current max range + 1 */
211 increment
= requested_rangenum
+ 1 - hwm
;
213 /* increase the HWM */
214 ret
= dbwrap_change_uint32_atomic_bystring(db
, HWM
, &hwm
,
216 if (!NT_STATUS_IS_OK(ret
)) {
217 DEBUG(1, ("Fatal error while incrementing the HWM "
218 "value in the database: %s\n",
225 * store away the new mapping in both directions
228 ret
= dbwrap_store_uint32_bystring(db
, keystr
, requested_rangenum
);
229 if (!NT_STATUS_IS_OK(ret
)) {
230 DEBUG(1, ("Fatal error while storing new "
231 "domain->range assignment: %s\n", nt_errstr(ret
)));
235 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
237 ret
= NT_STATUS_NO_MEMORY
;
241 ret
= dbwrap_store_bystring(db
, numstr
,
242 string_term_tdb_data(keystr
), TDB_INSERT
);
244 if (!NT_STATUS_IS_OK(ret
)) {
245 DEBUG(1, ("Fatal error while storing new "
246 "domain->range assignment: %s\n", nt_errstr(ret
)));
249 DEBUG(5, ("Acquired new range #%d for domain %s "
250 "(domain_range_index=%"PRIu32
")\n", requested_rangenum
, keystr
,
251 range
->domain_range_index
));
253 range
->rangenum
= requested_rangenum
;
255 range
->low_id
= globalcfg
->minvalue
256 + range
->rangenum
* globalcfg
->rangesize
;
261 talloc_free(mem_ctx
);
265 static NTSTATUS
idmap_autorid_addrange(struct db_context
*db
,
266 struct autorid_range_config
*range
,
270 struct idmap_autorid_addrange_ctx ctx
;
272 ctx
.acquire
= acquire
;
275 status
= dbwrap_trans_do(db
, idmap_autorid_addrange_action
, &ctx
);
279 NTSTATUS
idmap_autorid_setrange(struct db_context
*db
,
281 uint32_t domain_range_index
,
285 struct autorid_range_config range
;
288 fstrcpy(range
.domsid
, domsid
);
289 range
.domain_range_index
= domain_range_index
;
290 range
.rangenum
= rangenum
;
292 status
= idmap_autorid_addrange(db
, &range
, false);
296 static NTSTATUS
idmap_autorid_acquire_range(struct db_context
*db
,
297 struct autorid_range_config
*range
)
299 return idmap_autorid_addrange(db
, range
, true);
302 static NTSTATUS
idmap_autorid_getrange_int(struct db_context
*db
,
303 struct autorid_range_config
*range
)
305 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
306 struct autorid_global_config
*globalcfg
= NULL
;
309 if (db
== NULL
|| range
== NULL
) {
310 DEBUG(3, ("Invalid arguments received\n"));
314 if (!idmap_autorid_validate_sid(range
->domsid
)) {
315 DEBUG(3, ("Invalid SID: '%s'\n", range
->domsid
));
316 status
= NT_STATUS_INVALID_PARAMETER
;
320 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
323 DEBUG(10, ("reading domain range for key %s\n", keystr
));
324 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &(range
->rangenum
));
325 if (!NT_STATUS_IS_OK(status
)) {
326 DEBUG(1, ("Failed to read database for key '%s': %s\n",
327 keystr
, nt_errstr(status
)));
331 status
= idmap_autorid_loadconfig(db
, talloc_tos(), &globalcfg
);
332 if (!NT_STATUS_IS_OK(status
)) {
333 DEBUG(1, ("Failed to read global configuration"));
336 range
->low_id
= globalcfg
->minvalue
337 + range
->rangenum
* globalcfg
->rangesize
;
339 TALLOC_FREE(globalcfg
);
344 NTSTATUS
idmap_autorid_getrange(struct db_context
*db
,
346 uint32_t domain_range_index
,
351 struct autorid_range_config range
;
353 if (rangenum
== NULL
) {
354 return NT_STATUS_INVALID_PARAMETER
;
358 fstrcpy(range
.domsid
, domsid
);
359 range
.domain_range_index
= domain_range_index
;
361 status
= idmap_autorid_getrange_int(db
, &range
);
362 if (!NT_STATUS_IS_OK(status
)) {
366 *rangenum
= range
.rangenum
;
368 if (low_id
!= NULL
) {
369 *low_id
= range
.low_id
;
375 NTSTATUS
idmap_autorid_get_domainrange(struct db_context
*db
,
376 struct autorid_range_config
*range
,
381 ret
= idmap_autorid_getrange_int(db
, range
);
382 if (!NT_STATUS_IS_OK(ret
)) {
384 return NT_STATUS_NOT_FOUND
;
387 ret
= idmap_autorid_acquire_range(db
, range
);
390 DEBUG(10, ("Using range #%d for domain %s "
391 "(domain_range_index=%"PRIu32
", low_id=%"PRIu32
")\n",
392 range
->rangenum
, range
->domsid
, range
->domain_range_index
,
398 /* initialize the given HWM to 0 if it does not exist yet */
399 static NTSTATUS
idmap_autorid_init_hwm_action(struct db_context
*db
,
406 hwm
= (char *)private_data
;
408 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
409 if (NT_STATUS_IS_OK(status
)) {
410 DEBUG(1, ("HWM (%s) already initialized in autorid database "
411 "(value %"PRIu32
").\n", hwm
, hwmval
));
414 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
415 DEBUG(0, ("Error fetching HWM (%s) from autorid "
416 "database: %s\n", hwm
, nt_errstr(status
)));
420 status
= dbwrap_trans_store_uint32_bystring(db
, hwm
, 0);
421 if (!NT_STATUS_IS_OK(status
)) {
422 DEBUG(0, ("Error storing HWM (%s) in autorid database: %s\n",
423 hwm
, nt_errstr(status
)));
430 NTSTATUS
idmap_autorid_init_hwm(struct db_context
*db
, const char *hwm
)
435 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
436 if (NT_STATUS_IS_OK(status
)) {
437 DEBUG(1, ("HWM (%s) already initialized in autorid database "
438 "(value %"PRIu32
").\n", hwm
, hwmval
));
441 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
442 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
443 "database: %s\n", hwm
, nt_errstr(status
)));
447 status
= dbwrap_trans_do(db
, idmap_autorid_init_hwm_action
,
449 if (!NT_STATUS_IS_OK(status
)) {
450 DEBUG(0, ("Error initializing HWM (%s) in autorid database: "
451 "%s\n", hwm
, nt_errstr(status
)));
452 return NT_STATUS_INTERNAL_DB_ERROR
;
455 DEBUG(1, ("Initialized HWM (%s) in autorid database.\n", hwm
));
461 * Delete a domain#index <-> range mapping from the database.
462 * The mapping is specified by the sid and index.
463 * If force == true, invalid mapping records are deleted as far
464 * as possible, otherwise they are left untouched.
467 struct idmap_autorid_delete_range_by_sid_ctx
{
469 uint32_t domain_range_index
;
473 static NTSTATUS
idmap_autorid_delete_range_by_sid_action(struct db_context
*db
,
476 struct idmap_autorid_delete_range_by_sid_ctx
*ctx
=
477 (struct idmap_autorid_delete_range_by_sid_ctx
*)private_data
;
479 uint32_t domain_range_index
;
485 TALLOC_CTX
*frame
= talloc_stackframe();
486 bool is_valid_range_mapping
= true;
489 domsid
= ctx
->domsid
;
490 domain_range_index
= ctx
->domain_range_index
;
493 keystr
= idmap_autorid_build_keystr_talloc(frame
, domsid
,
495 if (keystr
== NULL
) {
496 status
= NT_STATUS_NO_MEMORY
;
500 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &rangenum
);
501 if (!NT_STATUS_IS_OK(status
)) {
505 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
506 if (range_keystr
== NULL
) {
507 status
= NT_STATUS_NO_MEMORY
;
511 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &data
);
512 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
513 DEBUG(1, ("Incomplete mapping %s -> %s: no backward mapping\n",
514 keystr
, range_keystr
));
515 is_valid_range_mapping
= false;
516 } else if (!NT_STATUS_IS_OK(status
)) {
517 DEBUG(1, ("Error fetching reverse mapping for %s -> %s: %s\n",
518 keystr
, range_keystr
, nt_errstr(status
)));
520 } else if (strncmp((const char *)data
.dptr
, keystr
, strlen(keystr
))
523 DEBUG(1, ("Invalid mapping: %s -> %s -> %s\n",
524 keystr
, range_keystr
, (const char *)data
.dptr
));
525 is_valid_range_mapping
= false;
528 if (!is_valid_range_mapping
&& !force
) {
529 DEBUG(10, ("Not deleting invalid mapping, since not in force "
531 status
= NT_STATUS_FILE_INVALID
;
535 status
= dbwrap_delete_bystring(db
, keystr
);
536 if (!NT_STATUS_IS_OK(status
)) {
537 DEBUG(1, ("Deletion of '%s' failed: %s\n",
538 keystr
, nt_errstr(status
)));
542 if (!is_valid_range_mapping
) {
546 status
= dbwrap_delete_bystring(db
, range_keystr
);
547 if (!NT_STATUS_IS_OK(status
)) {
548 DEBUG(1, ("Deletion of '%s' failed: %s\n",
549 range_keystr
, nt_errstr(status
)));
553 DEBUG(10, ("Deleted range mapping %s <--> %s\n", keystr
,
561 NTSTATUS
idmap_autorid_delete_range_by_sid(struct db_context
*db
,
563 uint32_t domain_range_index
,
567 struct idmap_autorid_delete_range_by_sid_ctx ctx
;
569 ctx
.domain_range_index
= domain_range_index
;
573 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_sid_action
,
579 * Delete a domain#index <-> range mapping from the database.
580 * The mapping is specified by the range number.
581 * If force == true, invalid mapping records are deleted as far
582 * as possible, otherwise they are left untouched.
584 struct idmap_autorid_delete_range_by_num_ctx
{
589 static NTSTATUS
idmap_autorid_delete_range_by_num_action(struct db_context
*db
,
592 struct idmap_autorid_delete_range_by_num_ctx
*ctx
=
593 (struct idmap_autorid_delete_range_by_num_ctx
*)private_data
;
599 TALLOC_CTX
*frame
= talloc_stackframe();
600 bool is_valid_range_mapping
= true;
603 rangenum
= ctx
->rangenum
;
606 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
607 if (range_keystr
== NULL
) {
608 status
= NT_STATUS_NO_MEMORY
;
614 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &val
);
615 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
616 DEBUG(10, ("Did not find range '%s' in database.\n",
619 } else if (!NT_STATUS_IS_OK(status
)) {
620 DEBUG(5, ("Error fetching rang key: %s\n", nt_errstr(status
)));
624 if (val
.dptr
== NULL
) {
625 DEBUG(1, ("Invalid mapping: %s -> empty value\n",
627 is_valid_range_mapping
= false;
629 uint32_t reverse_rangenum
= 0;
631 keystr
= (char *)val
.dptr
;
633 status
= dbwrap_fetch_uint32_bystring(db
, keystr
,
635 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
636 DEBUG(1, ("Incomplete mapping %s -> %s: "
637 "no backward mapping\n",
638 range_keystr
, keystr
));
639 is_valid_range_mapping
= false;
640 } else if (!NT_STATUS_IS_OK(status
)) {
641 DEBUG(1, ("Error fetching reverse mapping for "
643 range_keystr
, keystr
, nt_errstr(status
)));
645 } else if (rangenum
!= reverse_rangenum
) {
646 is_valid_range_mapping
= false;
650 if (!is_valid_range_mapping
&& !force
) {
651 DEBUG(10, ("Not deleting invalid mapping, since not in force "
653 status
= NT_STATUS_FILE_INVALID
;
657 status
= dbwrap_delete_bystring(db
, range_keystr
);
658 if (!NT_STATUS_IS_OK(status
)) {
659 DEBUG(1, ("Deletion of '%s' failed: %s\n",
660 range_keystr
, nt_errstr(status
)));
664 if (!is_valid_range_mapping
) {
668 status
= dbwrap_delete_bystring(db
, keystr
);
669 if (!NT_STATUS_IS_OK(status
)) {
670 DEBUG(1, ("Deletion of '%s' failed: %s\n",
671 keystr
, nt_errstr(status
)));
675 DEBUG(10, ("Deleted range mapping %s <--> %s\n", range_keystr
,
683 NTSTATUS
idmap_autorid_delete_range_by_num(struct db_context
*db
,
688 struct idmap_autorid_delete_range_by_num_ctx ctx
;
690 ctx
.rangenum
= rangenum
;
693 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_num_action
,
699 * open and initialize the database which stores the ranges for the domains
701 NTSTATUS
idmap_autorid_db_init(const char *path
,
703 struct db_context
**db
)
708 /* its already open */
712 /* Open idmap repository */
713 *db
= db_open(mem_ctx
, path
, 0, TDB_DEFAULT
, O_RDWR
| O_CREAT
, 0644,
714 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
717 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path
));
718 return NT_STATUS_UNSUCCESSFUL
;
721 /* Initialize high water mark for the currently used range to 0 */
723 status
= idmap_autorid_init_hwm(*db
, HWM
);
724 NT_STATUS_NOT_OK_RETURN(status
);
726 status
= idmap_autorid_init_hwm(*db
, ALLOC_HWM_UID
);
727 NT_STATUS_NOT_OK_RETURN(status
);
729 status
= idmap_autorid_init_hwm(*db
, ALLOC_HWM_GID
);
734 struct idmap_autorid_fetch_config_state
{
739 static void idmap_autorid_config_parser(TDB_DATA key
, TDB_DATA value
,
742 struct idmap_autorid_fetch_config_state
*state
;
744 state
= (struct idmap_autorid_fetch_config_state
*)private_data
;
747 * strndup because we have non-nullterminated strings in the db
749 state
->configstr
= talloc_strndup(
750 state
->mem_ctx
, (const char *)value
.dptr
, value
.dsize
);
753 NTSTATUS
idmap_autorid_getconfigstr(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
758 struct idmap_autorid_fetch_config_state state
;
760 if (result
== NULL
) {
761 return NT_STATUS_INVALID_PARAMETER
;
764 key
= string_term_tdb_data(CONFIGKEY
);
766 state
.mem_ctx
= mem_ctx
;
767 state
.configstr
= NULL
;
769 status
= dbwrap_parse_record(db
, key
, idmap_autorid_config_parser
,
771 if (!NT_STATUS_IS_OK(status
)) {
772 DEBUG(1, ("Error while retrieving config: %s\n",
777 if (state
.configstr
== NULL
) {
778 DEBUG(1, ("Error while retrieving config\n"));
779 return NT_STATUS_NO_MEMORY
;
782 DEBUG(5, ("found CONFIG: %s\n", state
.configstr
));
784 *result
= state
.configstr
;
788 bool idmap_autorid_parse_configstr(const char *configstr
,
789 struct autorid_global_config
*cfg
)
791 unsigned long minvalue
, rangesize
, maxranges
;
793 if (sscanf(configstr
,
794 "minvalue:%lu rangesize:%lu maxranges:%lu",
795 &minvalue
, &rangesize
, &maxranges
) != 3) {
797 ("Found invalid configuration data. "
798 "Creating new config\n"));
802 cfg
->minvalue
= minvalue
;
803 cfg
->rangesize
= rangesize
;
804 cfg
->maxranges
= maxranges
;
809 NTSTATUS
idmap_autorid_loadconfig(struct db_context
*db
,
811 struct autorid_global_config
**result
)
813 struct autorid_global_config
*cfg
;
816 char *configstr
= NULL
;
818 if (result
== NULL
) {
819 return NT_STATUS_INVALID_PARAMETER
;
822 status
= idmap_autorid_getconfigstr(db
, mem_ctx
, &configstr
);
823 if (!NT_STATUS_IS_OK(status
)) {
827 cfg
= talloc_zero(mem_ctx
, struct autorid_global_config
);
829 return NT_STATUS_NO_MEMORY
;
832 ok
= idmap_autorid_parse_configstr(configstr
, cfg
);
835 return NT_STATUS_INVALID_PARAMETER
;
838 DEBUG(10, ("Loaded previously stored configuration "
839 "minvalue:%d rangesize:%d\n",
840 cfg
->minvalue
, cfg
->rangesize
));
847 NTSTATUS
idmap_autorid_saveconfig(struct db_context
*db
,
848 struct autorid_global_config
*cfg
)
851 struct autorid_global_config
*storedconfig
= NULL
;
852 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
856 TALLOC_CTX
*frame
= talloc_stackframe();
858 DEBUG(10, ("New configuration provided for storing is "
859 "minvalue:%d rangesize:%d maxranges:%d\n",
860 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
));
862 if (cfg
->rangesize
< 2000) {
863 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
867 if (cfg
->maxranges
== 0) {
868 DEBUG(1, ("An autorid maxranges value of 0 is invalid. "
869 "Must have at least one range available.\n"));
873 status
= idmap_autorid_loadconfig(db
, frame
, &storedconfig
);
874 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
875 DEBUG(5, ("No configuration found. Storing initial "
876 "configuration.\n"));
877 } else if (!NT_STATUS_IS_OK(status
)) {
881 /* did the minimum value or rangesize change? */
883 ((storedconfig
->minvalue
!= cfg
->minvalue
) ||
884 (storedconfig
->rangesize
!= cfg
->rangesize
)))
886 DEBUG(1, ("New configuration values for rangesize or "
887 "minimum uid value conflict with previously "
888 "used values! Not storing new config.\n"));
889 status
= NT_STATUS_INVALID_PARAMETER
;
893 status
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
894 if (!NT_STATUS_IS_OK(status
)) {
895 DEBUG(1, ("Fatal error while fetching current "
896 "HWM value: %s\n", nt_errstr(status
)));
897 status
= NT_STATUS_INTERNAL_ERROR
;
902 * has the highest uid value been reduced to setting that is not
903 * sufficient any more for already existing ranges?
905 if (hwm
> cfg
->maxranges
) {
906 DEBUG(1, ("New upper uid limit is too low to cover "
907 "existing mappings! Not storing new config.\n"));
908 status
= NT_STATUS_INVALID_PARAMETER
;
913 talloc_asprintf(frame
,
914 "minvalue:%u rangesize:%u maxranges:%u",
915 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
);
917 if (cfgstr
== NULL
) {
918 status
= NT_STATUS_NO_MEMORY
;
922 data
= string_tdb_data(cfgstr
);
924 status
= dbwrap_trans_store_bystring(db
, CONFIGKEY
, data
, TDB_REPLACE
);
931 NTSTATUS
idmap_autorid_saveconfigstr(struct db_context
*db
,
932 const char *configstr
)
936 struct autorid_global_config cfg
;
938 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
940 return NT_STATUS_INVALID_PARAMETER
;
943 status
= idmap_autorid_saveconfig(db
, &cfg
);
949 * iteration: Work on all range mappings for a given domain
952 struct domain_range_visitor_ctx
{
954 NTSTATUS (*fn
)(struct db_context
*db
,
960 int count
; /* number of records worked on */
963 static int idmap_autorid_visit_domain_range(struct db_record
*rec
,
966 struct domain_range_visitor_ctx
*vi
;
969 uint32_t range_index
= 0;
970 uint32_t rangenum
= 0;
974 struct db_context
*db
;
976 vi
= talloc_get_type_abort(private_data
,
977 struct domain_range_visitor_ctx
);
979 key
= dbwrap_record_get_key(rec
);
982 * split string "<sid>[#<index>]" into sid string and index number
985 domsid
= (char *)key
.dptr
;
987 DEBUG(10, ("idmap_autorid_visit_domain_range: visiting key '%s'\n",
990 sep
= strrchr(domsid
, '#');
995 if (sscanf(index_str
, "%"SCNu32
, &range_index
) != 1) {
996 DEBUG(10, ("Found separator '#' but '%s' is not a "
997 "valid range index. Skipping record\n",
1003 if (!idmap_autorid_validate_sid(domsid
)) {
1004 DEBUG(10, ("String '%s' is not a valid sid. "
1005 "Skipping record.\n", domsid
));
1009 if ((vi
->domsid
!= NULL
) && (strcmp(domsid
, vi
->domsid
) != 0)) {
1010 DEBUG(10, ("key sid '%s' does not match requested sid '%s'.\n",
1011 domsid
, vi
->domsid
));
1015 value
= dbwrap_record_get_value(rec
);
1017 if (value
.dsize
!= sizeof(uint32_t)) {
1018 /* it might be a mapping of a well known sid */
1019 DEBUG(10, ("value size %u != sizeof(uint32_t) for sid '%s', "
1020 "skipping.\n", (unsigned)value
.dsize
, vi
->domsid
));
1024 rangenum
= IVAL(value
.dptr
, 0);
1026 db
= dbwrap_record_get_db(rec
);
1028 status
= vi
->fn(db
, domsid
, range_index
, rangenum
, vi
->private_data
);
1029 if (!NT_STATUS_IS_OK(status
)) {
1041 static NTSTATUS
idmap_autorid_iterate_domain_ranges_int(struct db_context
*db
,
1043 NTSTATUS (*fn
)(struct db_context
*db
,
1047 void *private_data
),
1050 NTSTATUS (*traverse
)(struct db_context
*db
,
1051 int (*f
)(struct db_record
*, void *),
1056 struct domain_range_visitor_ctx
*vi
;
1057 TALLOC_CTX
*frame
= talloc_stackframe();
1059 if (domsid
== NULL
) {
1060 DEBUG(10, ("No sid provided, operating on all ranges\n"));
1064 DEBUG(1, ("Error: missing visitor callback\n"));
1065 status
= NT_STATUS_INVALID_PARAMETER
;
1069 vi
= talloc_zero(frame
, struct domain_range_visitor_ctx
);
1071 status
= NT_STATUS_NO_MEMORY
;
1075 vi
->domsid
= domsid
;
1077 vi
->private_data
= private_data
;
1079 status
= traverse(db
, idmap_autorid_visit_domain_range
, vi
, NULL
);
1080 if (!NT_STATUS_IS_OK(status
)) {
1084 if (count
!= NULL
) {
1093 NTSTATUS
idmap_autorid_iterate_domain_ranges(struct db_context
*db
,
1095 NTSTATUS (*fn
)(struct db_context
*db
,
1099 void *private_data
),
1105 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1116 NTSTATUS
idmap_autorid_iterate_domain_ranges_read(struct db_context
*db
,
1118 NTSTATUS (*fn
)(struct db_context
*db
,
1128 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1133 dbwrap_traverse_read
);
1140 * Delete all ranges configured for a given domain
1143 struct delete_domain_ranges_visitor_ctx
{
1147 static NTSTATUS
idmap_autorid_delete_domain_ranges_visitor(
1148 struct db_context
*db
,
1150 uint32_t domain_range_index
,
1154 struct delete_domain_ranges_visitor_ctx
*ctx
;
1157 ctx
= (struct delete_domain_ranges_visitor_ctx
*)private_data
;
1159 status
= idmap_autorid_delete_range_by_sid(
1160 db
, domsid
, domain_range_index
, ctx
->force
);
1164 struct idmap_autorid_delete_domain_ranges_ctx
{
1167 int count
; /* output: count records operated on */
1170 static NTSTATUS
idmap_autorid_delete_domain_ranges_action(struct db_context
*db
,
1173 struct idmap_autorid_delete_domain_ranges_ctx
*ctx
;
1174 struct delete_domain_ranges_visitor_ctx visitor_ctx
;
1178 ctx
= (struct idmap_autorid_delete_domain_ranges_ctx
*)private_data
;
1180 ZERO_STRUCT(visitor_ctx
);
1181 visitor_ctx
.force
= ctx
->force
;
1183 status
= idmap_autorid_iterate_domain_ranges(db
,
1185 idmap_autorid_delete_domain_ranges_visitor
,
1188 if (!NT_STATUS_IS_OK(status
)) {
1194 return NT_STATUS_OK
;
1197 NTSTATUS
idmap_autorid_delete_domain_ranges(struct db_context
*db
,
1203 struct idmap_autorid_delete_domain_ranges_ctx ctx
;
1206 ctx
.domsid
= domsid
;
1209 status
= dbwrap_trans_do(db
, idmap_autorid_delete_domain_ranges_action
,
1211 if (!NT_STATUS_IS_OK(status
)) {
1217 return NT_STATUS_OK
;