Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : common functions for TDB based idmapping backends
5 :
6 : Copyright (C) Christian Ambach 2012
7 :
8 : These functions were initially copied over from idmap_tdb.c and idmap_tdb2.c
9 : which are:
10 :
11 : Copyright (C) Tim Potter 2000
12 : Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
13 : Copyright (C) Jeremy Allison 2006
14 : Copyright (C) Simo Sorce 2003-2006
15 : Copyright (C) Michael Adam 2009-2010
16 : Copyright (C) Andrew Tridgell 2007
17 :
18 : This program is free software; you can redistribute it and/or modify
19 : it under the terms of the GNU General Public License as published by
20 : the Free Software Foundation; either version 2 of the License, or
21 : (at your option) any later version.
22 :
23 : This program is distributed in the hope that it will be useful,
24 : but WITHOUT ANY WARRANTY; without even the implied warranty of
25 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 : GNU General Public License for more details.
27 :
28 : You should have received a copy of the GNU General Public License
29 : along with this program; if not, write to the Free Software
30 : Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 : */
32 :
33 : #include "includes.h"
34 : #include "idmap_tdb_common.h"
35 : #include "dbwrap/dbwrap.h"
36 : #include "util_tdb.h"
37 : #include "idmap_rw.h"
38 : #include "../libcli/security/dom_sid.h"
39 :
40 : #undef DBGC_CLASS
41 : #define DBGC_CLASS DBGC_IDMAP
42 :
43 : struct idmap_tdb_common_allocate_id_context {
44 : const char *hwmkey;
45 : const char *hwmtype;
46 : uint32_t high_hwm;
47 : uint32_t hwm;
48 : };
49 :
50 109 : static NTSTATUS idmap_tdb_common_allocate_id_action(struct db_context *db,
51 : void *private_data)
52 : {
53 109 : NTSTATUS ret;
54 109 : struct idmap_tdb_common_allocate_id_context *state = private_data;
55 109 : uint32_t hwm;
56 :
57 109 : ret = dbwrap_fetch_uint32_bystring(db, state->hwmkey, &hwm);
58 109 : if (!NT_STATUS_IS_OK(ret)) {
59 0 : ret = NT_STATUS_INTERNAL_DB_ERROR;
60 0 : goto done;
61 : }
62 :
63 : /* check it is in the range */
64 109 : if (hwm > state->high_hwm) {
65 1 : DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
66 : state->hwmtype, (unsigned long)state->high_hwm));
67 1 : ret = NT_STATUS_UNSUCCESSFUL;
68 1 : goto done;
69 : }
70 :
71 : /* fetch a new id and increment it */
72 108 : ret = dbwrap_change_uint32_atomic_bystring(db, state->hwmkey, &hwm, 1);
73 108 : if (!NT_STATUS_IS_OK(ret)) {
74 0 : DEBUG(1, ("Fatal error while fetching a new %s value\n!",
75 : state->hwmtype));
76 0 : goto done;
77 : }
78 :
79 : /* recheck it is in the range */
80 108 : if (hwm > state->high_hwm) {
81 0 : DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
82 : state->hwmtype, (unsigned long)state->high_hwm));
83 0 : ret = NT_STATUS_UNSUCCESSFUL;
84 0 : goto done;
85 : }
86 :
87 108 : ret = NT_STATUS_OK;
88 108 : state->hwm = hwm;
89 :
90 109 : done:
91 109 : return ret;
92 : }
93 :
94 109 : static NTSTATUS idmap_tdb_common_allocate_id(struct idmap_domain *dom,
95 : struct unixid *xid)
96 : {
97 109 : const char *hwmkey;
98 109 : const char *hwmtype;
99 109 : uint32_t hwm = 0;
100 109 : NTSTATUS status;
101 109 : struct idmap_tdb_common_allocate_id_context state;
102 109 : struct idmap_tdb_common_context *ctx;
103 :
104 109 : ctx =
105 109 : talloc_get_type_abort(dom->private_data,
106 : struct idmap_tdb_common_context);
107 :
108 : /* Get current high water mark */
109 109 : switch (xid->type) {
110 :
111 101 : case ID_TYPE_UID:
112 101 : hwmkey = ctx->hwmkey_uid;
113 101 : hwmtype = "UID";
114 101 : break;
115 :
116 8 : case ID_TYPE_GID:
117 8 : hwmkey = ctx->hwmkey_gid;
118 8 : hwmtype = "GID";
119 8 : break;
120 :
121 0 : case ID_TYPE_BOTH:
122 : /*
123 : * This is not supported here yet and
124 : * already handled in idmap_rw_new_mapping()
125 : */
126 0 : FALL_THROUGH;
127 : case ID_TYPE_NOT_SPECIFIED:
128 : /*
129 : * This is handled in idmap_rw_new_mapping()
130 : */
131 0 : FALL_THROUGH;
132 : default:
133 0 : DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
134 0 : return NT_STATUS_INVALID_PARAMETER;
135 : }
136 :
137 109 : state.hwm = hwm;
138 109 : state.high_hwm = ctx->max_id;
139 109 : state.hwmtype = hwmtype;
140 109 : state.hwmkey = hwmkey;
141 :
142 109 : status = dbwrap_trans_do(ctx->db, idmap_tdb_common_allocate_id_action,
143 : &state);
144 :
145 109 : if (NT_STATUS_IS_OK(status)) {
146 108 : xid->id = state.hwm;
147 108 : DEBUG(10, ("New %s = %d\n", hwmtype, state.hwm));
148 : } else {
149 1 : DEBUG(1, ("Error allocating a new %s\n", hwmtype));
150 : }
151 :
152 109 : return status;
153 : }
154 :
155 : /**
156 : * Allocate a new unix-ID.
157 : * For now this is for the default idmap domain only.
158 : * Should be extended later on.
159 : */
160 109 : NTSTATUS idmap_tdb_common_get_new_id(struct idmap_domain * dom,
161 : struct unixid * id)
162 : {
163 109 : NTSTATUS ret;
164 :
165 109 : if (!strequal(dom->name, "*")) {
166 0 : DEBUG(3, ("idmap_tdb_common_get_new_id: "
167 : "Refusing allocation of a new unixid for domain'%s'. "
168 : "Currently only supported for the default "
169 : "domain \"*\".\n", dom->name));
170 0 : return NT_STATUS_NOT_IMPLEMENTED;
171 : }
172 :
173 109 : ret = idmap_tdb_common_allocate_id(dom, id);
174 :
175 109 : return ret;
176 : }
177 :
178 : /**
179 : * store a mapping in the database.
180 : */
181 :
182 : struct idmap_tdb_common_set_mapping_context {
183 : const char *ksidstr;
184 : const char *kidstr;
185 : };
186 :
187 18 : static NTSTATUS idmap_tdb_common_set_mapping_action(struct db_context *db,
188 : void *private_data)
189 : {
190 18 : TDB_DATA data;
191 18 : NTSTATUS ret;
192 18 : struct idmap_tdb_common_set_mapping_context *state = private_data;
193 18 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
194 :
195 18 : DEBUG(10, ("Storing %s <-> %s map\n", state->ksidstr, state->kidstr));
196 :
197 : /* check whether sid mapping is already present in db */
198 18 : ret = dbwrap_fetch_bystring(db, tmp_ctx, state->ksidstr, &data);
199 18 : if (NT_STATUS_IS_OK(ret)) {
200 3 : ret = NT_STATUS_OBJECT_NAME_COLLISION;
201 3 : goto done;
202 : }
203 :
204 15 : ret = dbwrap_store_bystring(db, state->ksidstr,
205 : string_term_tdb_data(state->kidstr),
206 : TDB_INSERT);
207 15 : if (!NT_STATUS_IS_OK(ret)) {
208 0 : DEBUG(0, ("Error storing SID -> ID: %s\n", nt_errstr(ret)));
209 0 : goto done;
210 : }
211 :
212 15 : ret = dbwrap_store_bystring(db, state->kidstr,
213 : string_term_tdb_data(state->ksidstr),
214 : TDB_INSERT);
215 15 : if (!NT_STATUS_IS_OK(ret)) {
216 0 : DEBUG(0, ("Error storing ID -> SID: %s\n", nt_errstr(ret)));
217 : /* try to remove the previous stored SID -> ID map */
218 0 : dbwrap_delete_bystring(db, state->ksidstr);
219 0 : goto done;
220 : }
221 :
222 15 : DEBUG(10, ("Stored %s <-> %s\n", state->ksidstr, state->kidstr));
223 :
224 18 : done:
225 18 : talloc_free(tmp_ctx);
226 18 : return ret;
227 : }
228 :
229 21 : NTSTATUS idmap_tdb_common_set_mapping(struct idmap_domain * dom,
230 : const struct id_map * map)
231 : {
232 21 : struct idmap_tdb_common_context *ctx;
233 21 : struct idmap_tdb_common_set_mapping_context state;
234 21 : NTSTATUS ret;
235 21 : struct dom_sid_buf ksidstr;
236 21 : char *kidstr = NULL;
237 :
238 21 : if (!map || !map->sid) {
239 2 : return NT_STATUS_INVALID_PARAMETER;
240 : }
241 :
242 : /* TODO: should we filter a set_mapping using low/high filters ? */
243 :
244 19 : ctx =
245 19 : talloc_get_type_abort(dom->private_data,
246 : struct idmap_tdb_common_context);
247 :
248 19 : switch (map->xid.type) {
249 :
250 9 : case ID_TYPE_UID:
251 9 : kidstr =
252 9 : talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
253 9 : break;
254 :
255 9 : case ID_TYPE_GID:
256 9 : kidstr =
257 9 : talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
258 9 : break;
259 :
260 1 : default:
261 1 : DEBUG(2, ("INVALID unix ID type: 0x%02x\n", map->xid.type));
262 1 : return NT_STATUS_INVALID_PARAMETER;
263 : }
264 :
265 18 : if (kidstr == NULL) {
266 0 : DEBUG(0, ("ERROR: Out of memory!\n"));
267 0 : ret = NT_STATUS_NO_MEMORY;
268 0 : goto done;
269 : }
270 :
271 18 : state.ksidstr = dom_sid_str_buf(map->sid, &ksidstr);
272 18 : state.kidstr = kidstr;
273 :
274 18 : ret = dbwrap_trans_do(ctx->db, idmap_tdb_common_set_mapping_action,
275 : &state);
276 :
277 18 : done:
278 18 : talloc_free(kidstr);
279 18 : return ret;
280 : }
281 :
282 : /*
283 : * Create a new mapping for an unmapped SID, also allocating a new ID.
284 : * This should be run inside a transaction.
285 : *
286 : * TODO:
287 : * Properly integrate this with multi domain idmap config:
288 : * Currently, the allocator is default-config only.
289 : */
290 15 : NTSTATUS idmap_tdb_common_new_mapping(struct idmap_domain * dom,
291 : struct id_map * map)
292 : {
293 15 : NTSTATUS ret;
294 15 : struct idmap_tdb_common_context *ctx;
295 :
296 15 : ctx =
297 15 : talloc_get_type_abort(dom->private_data,
298 : struct idmap_tdb_common_context);
299 :
300 15 : ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
301 :
302 15 : return ret;
303 : }
304 :
305 : /*
306 : lookup a set of unix ids
307 : */
308 5 : NTSTATUS idmap_tdb_common_unixids_to_sids(struct idmap_domain * dom,
309 : struct id_map ** ids)
310 : {
311 5 : NTSTATUS ret;
312 5 : size_t i, num_mapped = 0;
313 5 : struct idmap_tdb_common_context *ctx;
314 :
315 5 : NTSTATUS(*unixid_to_sid_fn) (struct idmap_domain * dom,
316 : struct id_map * map);
317 5 : ctx =
318 5 : talloc_get_type_abort(dom->private_data,
319 : struct idmap_tdb_common_context);
320 :
321 5 : if (ctx->unixid_to_sid_fn == NULL) {
322 0 : unixid_to_sid_fn = idmap_tdb_common_unixid_to_sid;
323 : } else {
324 0 : unixid_to_sid_fn = ctx->unixid_to_sid_fn;
325 : }
326 :
327 : /* initialize the status to avoid surprise */
328 15 : for (i = 0; ids[i]; i++) {
329 10 : ids[i]->status = ID_UNKNOWN;
330 : }
331 :
332 15 : for (i = 0; ids[i]; i++) {
333 10 : ret = unixid_to_sid_fn(dom, ids[i]);
334 10 : if (!NT_STATUS_IS_OK(ret)) {
335 :
336 : /* if it is just a failed mapping continue */
337 5 : if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
338 :
339 : /* make sure it is marked as unmapped */
340 5 : ids[i]->status = ID_UNMAPPED;
341 5 : continue;
342 : }
343 :
344 : /* some fatal error occurred, return immediately */
345 0 : goto done;
346 : }
347 :
348 : /* all ok, id is mapped */
349 5 : ids[i]->status = ID_MAPPED;
350 5 : num_mapped += 1;
351 : }
352 :
353 0 : ret = NT_STATUS_OK;
354 :
355 5 : done:
356 :
357 5 : if (NT_STATUS_IS_OK(ret)) {
358 5 : if (i == 0 || num_mapped == 0) {
359 0 : ret = NT_STATUS_NONE_MAPPED;
360 3 : } else if (num_mapped < i) {
361 0 : ret = STATUS_SOME_UNMAPPED;
362 : } else {
363 2 : ret = NT_STATUS_OK;
364 : }
365 : }
366 :
367 5 : return ret;
368 : }
369 :
370 : /*
371 : default single id to sid lookup function
372 : */
373 16 : NTSTATUS idmap_tdb_common_unixid_to_sid(struct idmap_domain * dom,
374 : struct id_map * map)
375 : {
376 16 : NTSTATUS ret;
377 16 : TDB_DATA data;
378 16 : char *keystr;
379 16 : struct idmap_tdb_common_context *ctx;
380 :
381 16 : if (!dom || !map) {
382 3 : return NT_STATUS_INVALID_PARAMETER;
383 : }
384 :
385 13 : ctx =
386 13 : talloc_get_type_abort(dom->private_data,
387 : struct idmap_tdb_common_context);
388 :
389 : /* apply filters before checking */
390 13 : if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
391 1 : DEBUG(5,
392 : ("Requested id (%u) out of range (%u - %u). Filtered!\n",
393 : map->xid.id, dom->low_id, dom->high_id));
394 1 : return NT_STATUS_NONE_MAPPED;
395 : }
396 :
397 12 : switch (map->xid.type) {
398 :
399 6 : case ID_TYPE_UID:
400 6 : keystr =
401 6 : talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
402 6 : break;
403 :
404 6 : case ID_TYPE_GID:
405 6 : keystr =
406 6 : talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
407 6 : break;
408 :
409 0 : default:
410 0 : DEBUG(2, ("INVALID unix ID type: 0x%02x\n", map->xid.type));
411 0 : return NT_STATUS_INVALID_PARAMETER;
412 : }
413 :
414 12 : if (keystr == NULL) {
415 0 : DEBUG(0, ("Out of memory!\n"));
416 0 : ret = NT_STATUS_NO_MEMORY;
417 0 : goto done;
418 : }
419 :
420 12 : DEBUG(10, ("Fetching record %s\n", keystr));
421 :
422 : /* Check if the mapping exists */
423 12 : ret = dbwrap_fetch_bystring(ctx->db, keystr, keystr, &data);
424 :
425 12 : if (!NT_STATUS_IS_OK(ret)) {
426 5 : DEBUG(10, ("Record %s not found\n", keystr));
427 5 : ret = NT_STATUS_NONE_MAPPED;
428 5 : goto done;
429 : }
430 :
431 7 : if ((data.dsize == 0) || (data.dptr[data.dsize-1] != '\0')) {
432 0 : DBG_DEBUG("Invalid record length %zu\n", data.dsize);
433 0 : ret = NT_STATUS_INTERNAL_DB_ERROR;
434 0 : goto done;
435 : }
436 :
437 7 : if (!string_to_sid(map->sid, (const char *)data.dptr)) {
438 0 : DEBUG(10, ("INVALID SID (%s) in record %s\n",
439 : (const char *)data.dptr, keystr));
440 0 : ret = NT_STATUS_INTERNAL_DB_ERROR;
441 0 : goto done;
442 : }
443 :
444 7 : DEBUG(10, ("Found record %s -> %s\n", keystr, (const char *)data.dptr));
445 0 : ret = NT_STATUS_OK;
446 :
447 12 : done:
448 12 : talloc_free(keystr);
449 12 : return ret;
450 : }
451 :
452 : /**********************************
453 : Single sid to id lookup function.
454 : **********************************/
455 :
456 24 : NTSTATUS idmap_tdb_common_sid_to_unixid(struct idmap_domain * dom,
457 : struct id_map * map)
458 : {
459 24 : NTSTATUS ret;
460 24 : TDB_DATA data;
461 24 : struct dom_sid_buf keystr;
462 24 : unsigned long rec_id = 0;
463 24 : struct idmap_tdb_common_context *ctx;
464 24 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
465 :
466 24 : if (!dom || !map) {
467 3 : talloc_free(tmp_ctx);
468 3 : return NT_STATUS_INVALID_PARAMETER;
469 : }
470 :
471 21 : ctx =
472 21 : talloc_get_type_abort(dom->private_data,
473 : struct idmap_tdb_common_context);
474 :
475 21 : dom_sid_str_buf(map->sid, &keystr);
476 :
477 21 : DEBUG(10, ("Fetching record %s\n", keystr.buf));
478 :
479 : /* Check if sid is present in database */
480 21 : ret = dbwrap_fetch_bystring(ctx->db, tmp_ctx, keystr.buf, &data);
481 21 : if (!NT_STATUS_IS_OK(ret)) {
482 9 : DEBUG(10, ("Record %s not found\n", keystr.buf));
483 9 : ret = NT_STATUS_NONE_MAPPED;
484 9 : goto done;
485 : }
486 :
487 : /* What type of record is this ? */
488 12 : if (sscanf((const char *)data.dptr, "UID %lu", &rec_id) == 1) {
489 : /* Try a UID record. */
490 6 : map->xid.id = rec_id;
491 6 : map->xid.type = ID_TYPE_UID;
492 6 : DEBUG(10,
493 : ("Found uid record %s -> %s \n", keystr.buf,
494 : (const char *)data.dptr));
495 0 : ret = NT_STATUS_OK;
496 :
497 6 : } else if (sscanf((const char *)data.dptr, "GID %lu", &rec_id) == 1) {
498 : /* Try a GID record. */
499 6 : map->xid.id = rec_id;
500 6 : map->xid.type = ID_TYPE_GID;
501 6 : DEBUG(10,
502 : ("Found gid record %s -> %s \n", keystr.buf,
503 : (const char *)data.dptr));
504 0 : ret = NT_STATUS_OK;
505 :
506 : } else { /* Unknown record type ! */
507 0 : DEBUG(2,
508 : ("Found INVALID record %s -> %s\n", keystr.buf,
509 : (const char *)data.dptr));
510 0 : ret = NT_STATUS_INTERNAL_DB_ERROR;
511 0 : goto done;
512 : }
513 :
514 : /* apply filters before returning result */
515 12 : if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
516 0 : DEBUG(5,
517 : ("Requested id (%u) out of range (%u - %u). Filtered!\n",
518 : map->xid.id, dom->low_id, dom->high_id));
519 0 : ret = NT_STATUS_NONE_MAPPED;
520 : }
521 :
522 12 : done:
523 21 : talloc_free(tmp_ctx);
524 21 : return ret;
525 : }
526 :
527 : /**********************************
528 : lookup a set of sids
529 : **********************************/
530 :
531 : struct idmap_tdb_common_sids_to_unixids_context {
532 : struct idmap_domain *dom;
533 : struct id_map **ids;
534 : bool allocate_unmapped;
535 : NTSTATUS(*sid_to_unixid_fn) (struct idmap_domain * dom,
536 : struct id_map * map);
537 : };
538 :
539 10 : static NTSTATUS idmap_tdb_common_sids_to_unixids_action(struct db_context *db,
540 : void *private_data)
541 : {
542 10 : struct idmap_tdb_common_sids_to_unixids_context *state = private_data;
543 10 : size_t i, num_mapped = 0, num_required = 0;
544 10 : NTSTATUS ret = NT_STATUS_OK;
545 :
546 10 : DEBUG(10, ("idmap_tdb_common_sids_to_unixids: "
547 : " domain: [%s], allocate: %s\n",
548 : state->dom->name, state->allocate_unmapped ? "yes" : "no"));
549 :
550 28 : for (i = 0; state->ids[i]; i++) {
551 18 : if ((state->ids[i]->status == ID_UNKNOWN) ||
552 : /* retry if we could not map in previous run: */
553 0 : (state->ids[i]->status == ID_UNMAPPED)) {
554 17 : NTSTATUS ret2;
555 :
556 17 : ret2 = state->sid_to_unixid_fn(state->dom,
557 0 : state->ids[i]);
558 :
559 17 : if (!NT_STATUS_IS_OK(ret2)) {
560 :
561 : /* if it is just a failed mapping, continue */
562 9 : if (NT_STATUS_EQUAL
563 : (ret2, NT_STATUS_NONE_MAPPED)) {
564 :
565 : /* make sure it is marked as unmapped */
566 9 : state->ids[i]->status = ID_UNMAPPED;
567 9 : ret = STATUS_SOME_UNMAPPED;
568 : } else {
569 : /*
570 : * some fatal error occurred,
571 : * return immediately
572 : */
573 0 : ret = ret2;
574 0 : goto done;
575 : }
576 : } else {
577 : /* all ok, id is mapped */
578 8 : state->ids[i]->status = ID_MAPPED;
579 : }
580 : }
581 :
582 18 : if (state->ids[i]->status == ID_MAPPED) {
583 9 : num_mapped += 1;
584 : }
585 :
586 18 : if ((state->ids[i]->status == ID_UNMAPPED) &&
587 9 : state->allocate_unmapped) {
588 3 : ret =
589 3 : idmap_tdb_common_new_mapping(state->dom,
590 0 : state->ids[i]);
591 3 : DBG_DEBUG("idmap_tdb_common_new_mapping returned %s\n",
592 : nt_errstr(ret));
593 3 : if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) {
594 0 : if (state->ids[i]->status == ID_REQUIRE_TYPE) {
595 0 : num_required += 1;
596 0 : continue;
597 : }
598 : }
599 3 : if (!NT_STATUS_IS_OK(ret)) {
600 0 : ret = STATUS_SOME_UNMAPPED;
601 0 : continue;
602 : }
603 3 : num_mapped += 1;
604 : }
605 : }
606 :
607 10 : done:
608 :
609 10 : if (NT_STATUS_IS_OK(ret) ||
610 0 : NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) {
611 10 : if (i == 0 || num_mapped == 0) {
612 0 : ret = NT_STATUS_NONE_MAPPED;
613 8 : } else if (num_mapped < i) {
614 0 : ret = STATUS_SOME_UNMAPPED;
615 : } else {
616 6 : ret = NT_STATUS_OK;
617 : }
618 10 : if (num_required > 0) {
619 0 : ret = STATUS_SOME_UNMAPPED;
620 : }
621 : }
622 :
623 10 : return ret;
624 : }
625 :
626 8 : NTSTATUS idmap_tdb_common_sids_to_unixids(struct idmap_domain * dom,
627 : struct id_map ** ids)
628 : {
629 8 : NTSTATUS ret;
630 8 : int i;
631 8 : struct idmap_tdb_common_sids_to_unixids_context state;
632 8 : struct idmap_tdb_common_context *ctx;
633 :
634 8 : ctx =
635 8 : talloc_get_type_abort(dom->private_data,
636 : struct idmap_tdb_common_context);
637 :
638 : /* initialize the status to avoid surprise */
639 30 : for (i = 0; ids[i]; i++) {
640 14 : ids[i]->status = ID_UNKNOWN;
641 : }
642 :
643 8 : state.dom = dom;
644 8 : state.ids = ids;
645 8 : state.allocate_unmapped = false;
646 8 : if (ctx->sid_to_unixid_fn == NULL) {
647 8 : state.sid_to_unixid_fn = idmap_tdb_common_sid_to_unixid;
648 : } else {
649 0 : state.sid_to_unixid_fn = ctx->sid_to_unixid_fn;
650 : }
651 :
652 8 : ret = idmap_tdb_common_sids_to_unixids_action(ctx->db, &state);
653 :
654 8 : if ( (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED) ||
655 4 : NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) &&
656 4 : !dom->read_only) {
657 2 : state.allocate_unmapped = true;
658 2 : ret = dbwrap_trans_do(ctx->db,
659 : idmap_tdb_common_sids_to_unixids_action,
660 : &state);
661 : }
662 :
663 8 : return ret;
664 : }
|