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
= {0};
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 - "
131 ret
= idmap_autorid_loadconfig(db
, &globalcfg
);
132 if (!NT_STATUS_IS_OK(ret
)) {
133 DEBUG(1, ("Fatal error while fetching "
134 "configuration: %s\n",
139 range
->rangenum
= stored_rangenum
;
140 range
->low_id
= globalcfg
.minvalue
141 + range
->rangenum
* globalcfg
.rangesize
;
143 range
->low_id
+ globalcfg
.rangesize
- 1;
148 if (stored_rangenum
!= requested_rangenum
) {
149 DEBUG(1, ("Error: requested rangenumber (%u) differs "
150 "from stored one (%u).\n",
151 requested_rangenum
, stored_rangenum
));
152 return NT_STATUS_UNSUCCESSFUL
;
155 DEBUG(10, ("Note: stored range agrees with requested "
160 /* fetch the current HWM */
161 ret
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
162 if (!NT_STATUS_IS_OK(ret
)) {
163 DEBUG(1, ("Fatal error while fetching current "
164 "HWM value: %s\n", nt_errstr(ret
)));
165 return NT_STATUS_INTERNAL_ERROR
;
168 mem_ctx
= talloc_stackframe();
170 ret
= idmap_autorid_loadconfig(db
, &globalcfg
);
171 if (!NT_STATUS_IS_OK(ret
)) {
172 DEBUG(1, ("Fatal error while fetching configuration: %s\n",
179 * automatically acquire the next range
181 requested_rangenum
= hwm
;
184 if (requested_rangenum
>= globalcfg
.maxranges
) {
185 DEBUG(1, ("Not enough ranges available: New range %u must be "
186 "smaller than configured maximum number of ranges "
188 requested_rangenum
, globalcfg
.maxranges
));
189 ret
= NT_STATUS_NO_MEMORY
;
194 * Check that it is not yet taken.
195 * If the range is requested and < HWM, we need
196 * to check anyways, and otherwise, we also better
197 * check in order to prevent further corruption
198 * in case the db has been externally modified.
201 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
203 DEBUG(1, ("Talloc failed!\n"));
204 ret
= NT_STATUS_NO_MEMORY
;
208 if (dbwrap_exists(db
, string_term_tdb_data(numstr
))) {
209 DEBUG(1, ("Requested range '%s' is already in use.\n", numstr
));
211 if (requested_rangenum
< hwm
) {
212 ret
= NT_STATUS_INVALID_PARAMETER
;
214 ret
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
220 if (requested_rangenum
>= hwm
) {
222 * requested or automatic range >= HWM:
226 /* HWM always contains current max range + 1 */
227 increment
= requested_rangenum
+ 1 - hwm
;
229 /* increase the HWM */
230 ret
= dbwrap_change_uint32_atomic_bystring(db
, HWM
, &hwm
,
232 if (!NT_STATUS_IS_OK(ret
)) {
233 DEBUG(1, ("Fatal error while incrementing the HWM "
234 "value in the database: %s\n",
241 * store away the new mapping in both directions
244 ret
= dbwrap_store_uint32_bystring(db
, keystr
, requested_rangenum
);
245 if (!NT_STATUS_IS_OK(ret
)) {
246 DEBUG(1, ("Fatal error while storing new "
247 "domain->range assignment: %s\n", nt_errstr(ret
)));
251 numstr
= talloc_asprintf(mem_ctx
, "%u", requested_rangenum
);
253 ret
= NT_STATUS_NO_MEMORY
;
257 ret
= dbwrap_store_bystring(db
, numstr
,
258 string_term_tdb_data(keystr
), TDB_INSERT
);
260 if (!NT_STATUS_IS_OK(ret
)) {
261 DEBUG(1, ("Fatal error while storing new "
262 "domain->range assignment: %s\n", nt_errstr(ret
)));
266 DEBUG(5, ("%s new range #%d for domain %s "
267 "(domain_range_index=%"PRIu32
")\n",
268 (acquire
?"Acquired":"Stored"),
269 requested_rangenum
, keystr
,
270 range
->domain_range_index
));
272 range
->rangenum
= requested_rangenum
;
274 range
->low_id
= globalcfg
.minvalue
275 + range
->rangenum
* globalcfg
.rangesize
;
276 range
->high_id
= range
->low_id
+ globalcfg
.rangesize
- 1;
281 talloc_free(mem_ctx
);
285 static NTSTATUS
idmap_autorid_addrange(struct db_context
*db
,
286 struct autorid_range_config
*range
,
290 struct idmap_autorid_addrange_ctx ctx
;
292 ctx
.acquire
= acquire
;
295 status
= dbwrap_trans_do(db
, idmap_autorid_addrange_action
, &ctx
);
299 NTSTATUS
idmap_autorid_setrange(struct db_context
*db
,
301 uint32_t domain_range_index
,
305 struct autorid_range_config range
;
308 fstrcpy(range
.domsid
, domsid
);
309 range
.domain_range_index
= domain_range_index
;
310 range
.rangenum
= rangenum
;
312 status
= idmap_autorid_addrange(db
, &range
, false);
316 NTSTATUS
idmap_autorid_acquire_range(struct db_context
*db
,
317 struct autorid_range_config
*range
)
319 return idmap_autorid_addrange(db
, range
, true);
322 static NTSTATUS
idmap_autorid_getrange_int(struct db_context
*db
,
323 struct autorid_range_config
*range
)
325 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
326 struct autorid_global_config globalcfg
= {0};
329 if (db
== NULL
|| range
== NULL
) {
330 DEBUG(3, ("Invalid arguments received\n"));
334 if (!idmap_autorid_validate_sid(range
->domsid
)) {
335 DEBUG(3, ("Invalid SID: '%s'\n", range
->domsid
));
336 status
= NT_STATUS_INVALID_PARAMETER
;
340 idmap_autorid_build_keystr(range
->domsid
, range
->domain_range_index
,
343 DEBUG(10, ("reading domain range for key %s\n", keystr
));
344 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &(range
->rangenum
));
345 if (!NT_STATUS_IS_OK(status
)) {
346 DEBUG(1, ("Failed to read database record for key '%s': %s\n",
347 keystr
, nt_errstr(status
)));
351 status
= idmap_autorid_loadconfig(db
, &globalcfg
);
352 if (!NT_STATUS_IS_OK(status
)) {
353 DEBUG(1, ("Failed to read global configuration"));
356 range
->low_id
= globalcfg
.minvalue
357 + range
->rangenum
* globalcfg
.rangesize
;
358 range
->high_id
= range
->low_id
+ globalcfg
.rangesize
- 1;
363 NTSTATUS
idmap_autorid_getrange(struct db_context
*db
,
365 uint32_t domain_range_index
,
370 struct autorid_range_config range
;
372 if (rangenum
== NULL
) {
373 return NT_STATUS_INVALID_PARAMETER
;
377 fstrcpy(range
.domsid
, domsid
);
378 range
.domain_range_index
= domain_range_index
;
380 status
= idmap_autorid_getrange_int(db
, &range
);
381 if (!NT_STATUS_IS_OK(status
)) {
385 *rangenum
= range
.rangenum
;
387 if (low_id
!= NULL
) {
388 *low_id
= range
.low_id
;
394 NTSTATUS
idmap_autorid_get_domainrange(struct db_context
*db
,
395 struct autorid_range_config
*range
,
400 ret
= idmap_autorid_getrange_int(db
, range
);
401 if (!NT_STATUS_IS_OK(ret
)) {
402 DEBUG(10, ("Failed to read range config for '%s': %s\n",
403 range
->domsid
, nt_errstr(ret
)));
405 DEBUG(10, ("Not allocating new range for '%s' because "
406 "read-only is enabled.\n", range
->domsid
));
407 return NT_STATUS_NOT_FOUND
;
410 ret
= idmap_autorid_acquire_range(db
, range
);
413 DEBUG(10, ("Using range #%d for domain %s "
414 "(domain_range_index=%"PRIu32
", low_id=%"PRIu32
")\n",
415 range
->rangenum
, range
->domsid
, range
->domain_range_index
,
421 /* initialize the given HWM to 0 if it does not exist yet */
422 static NTSTATUS
idmap_autorid_init_hwm_action(struct db_context
*db
,
429 hwm
= (char *)private_data
;
431 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
432 if (NT_STATUS_IS_OK(status
)) {
433 DEBUG(1, ("HWM (%s) already initialized in autorid database "
434 "(value %"PRIu32
").\n", hwm
, hwmval
));
437 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
438 DEBUG(0, ("Error fetching HWM (%s) from autorid "
439 "database: %s\n", hwm
, nt_errstr(status
)));
443 status
= dbwrap_trans_store_uint32_bystring(db
, hwm
, 0);
444 if (!NT_STATUS_IS_OK(status
)) {
445 DEBUG(0, ("Error storing HWM (%s) in autorid database: %s\n",
446 hwm
, nt_errstr(status
)));
453 NTSTATUS
idmap_autorid_init_hwm(struct db_context
*db
, const char *hwm
)
458 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
459 if (NT_STATUS_IS_OK(status
)) {
460 DEBUG(1, ("HWM (%s) already initialized in autorid database "
461 "(value %"PRIu32
").\n", hwm
, hwmval
));
464 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
465 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
466 "database: %s\n", hwm
, nt_errstr(status
)));
470 status
= dbwrap_trans_do(db
, idmap_autorid_init_hwm_action
,
472 if (!NT_STATUS_IS_OK(status
)) {
473 DEBUG(0, ("Error initializing HWM (%s) in autorid database: "
474 "%s\n", hwm
, nt_errstr(status
)));
475 return NT_STATUS_INTERNAL_DB_ERROR
;
478 DEBUG(1, ("Initialized HWM (%s) in autorid database.\n", hwm
));
484 * Delete a domain#index <-> range mapping from the database.
485 * The mapping is specified by the sid and index.
486 * If force == true, invalid mapping records are deleted as far
487 * as possible, otherwise they are left untouched.
490 struct idmap_autorid_delete_range_by_sid_ctx
{
492 uint32_t domain_range_index
;
496 static NTSTATUS
idmap_autorid_delete_range_by_sid_action(struct db_context
*db
,
499 struct idmap_autorid_delete_range_by_sid_ctx
*ctx
=
500 (struct idmap_autorid_delete_range_by_sid_ctx
*)private_data
;
502 uint32_t domain_range_index
;
508 TALLOC_CTX
*frame
= talloc_stackframe();
509 bool is_valid_range_mapping
= true;
512 domsid
= ctx
->domsid
;
513 domain_range_index
= ctx
->domain_range_index
;
516 keystr
= idmap_autorid_build_keystr_talloc(frame
, domsid
,
518 if (keystr
== NULL
) {
519 status
= NT_STATUS_NO_MEMORY
;
523 status
= dbwrap_fetch_uint32_bystring(db
, keystr
, &rangenum
);
524 if (!NT_STATUS_IS_OK(status
)) {
528 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
529 if (range_keystr
== NULL
) {
530 status
= NT_STATUS_NO_MEMORY
;
534 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &data
);
535 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
536 DEBUG(1, ("Incomplete mapping %s -> %s: no backward mapping\n",
537 keystr
, range_keystr
));
538 is_valid_range_mapping
= false;
539 } else if (!NT_STATUS_IS_OK(status
)) {
540 DEBUG(1, ("Error fetching reverse mapping for %s -> %s: %s\n",
541 keystr
, range_keystr
, nt_errstr(status
)));
543 } else if (strncmp((const char *)data
.dptr
, keystr
, strlen(keystr
))
546 DEBUG(1, ("Invalid mapping: %s -> %s -> %s\n",
547 keystr
, range_keystr
, (const char *)data
.dptr
));
548 is_valid_range_mapping
= false;
551 if (!is_valid_range_mapping
&& !force
) {
552 DEBUG(10, ("Not deleting invalid mapping, since not in force "
554 status
= NT_STATUS_FILE_INVALID
;
558 status
= dbwrap_delete_bystring(db
, keystr
);
559 if (!NT_STATUS_IS_OK(status
)) {
560 DEBUG(1, ("Deletion of '%s' failed: %s\n",
561 keystr
, nt_errstr(status
)));
565 if (!is_valid_range_mapping
) {
569 status
= dbwrap_delete_bystring(db
, range_keystr
);
570 if (!NT_STATUS_IS_OK(status
)) {
571 DEBUG(1, ("Deletion of '%s' failed: %s\n",
572 range_keystr
, nt_errstr(status
)));
576 DEBUG(10, ("Deleted range mapping %s <--> %s\n", keystr
,
584 NTSTATUS
idmap_autorid_delete_range_by_sid(struct db_context
*db
,
586 uint32_t domain_range_index
,
590 struct idmap_autorid_delete_range_by_sid_ctx ctx
;
592 ctx
.domain_range_index
= domain_range_index
;
596 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_sid_action
,
602 * Delete a domain#index <-> range mapping from the database.
603 * The mapping is specified by the range number.
604 * If force == true, invalid mapping records are deleted as far
605 * as possible, otherwise they are left untouched.
607 struct idmap_autorid_delete_range_by_num_ctx
{
612 static NTSTATUS
idmap_autorid_delete_range_by_num_action(struct db_context
*db
,
615 struct idmap_autorid_delete_range_by_num_ctx
*ctx
=
616 (struct idmap_autorid_delete_range_by_num_ctx
*)private_data
;
622 TALLOC_CTX
*frame
= talloc_stackframe();
623 bool is_valid_range_mapping
= true;
626 rangenum
= ctx
->rangenum
;
629 range_keystr
= talloc_asprintf(frame
, "%"PRIu32
, rangenum
);
630 if (range_keystr
== NULL
) {
631 status
= NT_STATUS_NO_MEMORY
;
637 status
= dbwrap_fetch_bystring(db
, frame
, range_keystr
, &val
);
638 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
639 DEBUG(10, ("Did not find range '%s' in database.\n",
642 } else if (!NT_STATUS_IS_OK(status
)) {
643 DEBUG(5, ("Error fetching rang key: %s\n", nt_errstr(status
)));
647 if (val
.dptr
== NULL
) {
648 DEBUG(1, ("Invalid mapping: %s -> empty value\n",
650 is_valid_range_mapping
= false;
652 uint32_t reverse_rangenum
= 0;
654 keystr
= (char *)val
.dptr
;
656 status
= dbwrap_fetch_uint32_bystring(db
, keystr
,
658 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
659 DEBUG(1, ("Incomplete mapping %s -> %s: "
660 "no backward mapping\n",
661 range_keystr
, keystr
));
662 is_valid_range_mapping
= false;
663 } else if (!NT_STATUS_IS_OK(status
)) {
664 DEBUG(1, ("Error fetching reverse mapping for "
666 range_keystr
, keystr
, nt_errstr(status
)));
668 } else if (rangenum
!= reverse_rangenum
) {
669 is_valid_range_mapping
= false;
673 if (!is_valid_range_mapping
&& !force
) {
674 DEBUG(10, ("Not deleting invalid mapping, since not in force "
676 status
= NT_STATUS_FILE_INVALID
;
680 status
= dbwrap_delete_bystring(db
, range_keystr
);
681 if (!NT_STATUS_IS_OK(status
)) {
682 DEBUG(1, ("Deletion of '%s' failed: %s\n",
683 range_keystr
, nt_errstr(status
)));
687 if (!is_valid_range_mapping
) {
691 status
= dbwrap_delete_bystring(db
, keystr
);
692 if (!NT_STATUS_IS_OK(status
)) {
693 DEBUG(1, ("Deletion of '%s' failed: %s\n",
694 keystr
, nt_errstr(status
)));
698 DEBUG(10, ("Deleted range mapping %s <--> %s\n", range_keystr
,
706 NTSTATUS
idmap_autorid_delete_range_by_num(struct db_context
*db
,
711 struct idmap_autorid_delete_range_by_num_ctx ctx
;
713 ctx
.rangenum
= rangenum
;
716 status
= dbwrap_trans_do(db
, idmap_autorid_delete_range_by_num_action
,
722 * Open and possibly create the database.
724 NTSTATUS
idmap_autorid_db_open(const char *path
,
726 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
, DBWRAP_FLAG_NONE
);
738 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path
));
739 return NT_STATUS_UNSUCCESSFUL
;
746 * Initialize the high watermark records in the database.
748 NTSTATUS
idmap_autorid_init_hwms(struct db_context
*db
)
752 status
= idmap_autorid_init_hwm(db
, HWM
);
753 if (!NT_STATUS_IS_OK(status
)) {
757 status
= idmap_autorid_init_hwm(db
, ALLOC_HWM_UID
);
758 if (!NT_STATUS_IS_OK(status
)) {
762 status
= idmap_autorid_init_hwm(db
, ALLOC_HWM_GID
);
767 NTSTATUS
idmap_autorid_db_init(const char *path
,
769 struct db_context
**db
)
773 status
= idmap_autorid_db_open(path
, mem_ctx
, db
);
774 if (!NT_STATUS_IS_OK(status
)) {
778 status
= idmap_autorid_init_hwms(*db
);
784 struct idmap_autorid_fetch_config_state
{
789 static void idmap_autorid_config_parser(TDB_DATA key
, TDB_DATA value
,
792 struct idmap_autorid_fetch_config_state
*state
;
794 state
= (struct idmap_autorid_fetch_config_state
*)private_data
;
797 * strndup because we have non-nullterminated strings in the db
799 state
->configstr
= talloc_strndup(
800 state
->mem_ctx
, (const char *)value
.dptr
, value
.dsize
);
803 NTSTATUS
idmap_autorid_getconfigstr(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
808 struct idmap_autorid_fetch_config_state state
;
810 if (result
== NULL
) {
811 return NT_STATUS_INVALID_PARAMETER
;
814 key
= string_term_tdb_data(CONFIGKEY
);
816 state
.mem_ctx
= mem_ctx
;
817 state
.configstr
= NULL
;
819 status
= dbwrap_parse_record(db
, key
, idmap_autorid_config_parser
,
821 if (!NT_STATUS_IS_OK(status
)) {
822 DEBUG(1, ("Error while retrieving config: %s\n",
827 if (state
.configstr
== NULL
) {
828 DEBUG(1, ("Error while retrieving config\n"));
829 return NT_STATUS_NO_MEMORY
;
832 DEBUG(5, ("found CONFIG: %s\n", state
.configstr
));
834 *result
= state
.configstr
;
838 bool idmap_autorid_parse_configstr(const char *configstr
,
839 struct autorid_global_config
*cfg
)
841 unsigned long minvalue
, rangesize
, maxranges
;
843 if (sscanf(configstr
,
844 "minvalue:%lu rangesize:%lu maxranges:%lu",
845 &minvalue
, &rangesize
, &maxranges
) != 3) {
847 ("Found invalid configuration data. "
848 "Creating new config\n"));
852 cfg
->minvalue
= minvalue
;
853 cfg
->rangesize
= rangesize
;
854 cfg
->maxranges
= maxranges
;
859 NTSTATUS
idmap_autorid_loadconfig(struct db_context
*db
,
860 struct autorid_global_config
*result
)
862 struct autorid_global_config cfg
= {0};
865 char *configstr
= NULL
;
867 if (result
== NULL
) {
868 return NT_STATUS_INVALID_PARAMETER
;
871 status
= idmap_autorid_getconfigstr(db
, db
, &configstr
);
872 if (!NT_STATUS_IS_OK(status
)) {
876 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
877 TALLOC_FREE(configstr
);
879 return NT_STATUS_INVALID_PARAMETER
;
882 DEBUG(10, ("Loaded previously stored configuration "
883 "minvalue:%d rangesize:%d\n",
884 cfg
.minvalue
, cfg
.rangesize
));
891 NTSTATUS
idmap_autorid_saveconfig(struct db_context
*db
,
892 struct autorid_global_config
*cfg
)
895 struct autorid_global_config storedconfig
= {0};
896 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
900 TALLOC_CTX
*frame
= talloc_stackframe();
902 DEBUG(10, ("New configuration provided for storing is "
903 "minvalue:%d rangesize:%d maxranges:%d\n",
904 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
));
906 if (cfg
->rangesize
< 2000) {
907 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
911 if (cfg
->maxranges
== 0) {
912 DEBUG(1, ("An autorid maxranges value of 0 is invalid. "
913 "Must have at least one range available.\n"));
917 status
= idmap_autorid_loadconfig(db
, &storedconfig
);
918 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
919 DEBUG(5, ("No configuration found. Storing initial "
920 "configuration.\n"));
922 } else if (!NT_STATUS_IS_OK(status
)) {
923 DEBUG(1, ("Error loading configuration: %s\n",
928 /* did the minimum value or rangesize change? */
929 if ((storedconfig
.minvalue
!= cfg
->minvalue
) ||
930 (storedconfig
.rangesize
!= cfg
->rangesize
))
932 DEBUG(1, ("New configuration values for rangesize or "
933 "minimum uid value conflict with previously "
934 "used values! Not storing new config.\n"));
935 status
= NT_STATUS_INVALID_PARAMETER
;
939 status
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
940 if (!NT_STATUS_IS_OK(status
)) {
941 DEBUG(1, ("Fatal error while fetching current "
942 "HWM value: %s\n", nt_errstr(status
)));
943 status
= NT_STATUS_INTERNAL_ERROR
;
948 * has the highest uid value been reduced to setting that is not
949 * sufficient any more for already existing ranges?
951 if (hwm
> cfg
->maxranges
) {
952 DEBUG(1, ("New upper uid limit is too low to cover "
953 "existing mappings! Not storing new config.\n"));
954 status
= NT_STATUS_INVALID_PARAMETER
;
959 talloc_asprintf(frame
,
960 "minvalue:%u rangesize:%u maxranges:%u",
961 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
);
963 if (cfgstr
== NULL
) {
964 status
= NT_STATUS_NO_MEMORY
;
968 data
= string_tdb_data(cfgstr
);
970 status
= dbwrap_trans_store_bystring(db
, CONFIGKEY
, data
, TDB_REPLACE
);
977 NTSTATUS
idmap_autorid_saveconfigstr(struct db_context
*db
,
978 const char *configstr
)
982 struct autorid_global_config cfg
;
984 ok
= idmap_autorid_parse_configstr(configstr
, &cfg
);
986 return NT_STATUS_INVALID_PARAMETER
;
989 status
= idmap_autorid_saveconfig(db
, &cfg
);
995 * iteration: Work on all range mappings for a given domain
998 struct domain_range_visitor_ctx
{
1000 NTSTATUS (*fn
)(struct db_context
*db
,
1004 void *private_data
);
1006 int count
; /* number of records worked on */
1009 static int idmap_autorid_visit_domain_range(struct db_record
*rec
,
1012 struct domain_range_visitor_ctx
*vi
;
1015 uint32_t range_index
= 0;
1016 uint32_t rangenum
= 0;
1017 TDB_DATA key
, value
;
1020 struct db_context
*db
;
1022 vi
= talloc_get_type_abort(private_data
,
1023 struct domain_range_visitor_ctx
);
1025 key
= dbwrap_record_get_key(rec
);
1028 * split string "<sid>[#<index>]" into sid string and index number
1031 domsid
= (char *)key
.dptr
;
1033 DEBUG(10, ("idmap_autorid_visit_domain_range: visiting key '%s'\n",
1036 sep
= strrchr(domsid
, '#');
1041 if (sscanf(index_str
, "%"SCNu32
, &range_index
) != 1) {
1042 DEBUG(10, ("Found separator '#' but '%s' is not a "
1043 "valid range index. Skipping record\n",
1049 if (!idmap_autorid_validate_sid(domsid
)) {
1050 DEBUG(10, ("String '%s' is not a valid sid. "
1051 "Skipping record.\n", domsid
));
1055 if ((vi
->domsid
!= NULL
) && (strcmp(domsid
, vi
->domsid
) != 0)) {
1056 DEBUG(10, ("key sid '%s' does not match requested sid '%s'.\n",
1057 domsid
, vi
->domsid
));
1061 value
= dbwrap_record_get_value(rec
);
1063 if (value
.dsize
!= sizeof(uint32_t)) {
1064 /* it might be a mapping of a well known sid */
1065 DEBUG(10, ("value size %u != sizeof(uint32_t) for sid '%s', "
1066 "skipping.\n", (unsigned)value
.dsize
, vi
->domsid
));
1070 rangenum
= IVAL(value
.dptr
, 0);
1072 db
= dbwrap_record_get_db(rec
);
1074 status
= vi
->fn(db
, domsid
, range_index
, rangenum
, vi
->private_data
);
1075 if (!NT_STATUS_IS_OK(status
)) {
1087 static NTSTATUS
idmap_autorid_iterate_domain_ranges_int(struct db_context
*db
,
1089 NTSTATUS (*fn
)(struct db_context
*db
,
1093 void *private_data
),
1096 NTSTATUS (*traverse
)(struct db_context
*db
,
1097 int (*f
)(struct db_record
*, void *),
1102 struct domain_range_visitor_ctx
*vi
;
1103 TALLOC_CTX
*frame
= talloc_stackframe();
1105 if (domsid
== NULL
) {
1106 DEBUG(10, ("No sid provided, operating on all ranges\n"));
1110 DEBUG(1, ("Error: missing visitor callback\n"));
1111 status
= NT_STATUS_INVALID_PARAMETER
;
1115 vi
= talloc_zero(frame
, struct domain_range_visitor_ctx
);
1117 status
= NT_STATUS_NO_MEMORY
;
1121 vi
->domsid
= domsid
;
1123 vi
->private_data
= private_data
;
1125 status
= traverse(db
, idmap_autorid_visit_domain_range
, vi
, NULL
);
1126 if (!NT_STATUS_IS_OK(status
)) {
1130 if (count
!= NULL
) {
1139 NTSTATUS
idmap_autorid_iterate_domain_ranges(struct db_context
*db
,
1141 NTSTATUS (*fn
)(struct db_context
*db
,
1145 void *private_data
),
1151 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1162 NTSTATUS
idmap_autorid_iterate_domain_ranges_read(struct db_context
*db
,
1164 NTSTATUS (*fn
)(struct db_context
*db
,
1174 status
= idmap_autorid_iterate_domain_ranges_int(db
,
1179 dbwrap_traverse_read
);
1186 * Delete all ranges configured for a given domain
1189 struct delete_domain_ranges_visitor_ctx
{
1193 static NTSTATUS
idmap_autorid_delete_domain_ranges_visitor(
1194 struct db_context
*db
,
1196 uint32_t domain_range_index
,
1200 struct delete_domain_ranges_visitor_ctx
*ctx
;
1203 ctx
= (struct delete_domain_ranges_visitor_ctx
*)private_data
;
1205 status
= idmap_autorid_delete_range_by_sid(
1206 db
, domsid
, domain_range_index
, ctx
->force
);
1210 struct idmap_autorid_delete_domain_ranges_ctx
{
1213 int count
; /* output: count records operated on */
1216 static NTSTATUS
idmap_autorid_delete_domain_ranges_action(struct db_context
*db
,
1219 struct idmap_autorid_delete_domain_ranges_ctx
*ctx
;
1220 struct delete_domain_ranges_visitor_ctx visitor_ctx
;
1224 ctx
= (struct idmap_autorid_delete_domain_ranges_ctx
*)private_data
;
1226 ZERO_STRUCT(visitor_ctx
);
1227 visitor_ctx
.force
= ctx
->force
;
1229 status
= idmap_autorid_iterate_domain_ranges(db
,
1231 idmap_autorid_delete_domain_ranges_visitor
,
1234 if (!NT_STATUS_IS_OK(status
)) {
1240 return NT_STATUS_OK
;
1243 NTSTATUS
idmap_autorid_delete_domain_ranges(struct db_context
*db
,
1249 struct idmap_autorid_delete_domain_ranges_ctx ctx
;
1252 ctx
.domsid
= domsid
;
1255 status
= dbwrap_trans_do(db
, idmap_autorid_delete_domain_ranges_action
,
1257 if (!NT_STATUS_IS_OK(status
)) {
1263 return NT_STATUS_OK
;