Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : idmap TDB2 backend, used for clustered Samba setups.
5 :
6 : This uses dbwrap to access tdb files. The location can be set
7 : using tdb:idmap2.tdb =" in smb.conf
8 :
9 : Copyright (C) Andrew Tridgell 2007
10 :
11 : This is heavily based upon idmap_tdb.c, which is:
12 :
13 : Copyright (C) Tim Potter 2000
14 : Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
15 : Copyright (C) Jeremy Allison 2006
16 : Copyright (C) Simo Sorce 2003-2006
17 : Copyright (C) Michael Adam 2009-2010
18 :
19 : This program is free software; you can redistribute it and/or modify
20 : it under the terms of the GNU General Public License as published by
21 : the Free Software Foundation; either version 2 of the License, or
22 : (at your option) any later version.
23 :
24 : This program is distributed in the hope that it will be useful,
25 : but WITHOUT ANY WARRANTY; without even the implied warranty of
26 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 : GNU General Public License for more details.
28 :
29 : You should have received a copy of the GNU General Public License
30 : along with this program; if not, write to the Free Software
31 : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 : */
33 :
34 : #include "includes.h"
35 : #include "system/filesys.h"
36 : #include "winbindd.h"
37 : #include "idmap.h"
38 : #include "idmap_rw.h"
39 : #include "dbwrap/dbwrap.h"
40 : #include "dbwrap/dbwrap_open.h"
41 : #include "../libcli/security/dom_sid.h"
42 : #include "util_tdb.h"
43 : #include "idmap_tdb_common.h"
44 :
45 : #undef DBGC_CLASS
46 : #define DBGC_CLASS DBGC_IDMAP
47 :
48 : struct idmap_tdb2_context {
49 : const char *script; /* script to provide idmaps */
50 : };
51 :
52 : /* High water mark keys */
53 : #define HWM_GROUP "GROUP HWM"
54 : #define HWM_USER "USER HWM"
55 :
56 : /*
57 : * check and initialize high/low water marks in the db
58 : */
59 0 : static NTSTATUS idmap_tdb2_init_hwm(struct idmap_domain *dom)
60 : {
61 : NTSTATUS status;
62 : uint32_t low_id;
63 : struct idmap_tdb_common_context *ctx;
64 :
65 0 : ctx = talloc_get_type(dom->private_data,
66 : struct idmap_tdb_common_context);
67 :
68 : /* Create high water marks for group and user id */
69 :
70 0 : status = dbwrap_fetch_uint32_bystring(ctx->db, HWM_USER, &low_id);
71 0 : if (!NT_STATUS_IS_OK(status) || (low_id < dom->low_id)) {
72 0 : status = dbwrap_trans_store_uint32_bystring(ctx->db, HWM_USER,
73 : dom->low_id);
74 0 : if (!NT_STATUS_IS_OK(status)) {
75 0 : DEBUG(0, ("Unable to initialise user hwm in idmap "
76 : "database: %s\n", nt_errstr(status)));
77 0 : return NT_STATUS_INTERNAL_DB_ERROR;
78 : }
79 : }
80 :
81 0 : status = dbwrap_fetch_uint32_bystring(ctx->db, HWM_GROUP, &low_id);
82 0 : if (!NT_STATUS_IS_OK(status) || (low_id < dom->low_id)) {
83 0 : status = dbwrap_trans_store_uint32_bystring(ctx->db, HWM_GROUP,
84 : dom->low_id);
85 0 : if (!NT_STATUS_IS_OK(status)) {
86 0 : DEBUG(0, ("Unable to initialise group hwm in idmap "
87 : "database: %s\n", nt_errstr(status)));
88 0 : return NT_STATUS_INTERNAL_DB_ERROR;
89 : }
90 : }
91 :
92 0 : return NT_STATUS_OK;
93 : }
94 :
95 :
96 : /*
97 : open the permanent tdb
98 : */
99 0 : static NTSTATUS idmap_tdb2_open_db(struct idmap_domain *dom)
100 : {
101 : char *db_path;
102 : struct idmap_tdb_common_context *ctx;
103 :
104 0 : ctx = talloc_get_type(dom->private_data,
105 : struct idmap_tdb_common_context);
106 :
107 0 : if (ctx->db) {
108 : /* its already open */
109 0 : return NT_STATUS_OK;
110 : }
111 :
112 0 : db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir());
113 0 : NT_STATUS_HAVE_NO_MEMORY(db_path);
114 :
115 : /* Open idmap repository */
116 0 : ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644,
117 : DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
118 0 : if (ctx->db == NULL) {
119 0 : DEBUG(0, ("Unable to open idmap_tdb2 database '%s'\n",
120 : db_path));
121 0 : TALLOC_FREE(db_path);
122 0 : return NT_STATUS_UNSUCCESSFUL;
123 : }
124 0 : TALLOC_FREE(db_path);
125 :
126 0 : return idmap_tdb2_init_hwm(dom);
127 : }
128 :
129 : /**
130 : * store a mapping in the database.
131 : */
132 :
133 : struct idmap_tdb2_set_mapping_context {
134 : const char *ksidstr;
135 : const char *kidstr;
136 : };
137 :
138 0 : static NTSTATUS idmap_tdb2_set_mapping_action(struct db_context *db,
139 : void *private_data)
140 : {
141 : TDB_DATA data;
142 : NTSTATUS ret;
143 : struct idmap_tdb2_set_mapping_context *state;
144 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
145 :
146 0 : state = (struct idmap_tdb2_set_mapping_context *)private_data;
147 :
148 0 : DEBUG(10, ("Storing %s <-> %s map\n", state->ksidstr, state->kidstr));
149 :
150 : /* check whether sid mapping is already present in db */
151 0 : ret = dbwrap_fetch_bystring(db, tmp_ctx, state->ksidstr, &data);
152 0 : if (NT_STATUS_IS_OK(ret)) {
153 0 : ret = NT_STATUS_OBJECT_NAME_COLLISION;
154 0 : goto done;
155 : }
156 :
157 0 : ret = dbwrap_store_bystring(db, state->ksidstr,
158 : string_term_tdb_data(state->kidstr),
159 : TDB_INSERT);
160 0 : if (!NT_STATUS_IS_OK(ret)) {
161 0 : DEBUG(0, ("Error storing SID -> ID: %s\n", nt_errstr(ret)));
162 0 : goto done;
163 : }
164 :
165 0 : ret = dbwrap_store_bystring(db, state->kidstr,
166 : string_term_tdb_data(state->ksidstr),
167 : TDB_INSERT);
168 0 : if (!NT_STATUS_IS_OK(ret)) {
169 0 : DEBUG(0, ("Error storing ID -> SID: %s\n", nt_errstr(ret)));
170 : /* try to remove the previous stored SID -> ID map */
171 0 : dbwrap_delete_bystring(db, state->ksidstr);
172 0 : goto done;
173 : }
174 :
175 0 : DEBUG(10,("Stored %s <-> %s\n", state->ksidstr, state->kidstr));
176 :
177 0 : done:
178 0 : talloc_free(tmp_ctx);
179 0 : return ret;
180 : }
181 :
182 0 : static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map)
183 : {
184 : struct idmap_tdb2_context *ctx;
185 : NTSTATUS ret;
186 : char *kidstr;
187 : struct dom_sid_buf sid_str;
188 : struct idmap_tdb_common_context *commonctx;
189 : struct idmap_tdb2_set_mapping_context state;
190 :
191 0 : if (!map || !map->sid) {
192 0 : return NT_STATUS_INVALID_PARAMETER;
193 : }
194 :
195 0 : kidstr = NULL;
196 :
197 : /* TODO: should we filter a set_mapping using low/high filters ? */
198 :
199 0 : commonctx = talloc_get_type(dom->private_data,
200 : struct idmap_tdb_common_context);
201 :
202 0 : ctx = talloc_get_type(commonctx->private_data,
203 : struct idmap_tdb2_context);
204 :
205 0 : switch (map->xid.type) {
206 :
207 0 : case ID_TYPE_UID:
208 0 : kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
209 0 : break;
210 :
211 0 : case ID_TYPE_GID:
212 0 : kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
213 0 : break;
214 :
215 0 : default:
216 0 : DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
217 0 : return NT_STATUS_INVALID_PARAMETER;
218 : }
219 :
220 0 : if (kidstr == NULL) {
221 0 : DEBUG(0, ("ERROR: Out of memory!\n"));
222 0 : ret = NT_STATUS_NO_MEMORY;
223 0 : goto done;
224 : }
225 :
226 0 : state.ksidstr = dom_sid_str_buf(map->sid, &sid_str);
227 0 : state.kidstr = kidstr;
228 :
229 0 : ret = dbwrap_trans_do(commonctx->db, idmap_tdb2_set_mapping_action,
230 : &state);
231 :
232 0 : done:
233 0 : talloc_free(kidstr);
234 0 : return ret;
235 : }
236 :
237 : /*
238 : run a script to perform a mapping
239 :
240 : The script should the following command lines:
241 :
242 : SIDTOID S-1-xxxx
243 : IDTOSID UID xxxx
244 : IDTOSID GID xxxx
245 :
246 : and should return one of the following as a single line of text
247 : UID:xxxx
248 : GID:xxxx
249 : SID:xxxx
250 : ERR:xxxx
251 : */
252 : static NTSTATUS idmap_tdb2_script(struct idmap_tdb2_context *ctx,
253 : struct id_map *map, const char *fmt, ...)
254 : PRINTF_ATTRIBUTE(3,4);
255 :
256 0 : static NTSTATUS idmap_tdb2_script(struct idmap_tdb2_context *ctx, struct id_map *map,
257 : const char *fmt, ...)
258 : {
259 : va_list ap;
260 : char *cmd;
261 : FILE *p;
262 : char line[64];
263 : unsigned long v;
264 :
265 0 : cmd = talloc_asprintf(ctx, "%s ", ctx->script);
266 0 : NT_STATUS_HAVE_NO_MEMORY(cmd);
267 :
268 0 : va_start(ap, fmt);
269 0 : cmd = talloc_vasprintf_append(cmd, fmt, ap);
270 0 : va_end(ap);
271 0 : NT_STATUS_HAVE_NO_MEMORY(cmd);
272 :
273 0 : p = popen(cmd, "r");
274 0 : talloc_free(cmd);
275 0 : if (p == NULL) {
276 0 : return NT_STATUS_NONE_MAPPED;
277 : }
278 :
279 0 : if (fgets(line, sizeof(line)-1, p) == NULL) {
280 0 : pclose(p);
281 0 : return NT_STATUS_NONE_MAPPED;
282 : }
283 0 : pclose(p);
284 :
285 0 : DEBUG(10,("idmap script gave: %s\n", line));
286 :
287 0 : if (sscanf(line, "UID:%lu", &v) == 1) {
288 0 : map->xid.id = v;
289 0 : map->xid.type = ID_TYPE_UID;
290 0 : } else if (sscanf(line, "GID:%lu", &v) == 1) {
291 0 : map->xid.id = v;
292 0 : map->xid.type = ID_TYPE_GID;
293 0 : } else if (strncmp(line, "SID:S-", 6) == 0) {
294 0 : if (!string_to_sid(map->sid, &line[4])) {
295 0 : DEBUG(0,("Bad SID in '%s' from idmap script %s\n",
296 : line, ctx->script));
297 0 : return NT_STATUS_NONE_MAPPED;
298 : }
299 : } else {
300 0 : DEBUG(0,("Bad reply '%s' from idmap script %s\n",
301 : line, ctx->script));
302 0 : return NT_STATUS_NONE_MAPPED;
303 : }
304 :
305 0 : return NT_STATUS_OK;
306 : }
307 :
308 :
309 :
310 : /*
311 : Single id to sid lookup function.
312 : */
313 0 : static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_domain *dom, struct id_map *map)
314 : {
315 : NTSTATUS ret;
316 : TDB_DATA data;
317 : char *keystr;
318 : NTSTATUS status;
319 : struct idmap_tdb_common_context *commonctx;
320 : struct idmap_tdb2_context *ctx;
321 :
322 :
323 0 : if (!dom || !map) {
324 0 : return NT_STATUS_INVALID_PARAMETER;
325 : }
326 :
327 0 : status = idmap_tdb2_open_db(dom);
328 0 : NT_STATUS_NOT_OK_RETURN(status);
329 :
330 0 : commonctx = talloc_get_type(dom->private_data,
331 : struct idmap_tdb_common_context);
332 :
333 0 : ctx = talloc_get_type(commonctx->private_data,
334 : struct idmap_tdb2_context);
335 :
336 : /* apply filters before checking */
337 0 : if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
338 0 : DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
339 : map->xid.id, dom->low_id, dom->high_id));
340 0 : return NT_STATUS_NONE_MAPPED;
341 : }
342 :
343 0 : switch (map->xid.type) {
344 :
345 0 : case ID_TYPE_UID:
346 0 : keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
347 0 : break;
348 :
349 0 : case ID_TYPE_GID:
350 0 : keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
351 0 : break;
352 :
353 0 : default:
354 0 : DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
355 0 : return NT_STATUS_INVALID_PARAMETER;
356 : }
357 :
358 0 : if (keystr == NULL) {
359 0 : DEBUG(0, ("Out of memory!\n"));
360 0 : ret = NT_STATUS_NO_MEMORY;
361 0 : goto done;
362 : }
363 :
364 0 : DEBUG(10,("Fetching record %s\n", keystr));
365 :
366 : /* Check if the mapping exists */
367 0 : status = dbwrap_fetch_bystring(commonctx->db, keystr, keystr, &data);
368 :
369 0 : if (!NT_STATUS_IS_OK(status)) {
370 : struct dom_sid_buf sidstr;
371 : struct idmap_tdb2_set_mapping_context store_state;
372 :
373 0 : DEBUG(10,("Record %s not found\n", keystr));
374 0 : if (ctx->script == NULL) {
375 0 : ret = NT_STATUS_NONE_MAPPED;
376 0 : goto done;
377 : }
378 :
379 0 : ret = idmap_tdb2_script(ctx, map, "IDTOSID %s", keystr);
380 0 : if (!NT_STATUS_IS_OK(ret)) {
381 0 : goto done;
382 : }
383 :
384 0 : store_state.ksidstr = dom_sid_str_buf(map->sid, &sidstr);
385 0 : store_state.kidstr = keystr;
386 :
387 0 : ret = dbwrap_trans_do(commonctx->db,
388 : idmap_tdb2_set_mapping_action,
389 : &store_state);
390 0 : goto done;
391 : }
392 :
393 0 : if (!string_to_sid(map->sid, (const char *)data.dptr)) {
394 0 : DEBUG(10,("INVALID SID (%s) in record %s\n",
395 : (const char *)data.dptr, keystr));
396 0 : ret = NT_STATUS_INTERNAL_DB_ERROR;
397 0 : goto done;
398 : }
399 :
400 0 : DEBUG(10,("Found record %s -> %s\n", keystr, (const char *)data.dptr));
401 0 : ret = NT_STATUS_OK;
402 :
403 0 : done:
404 0 : talloc_free(keystr);
405 0 : return ret;
406 : }
407 :
408 :
409 : /*
410 : Single sid to id lookup function.
411 : */
412 0 : static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_domain *dom, struct id_map *map)
413 : {
414 : NTSTATUS ret;
415 : TDB_DATA data;
416 : struct dom_sid_buf keystr;
417 0 : unsigned long rec_id = 0;
418 : struct idmap_tdb_common_context *commonctx;
419 : struct idmap_tdb2_context *ctx;
420 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
421 :
422 0 : ret = idmap_tdb2_open_db(dom);
423 0 : NT_STATUS_NOT_OK_RETURN(ret);
424 :
425 0 : commonctx = talloc_get_type(dom->private_data,
426 : struct idmap_tdb_common_context);
427 :
428 0 : ctx = talloc_get_type(commonctx->private_data,
429 : struct idmap_tdb2_context);
430 :
431 0 : dom_sid_str_buf(map->sid, &keystr);
432 :
433 0 : DEBUG(10, ("Fetching record %s\n", keystr.buf));
434 :
435 : /* Check if sid is present in database */
436 0 : ret = dbwrap_fetch_bystring(commonctx->db, tmp_ctx, keystr.buf, &data);
437 0 : if (!NT_STATUS_IS_OK(ret)) {
438 : char *idstr;
439 : struct idmap_tdb2_set_mapping_context store_state;
440 :
441 0 : DBG_DEBUG("Record %s not found\n", keystr.buf);
442 :
443 0 : if (ctx->script == NULL) {
444 0 : ret = NT_STATUS_NONE_MAPPED;
445 0 : goto done;
446 : }
447 :
448 0 : ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr.buf);
449 0 : if (!NT_STATUS_IS_OK(ret)) {
450 0 : goto done;
451 : }
452 :
453 : /* apply filters before returning result */
454 0 : if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
455 0 : DEBUG(5, ("Script returned id (%u) out of range "
456 : "(%u - %u). Filtered!\n",
457 : map->xid.id, dom->low_id, dom->high_id));
458 0 : ret = NT_STATUS_NONE_MAPPED;
459 0 : goto done;
460 : }
461 :
462 0 : idstr = talloc_asprintf(tmp_ctx, "%cID %lu",
463 0 : map->xid.type == ID_TYPE_UID?'U':'G',
464 0 : (unsigned long)map->xid.id);
465 0 : if (idstr == NULL) {
466 0 : ret = NT_STATUS_NO_MEMORY;
467 0 : goto done;
468 : }
469 :
470 0 : store_state.ksidstr = keystr.buf;
471 0 : store_state.kidstr = idstr;
472 :
473 0 : ret = dbwrap_trans_do(commonctx->db,
474 : idmap_tdb2_set_mapping_action,
475 : &store_state);
476 0 : goto done;
477 : }
478 :
479 : /* What type of record is this ? */
480 0 : if (sscanf((const char *)data.dptr, "UID %lu", &rec_id) == 1) { /* Try a UID record. */
481 0 : map->xid.id = rec_id;
482 0 : map->xid.type = ID_TYPE_UID;
483 0 : DBG_DEBUG("Found uid record %s -> %s \n",
484 : keystr.buf,
485 : (const char *)data.dptr );
486 0 : ret = NT_STATUS_OK;
487 :
488 0 : } else if (sscanf((const char *)data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */
489 0 : map->xid.id = rec_id;
490 0 : map->xid.type = ID_TYPE_GID;
491 0 : DBG_DEBUG("Found gid record %s -> %s \n",
492 : keystr.buf,
493 : (const char *)data.dptr );
494 0 : ret = NT_STATUS_OK;
495 :
496 : } else { /* Unknown record type ! */
497 0 : DBG_WARNING("Found INVALID record %s -> %s\n",
498 : keystr.buf,
499 : (const char *)data.dptr);
500 0 : ret = NT_STATUS_INTERNAL_DB_ERROR;
501 0 : goto done;
502 : }
503 :
504 : /* apply filters before returning result */
505 0 : if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
506 0 : DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
507 : map->xid.id, dom->low_id, dom->high_id));
508 0 : ret = NT_STATUS_NONE_MAPPED;
509 : }
510 :
511 0 : done:
512 0 : talloc_free(tmp_ctx);
513 0 : return ret;
514 : }
515 :
516 : /*
517 : Initialise idmap database.
518 : */
519 0 : static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom)
520 : {
521 : NTSTATUS ret;
522 : struct idmap_tdb_common_context *commonctx;
523 : struct idmap_tdb2_context *ctx;
524 0 : const char * idmap_script = NULL;
525 0 : const char *ctx_script = NULL;
526 :
527 0 : commonctx = talloc_zero(dom, struct idmap_tdb_common_context);
528 0 : if(!commonctx) {
529 0 : DEBUG(0, ("Out of memory!\n"));
530 0 : return NT_STATUS_NO_MEMORY;
531 : }
532 :
533 0 : commonctx->rw_ops = talloc_zero(commonctx, struct idmap_rw_ops);
534 0 : if (commonctx->rw_ops == NULL) {
535 0 : DEBUG(0, ("Out of memory!\n"));
536 0 : ret = NT_STATUS_NO_MEMORY;
537 0 : goto failed;
538 : }
539 :
540 0 : ctx = talloc_zero(commonctx, struct idmap_tdb2_context);
541 0 : if (!ctx) {
542 0 : DEBUG(0, ("Out of memory!\n"));
543 0 : ret = NT_STATUS_NO_MEMORY;
544 0 : goto failed;
545 : }
546 :
547 0 : ctx_script = idmap_config_const_string(dom->name, "script", NULL);
548 :
549 0 : idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL);
550 0 : if (idmap_script != NULL) {
551 0 : DEBUG(0, ("Warning: 'idmap:script' is deprecated. "
552 : " Please use 'idmap config * : script' instead!\n"));
553 : }
554 :
555 0 : if (strequal(dom->name, "*") && ctx_script == NULL) {
556 : /* fall back to idmap:script for backwards compatibility */
557 0 : ctx_script = idmap_script;
558 : }
559 :
560 0 : if (ctx_script) {
561 0 : DEBUG(1, ("using idmap script '%s'\n", ctx_script));
562 : /*
563 : * We must ensure this memory is owned by ctx.
564 : * The ctx_script const pointer is a pointer into
565 : * the config file data and may become invalid
566 : * on config file reload. BUG: 13956
567 : */
568 0 : ctx->script = talloc_strdup(ctx, ctx_script);
569 0 : if (ctx->script == NULL) {
570 0 : ret = NT_STATUS_NO_MEMORY;
571 0 : goto failed;
572 : }
573 : }
574 :
575 0 : commonctx->max_id = dom->high_id;
576 0 : commonctx->hwmkey_uid = HWM_USER;
577 0 : commonctx->hwmkey_gid = HWM_GROUP;
578 :
579 0 : commonctx->sid_to_unixid_fn = idmap_tdb2_sid_to_id;
580 0 : commonctx->unixid_to_sid_fn = idmap_tdb2_id_to_sid;
581 :
582 0 : commonctx->rw_ops->get_new_id = idmap_tdb_common_get_new_id;
583 0 : commonctx->rw_ops->set_mapping = idmap_tdb2_set_mapping;
584 :
585 0 : commonctx->private_data = ctx;
586 0 : dom->private_data = commonctx;
587 :
588 0 : ret = idmap_tdb2_open_db(dom);
589 0 : if (!NT_STATUS_IS_OK(ret)) {
590 0 : goto failed;
591 : }
592 :
593 0 : return NT_STATUS_OK;
594 :
595 0 : failed:
596 0 : talloc_free(commonctx);
597 0 : return ret;
598 : }
599 :
600 :
601 : static const struct idmap_methods db_methods = {
602 : .init = idmap_tdb2_db_init,
603 : .unixids_to_sids = idmap_tdb_common_unixids_to_sids,
604 : .sids_to_unixids = idmap_tdb_common_sids_to_unixids,
605 : .allocate_id = idmap_tdb_common_get_new_id
606 : };
607 :
608 : static_decl_idmap;
609 0 : NTSTATUS idmap_tdb2_init(TALLOC_CTX *ctx)
610 : {
611 0 : return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods);
612 : }
|