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"
28 static NTSTATUS
idmap_autorid_get_domainrange_action(struct db_context
*db
,
32 uint32_t rangenum
, hwm
;
34 struct autorid_range_config
*range
;
36 range
= (struct autorid_range_config
*)private_data
;
38 ret
= dbwrap_fetch_uint32_bystring(db
, range
->keystr
,
41 if (NT_STATUS_IS_OK(ret
)) {
42 /* entry is already present*/
46 DEBUG(10, ("Acquiring new range for domain %s "
47 "(domain_range_index=%"PRIu32
")\n",
48 range
->domsid
, range
->domain_range_index
));
50 /* fetch the current HWM */
51 ret
= dbwrap_fetch_uint32_bystring(db
, HWM
, &hwm
);
52 if (!NT_STATUS_IS_OK(ret
)) {
53 DEBUG(1, ("Fatal error while fetching current "
54 "HWM value: %s\n", nt_errstr(ret
)));
55 ret
= NT_STATUS_INTERNAL_ERROR
;
59 /* do we have a range left? */
60 if (hwm
>= range
->globalcfg
->maxranges
) {
61 DEBUG(1, ("No more domain ranges available!\n"));
62 ret
= NT_STATUS_NO_MEMORY
;
66 /* increase the HWM */
67 ret
= dbwrap_change_uint32_atomic_bystring(db
, HWM
, &rangenum
, 1);
68 if (!NT_STATUS_IS_OK(ret
)) {
69 DEBUG(1, ("Fatal error while fetching a new "
70 "domain range value!\n"));
74 /* store away the new mapping in both directions */
75 ret
= dbwrap_store_uint32_bystring(db
, range
->keystr
, rangenum
);
76 if (!NT_STATUS_IS_OK(ret
)) {
77 DEBUG(1, ("Fatal error while storing new "
78 "domain->range assignment!\n"));
82 numstr
= talloc_asprintf(db
, "%u", rangenum
);
84 ret
= NT_STATUS_NO_MEMORY
;
88 ret
= dbwrap_store_bystring(db
, numstr
,
89 string_term_tdb_data(range
->keystr
), TDB_INSERT
);
92 if (!NT_STATUS_IS_OK(ret
)) {
93 DEBUG(1, ("Fatal error while storing "
94 "new domain->range assignment!\n"));
97 DEBUG(5, ("Acquired new range #%d for domain %s "
98 "(domain_range_index=%"PRIu32
")\n", rangenum
, range
->keystr
,
99 range
->domain_range_index
));
101 range
->rangenum
= rangenum
;
110 NTSTATUS
idmap_autorid_get_domainrange(struct db_context
*db
,
111 struct autorid_range_config
*range
,
117 * try to find mapping without locking the database,
118 * if it is not found create a mapping in a transaction unless
119 * read-only mode has been set
121 if (range
->domain_range_index
> 0) {
122 snprintf(range
->keystr
, FSTRING_LEN
, "%s#%"PRIu32
,
123 range
->domsid
, range
->domain_range_index
);
125 fstrcpy(range
->keystr
, range
->domsid
);
128 ret
= dbwrap_fetch_uint32_bystring(db
, range
->keystr
,
131 if (!NT_STATUS_IS_OK(ret
)) {
133 return NT_STATUS_NOT_FOUND
;
135 ret
= dbwrap_trans_do(db
,
136 idmap_autorid_get_domainrange_action
, range
);
139 range
->low_id
= range
->globalcfg
->minvalue
140 + range
->rangenum
* range
->globalcfg
->rangesize
;
142 DEBUG(10, ("Using range #%d for domain %s "
143 "(domain_range_index=%"PRIu32
", low_id=%"PRIu32
")\n",
144 range
->rangenum
, range
->domsid
, range
->domain_range_index
,
150 /* initialize the given HWM to 0 if it does not exist yet */
151 NTSTATUS
idmap_autorid_init_hwm(struct db_context
*db
, const char *hwm
)
156 status
= dbwrap_fetch_uint32_bystring(db
, hwm
, &hwmval
);
157 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
158 status
= dbwrap_trans_store_int32_bystring(db
, hwm
, 0);
159 if (!NT_STATUS_IS_OK(status
)) {
161 ("Unable to initialise HWM (%s) in autorid "
162 "database: %s\n", hwm
, nt_errstr(status
)));
163 return NT_STATUS_INTERNAL_DB_ERROR
;
165 } else if (!NT_STATUS_IS_OK(status
)) {
166 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
167 "database: %s\n", hwm
, nt_errstr(status
)));
175 * open and initialize the database which stores the ranges for the domains
177 NTSTATUS
idmap_autorid_db_init(const char *path
,
179 struct db_context
**db
)
184 /* its already open */
188 /* Open idmap repository */
189 *db
= db_open(mem_ctx
, path
, 0, TDB_DEFAULT
, O_RDWR
| O_CREAT
, 0644,
190 DBWRAP_LOCK_ORDER_1
);
193 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path
));
194 return NT_STATUS_UNSUCCESSFUL
;
197 /* Initialize high water mark for the currently used range to 0 */
199 status
= idmap_autorid_init_hwm(*db
, HWM
);
200 NT_STATUS_NOT_OK_RETURN(status
);
202 status
= idmap_autorid_init_hwm(*db
, ALLOC_HWM_UID
);
203 NT_STATUS_NOT_OK_RETURN(status
);
205 status
= idmap_autorid_init_hwm(*db
, ALLOC_HWM_GID
);
210 struct idmap_autorid_fetch_config_state
{
215 static void idmap_autorid_config_parser(TDB_DATA key
, TDB_DATA value
,
218 struct idmap_autorid_fetch_config_state
*state
;
220 state
= (struct idmap_autorid_fetch_config_state
*)private_data
;
223 * strndup because we have non-nullterminated strings in the db
225 state
->configstr
= talloc_strndup(
226 state
->mem_ctx
, (const char *)value
.dptr
, value
.dsize
);
229 NTSTATUS
idmap_autorid_getconfigstr(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
234 struct idmap_autorid_fetch_config_state state
;
236 if (result
== NULL
) {
237 return NT_STATUS_INVALID_PARAMETER
;
240 key
= string_term_tdb_data(CONFIGKEY
);
242 state
.mem_ctx
= mem_ctx
;
243 state
.configstr
= NULL
;
245 status
= dbwrap_parse_record(db
, key
, idmap_autorid_config_parser
,
247 if (!NT_STATUS_IS_OK(status
)) {
248 DEBUG(1, ("Error while retrieving config: %s\n",
253 if (state
.configstr
== NULL
) {
254 DEBUG(1, ("Error while retrieving config\n"));
255 return NT_STATUS_NO_MEMORY
;
258 DEBUG(5, ("found CONFIG: %s\n", state
.configstr
));
260 *result
= state
.configstr
;
264 struct autorid_global_config
*idmap_autorid_loadconfig(struct db_context
*db
,
269 struct autorid_global_config
*cfg
;
270 unsigned long minvalue
, rangesize
, maxranges
;
273 status
= dbwrap_fetch_bystring(db
, ctx
, CONFIGKEY
, &data
);
275 if (!NT_STATUS_IS_OK(status
)) {
276 DEBUG(10, ("No saved config found\n"));
280 cfg
= talloc_zero(ctx
, struct autorid_global_config
);
285 if (sscanf((char *)data
.dptr
,
286 "minvalue:%lu rangesize:%lu maxranges:%lu",
287 &minvalue
, &rangesize
, &maxranges
) != 3) {
289 ("Found invalid configuration data"
290 "creating new config\n"));
294 cfg
->minvalue
= minvalue
;
295 cfg
->rangesize
= rangesize
;
296 cfg
->maxranges
= maxranges
;
298 DEBUG(10, ("Loaded previously stored configuration "
299 "minvalue:%d rangesize:%d\n",
300 cfg
->minvalue
, cfg
->rangesize
));
306 NTSTATUS
idmap_autorid_saveconfig(struct db_context
*db
,
307 struct autorid_global_config
*cfg
)
315 talloc_asprintf(talloc_tos(),
316 "minvalue:%u rangesize:%u maxranges:%u",
317 cfg
->minvalue
, cfg
->rangesize
, cfg
->maxranges
);
320 return NT_STATUS_NO_MEMORY
;
323 data
= string_tdb_data(cfgstr
);
325 status
= dbwrap_trans_store_bystring(db
, CONFIGKEY
, data
, TDB_REPLACE
);