s3/docs: Correct version number.
[Samba/gebeck_regimport.git] / source4 / winbind / idmap.c
blobd0efbb159b7f9673cae4e061af51131ee38052d7
1 /*
2 Unix SMB/CIFS implementation.
4 Map SIDs to unixids and back
6 Copyright (C) Kai Blin 2008
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "auth/auth.h"
24 #include "librpc/gen_ndr/lsa.h"
25 #include "librpc/gen_ndr/samr.h"
26 #include "librpc/gen_ndr/ndr_security.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "lib/ldb/include/ldb_errors.h"
29 #include "lib/ldb_wrap.h"
30 #include "param/param.h"
31 #include "winbind/idmap.h"
32 #include "libcli/security/security.h"
33 #include "libcli/ldap/ldap_ndr.h"
35 /**
36 * Get uid/gid bounds from idmap database
38 * \param idmap_ctx idmap context to use
39 * \param low lower uid/gid bound is stored here
40 * \param high upper uid/gid bound is stored here
41 * \return 0 on success, nonzero on failure
43 static int idmap_get_bounds(struct idmap_context *idmap_ctx, uint32_t *low,
44 uint32_t *high)
46 int ret = -1;
47 struct ldb_context *ldb = idmap_ctx->ldb_ctx;
48 struct ldb_dn *dn;
49 struct ldb_result *res = NULL;
50 TALLOC_CTX *tmp_ctx = talloc_new(idmap_ctx);
51 uint32_t lower_bound = (uint32_t) -1;
52 uint32_t upper_bound = (uint32_t) -1;
54 dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
55 if (dn == NULL) goto failed;
57 ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
58 if (ret != LDB_SUCCESS) goto failed;
60 if (res->count != 1) {
61 ret = -1;
62 goto failed;
65 lower_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "lowerBound", -1);
66 if (lower_bound != (uint32_t) -1) {
67 ret = LDB_SUCCESS;
68 } else {
69 ret = -1;
70 goto failed;
73 upper_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "upperBound", -1);
74 if (upper_bound != (uint32_t) -1) {
75 ret = LDB_SUCCESS;
76 } else {
77 ret = -1;
80 failed:
81 talloc_free(tmp_ctx);
82 *low = lower_bound;
83 *high = upper_bound;
84 return ret;
87 /**
88 * Add a dom_sid structure to a ldb_message
89 * \param idmap_ctx idmap context to use
90 * \param mem_ctx talloc context to use
91 * \param ldb_message ldb message to add dom_sid to
92 * \param attr_name name of the attribute to store the dom_sid in
93 * \param sid dom_sid to store
94 * \return 0 on success, an ldb error code on failure.
96 static int idmap_msg_add_dom_sid(struct idmap_context *idmap_ctx,
97 TALLOC_CTX *mem_ctx, struct ldb_message *msg,
98 const char *attr_name, const struct dom_sid *sid)
100 struct ldb_val val;
101 enum ndr_err_code ndr_err;
103 ndr_err = ndr_push_struct_blob(&val, mem_ctx,
104 lp_iconv_convenience(idmap_ctx->lp_ctx),
105 sid,
106 (ndr_push_flags_fn_t)ndr_push_dom_sid);
108 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
109 return -1;
112 return ldb_msg_add_value(msg, attr_name, &val, NULL);
116 * Get a dom_sid structure from a ldb message.
118 * \param mem_ctx talloc context to allocate dom_sid memory in
119 * \param msg ldb_message to get dom_sid from
120 * \param attr_name key that has the dom_sid as data
121 * \return dom_sid structure on success, NULL on failure
123 static struct dom_sid *idmap_msg_get_dom_sid(TALLOC_CTX *mem_ctx,
124 struct ldb_message *msg, const char *attr_name)
126 struct dom_sid *sid;
127 const struct ldb_val *val;
128 enum ndr_err_code ndr_err;
130 val = ldb_msg_find_ldb_val(msg, attr_name);
131 if (val == NULL) {
132 return NULL;
135 sid = talloc(mem_ctx, struct dom_sid);
136 if (sid == NULL) {
137 return NULL;
140 ndr_err = ndr_pull_struct_blob(val, sid, NULL, sid,
141 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
142 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
143 talloc_free(sid);
144 return NULL;
147 return sid;
151 * Initialize idmap context
153 * talloc_free to close.
155 * \param mem_ctx talloc context to use.
156 * \return allocated idmap_context on success, NULL on error
158 struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
159 struct tevent_context *ev_ctx,
160 struct loadparm_context *lp_ctx)
162 struct idmap_context *idmap_ctx;
164 idmap_ctx = talloc(mem_ctx, struct idmap_context);
165 if (idmap_ctx == NULL) {
166 return NULL;
169 idmap_ctx->lp_ctx = lp_ctx;
171 idmap_ctx->ldb_ctx = ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx,
172 lp_idmap_url(lp_ctx),
173 system_session(mem_ctx, lp_ctx),
174 NULL, 0, NULL);
175 if (idmap_ctx->ldb_ctx == NULL) {
176 return NULL;
179 idmap_ctx->unix_groups_sid = dom_sid_parse_talloc(mem_ctx, "S-1-22-2");
180 if (idmap_ctx->unix_groups_sid == NULL) {
181 return NULL;
184 idmap_ctx->unix_users_sid = dom_sid_parse_talloc(mem_ctx, "S-1-22-1");
185 if (idmap_ctx->unix_users_sid == NULL) {
186 return NULL;
189 return idmap_ctx;
193 * Convert an unixid to the corresponding SID
195 * \param idmap_ctx idmap context to use
196 * \param mem_ctx talloc context the memory for the struct dom_sid is allocated
197 * from.
198 * \param unixid pointer to a unixid struct to convert
199 * \param sid pointer that will take the struct dom_sid pointer if the mapping
200 * succeeds.
201 * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping not
202 * possible or some other NTSTATUS that is more descriptive on failure.
205 NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
206 const struct unixid *unixid, struct dom_sid **sid)
208 int ret;
209 NTSTATUS status = NT_STATUS_NONE_MAPPED;
210 struct ldb_context *ldb = idmap_ctx->ldb_ctx;
211 struct ldb_result *res = NULL;
212 struct dom_sid *unix_sid, *new_sid;
213 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
214 const char *id_type;
216 switch (unixid->type) {
217 case ID_TYPE_UID:
218 id_type = "ID_TYPE_UID";
219 break;
220 case ID_TYPE_GID:
221 id_type = "ID_TYPE_GID";
222 break;
223 default:
224 DEBUG(1, ("unixid->type must be type gid or uid\n"));
225 status = NT_STATUS_NONE_MAPPED;
226 goto failed;
229 ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
230 NULL, "(&(|(type=ID_TYPE_BOTH)(type=%s))"
231 "(xidNumber=%u))", id_type, unixid->id);
232 if (ret != LDB_SUCCESS) {
233 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
234 status = NT_STATUS_NONE_MAPPED;
235 goto failed;
238 if (res->count == 1) {
239 *sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0],
240 "objectSid");
241 if (*sid == NULL) {
242 DEBUG(1, ("Failed to get sid from db: %u\n", ret));
243 status = NT_STATUS_NONE_MAPPED;
244 goto failed;
246 talloc_free(tmp_ctx);
247 return NT_STATUS_OK;
250 DEBUG(6, ("xid not found in idmap db, create S-1-22- SID.\n"));
252 /* For local users/groups , we just create a rid = uid/gid */
253 if (unixid->type == ID_TYPE_UID) {
254 unix_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-1");
255 } else {
256 unix_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-2");
258 if (unix_sid == NULL) {
259 status = NT_STATUS_NO_MEMORY;
260 goto failed;
263 new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
264 if (new_sid == NULL) {
265 status = NT_STATUS_NO_MEMORY;
266 goto failed;
269 *sid = new_sid;
270 talloc_free(tmp_ctx);
271 return NT_STATUS_OK;
273 failed:
274 talloc_free(tmp_ctx);
275 return status;
280 * Map a SID to an unixid struct.
282 * If no mapping exists, a new mapping will be created.
284 * \todo Check if SIDs can be resolved if lp_idmap_trusted_only() == true
285 * \todo Fix backwards compatibility for Samba3
287 * \param idmap_ctx idmap context to use
288 * \param mem_ctx talloc context to use
289 * \param sid SID to map to an unixid struct
290 * \param unixid pointer to a unixid struct pointer
291 * \return NT_STATUS_OK on success, NT_STATUS_INVALID_SID if the sid is not from
292 * a trusted domain and idmap trusted only = true, NT_STATUS_NONE_MAPPED if the
293 * mapping failed.
295 NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
296 const struct dom_sid *sid, struct unixid **unixid)
298 int ret;
299 NTSTATUS status = NT_STATUS_NONE_MAPPED;
300 struct ldb_context *ldb = idmap_ctx->ldb_ctx;
301 struct ldb_dn *dn;
302 struct ldb_message *hwm_msg, *map_msg;
303 struct ldb_result *res = NULL;
304 int trans;
305 uint32_t low, high, hwm, new_xid;
306 char *sid_string, *unixid_string, *hwm_string;
307 bool hwm_entry_exists;
308 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
310 if (dom_sid_in_domain(idmap_ctx->unix_users_sid, sid)) {
311 uint32_t rid;
312 DEBUG(6, ("This is a local unix uid, just calculate that.\n"));
313 status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
314 if (!NT_STATUS_IS_OK(status)) goto failed;
316 *unixid = talloc(mem_ctx, struct unixid);
317 if (*unixid == NULL) {
318 status = NT_STATUS_NO_MEMORY;
319 goto failed;
321 (*unixid)->id = rid;
322 (*unixid)->type = ID_TYPE_UID;
324 talloc_free(tmp_ctx);
325 return NT_STATUS_OK;
328 if (dom_sid_in_domain(idmap_ctx->unix_groups_sid, sid)) {
329 uint32_t rid;
330 DEBUG(6, ("This is a local unix gid, just calculate that.\n"));
331 status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
332 if (!NT_STATUS_IS_OK(status)) goto failed;
334 *unixid = talloc(mem_ctx, struct unixid);
335 if (*unixid == NULL) {
336 status = NT_STATUS_NO_MEMORY;
337 goto failed;
339 (*unixid)->id = rid;
340 (*unixid)->type = ID_TYPE_GID;
342 talloc_free(tmp_ctx);
343 return NT_STATUS_OK;
346 ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
347 NULL, "(&(objectClass=sidMap)(objectSid=%s))",
348 ldap_encode_ndr_dom_sid(tmp_ctx, sid));
349 if (ret != LDB_SUCCESS) {
350 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
351 status = NT_STATUS_NONE_MAPPED;
352 goto failed;
355 if (res->count == 1) {
356 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
357 "type", NULL);
358 new_xid = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber",
359 -1);
360 if (new_xid == (uint32_t) -1) {
361 DEBUG(1, ("Invalid xid mapping.\n"));
362 status = NT_STATUS_NONE_MAPPED;
363 goto failed;
366 if (type == NULL) {
367 DEBUG(1, ("Invalid type for mapping entry.\n"));
368 status = NT_STATUS_NONE_MAPPED;
369 goto failed;
372 *unixid = talloc(mem_ctx, struct unixid);
373 if (*unixid == NULL) {
374 status = NT_STATUS_NO_MEMORY;
375 goto failed;
378 (*unixid)->id = new_xid;
380 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
381 (*unixid)->type = ID_TYPE_BOTH;
382 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
383 (*unixid)->type = ID_TYPE_UID;
384 } else {
385 (*unixid)->type = ID_TYPE_GID;
388 talloc_free(tmp_ctx);
389 return NT_STATUS_OK;
392 DEBUG(6, ("No existing mapping found, attempting to create one.\n"));
394 trans = ldb_transaction_start(ldb);
395 if (trans != LDB_SUCCESS) {
396 status = NT_STATUS_NONE_MAPPED;
397 goto failed;
400 /* Redo the search to make sure noone changed the mapping while we
401 * weren't looking */
402 ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
403 NULL, "(&(objectClass=sidMap)(objectSid=%s))",
404 ldap_encode_ndr_dom_sid(tmp_ctx, sid));
405 if (ret != LDB_SUCCESS) {
406 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
407 status = NT_STATUS_NONE_MAPPED;
408 goto failed;
411 if (res->count > 0) {
412 DEBUG(1, ("Database changed while trying to add a sidmap.\n"));
413 status = NT_STATUS_RETRY;
414 goto failed;
417 /*FIXME: if lp_idmap_trusted_only() == true, check if SID can be
418 * resolved here. */
420 ret = idmap_get_bounds(idmap_ctx, &low, &high);
421 if (ret != LDB_SUCCESS) {
422 status = NT_STATUS_NONE_MAPPED;
423 goto failed;
426 dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
427 if (dn == NULL) {
428 status = NT_STATUS_NO_MEMORY;
429 goto failed;
432 ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
433 if (ret != LDB_SUCCESS) {
434 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
435 status = NT_STATUS_NONE_MAPPED;
436 goto failed;
439 if (res->count != 1) {
440 DEBUG(1, ("No CN=CONFIG record, idmap database is broken.\n"));
441 status = NT_STATUS_NONE_MAPPED;
442 goto failed;
445 hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1);
446 if (hwm == (uint32_t)-1) {
447 hwm = low;
448 hwm_entry_exists = false;
449 } else {
450 hwm_entry_exists = true;
453 if (hwm > high) {
454 DEBUG(1, ("Out of xids to allocate.\n"));
455 status = NT_STATUS_NONE_MAPPED;
456 goto failed;
459 hwm_msg = ldb_msg_new(tmp_ctx);
460 if (hwm_msg == NULL) {
461 DEBUG(1, ("Out of memory when creating ldb_message\n"));
462 status = NT_STATUS_NO_MEMORY;
463 goto failed;
466 hwm_msg->dn = dn;
468 new_xid = hwm;
469 hwm++;
471 hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm);
472 if (hwm_string == NULL) {
473 status = NT_STATUS_NO_MEMORY;
474 goto failed;
477 sid_string = dom_sid_string(tmp_ctx, sid);
478 if (sid_string == NULL) {
479 status = NT_STATUS_NO_MEMORY;
480 goto failed;
483 unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid);
484 if (unixid_string == NULL) {
485 status = NT_STATUS_NO_MEMORY;
486 goto failed;
489 if (hwm_entry_exists) {
490 struct ldb_message_element *els;
491 struct ldb_val *vals;
493 /* We're modifying the entry, not just adding a new one. */
494 els = talloc_array(tmp_ctx, struct ldb_message_element, 2);
495 if (els == NULL) {
496 status = NT_STATUS_NO_MEMORY;
497 goto failed;
500 vals = talloc_array(tmp_ctx, struct ldb_val, 2);
501 if (els == NULL) {
502 status = NT_STATUS_NO_MEMORY;
503 goto failed;
506 hwm_msg->num_elements = 2;
507 hwm_msg->elements = els;
509 els[0].num_values = 1;
510 els[0].values = &vals[0];
511 els[0].flags = LDB_FLAG_MOD_DELETE;
512 els[0].name = talloc_strdup(tmp_ctx, "xidNumber");
513 if (els[0].name == NULL) {
514 status = NT_STATUS_NO_MEMORY;
515 goto failed;
518 els[1].num_values = 1;
519 els[1].values = &vals[1];
520 els[1].flags = LDB_FLAG_MOD_ADD;
521 els[1].name = els[0].name;
523 vals[0].data = (uint8_t *)unixid_string;
524 vals[0].length = strlen(unixid_string);
525 vals[1].data = (uint8_t *)hwm_string;
526 vals[1].length = strlen(hwm_string);
527 } else {
528 ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD,
529 NULL);
530 if (ret != LDB_SUCCESS) {
531 status = NT_STATUS_NONE_MAPPED;
532 goto failed;
535 ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string);
536 if (ret != LDB_SUCCESS)
538 status = NT_STATUS_NONE_MAPPED;
539 goto failed;
543 ret = ldb_modify(ldb, hwm_msg);
544 if (ret != LDB_SUCCESS) {
545 DEBUG(1, ("Updating the xid high water mark failed: %s\n",
546 ldb_errstring(ldb)));
547 status = NT_STATUS_NONE_MAPPED;
548 goto failed;
551 map_msg = ldb_msg_new(tmp_ctx);
552 if (map_msg == NULL) {
553 status = NT_STATUS_NO_MEMORY;
554 goto failed;
557 map_msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string);
558 if (map_msg->dn == NULL) {
559 status = NT_STATUS_NO_MEMORY;
560 goto failed;
563 ret = ldb_msg_add_string(map_msg, "xidNumber", unixid_string);
564 if (ret != LDB_SUCCESS) {
565 status = NT_STATUS_NONE_MAPPED;
566 goto failed;
569 ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, map_msg, "objectSid",
570 sid);
571 if (ret != LDB_SUCCESS) {
572 status = NT_STATUS_NONE_MAPPED;
573 goto failed;
576 ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap");
577 if (ret != LDB_SUCCESS) {
578 status = NT_STATUS_NONE_MAPPED;
579 goto failed;
582 ret = ldb_msg_add_string(map_msg, "type", "ID_TYPE_BOTH");
583 if (ret != LDB_SUCCESS) {
584 status = NT_STATUS_NONE_MAPPED;
585 goto failed;
588 ret = ldb_msg_add_string(map_msg, "cn", sid_string);
589 if (ret != LDB_SUCCESS) {
590 status = NT_STATUS_NONE_MAPPED;
591 goto failed;
594 ret = ldb_add(ldb, map_msg);
595 if (ret != LDB_SUCCESS) {
596 DEBUG(1, ("Adding a sidmap failed: %s\n", ldb_errstring(ldb)));
597 status = NT_STATUS_NONE_MAPPED;
598 goto failed;
601 trans = ldb_transaction_commit(ldb);
602 if (trans != LDB_SUCCESS) {
603 DEBUG(1, ("Transaction failed: %s\n", ldb_errstring(ldb)));
604 status = NT_STATUS_NONE_MAPPED;
605 goto failed;
608 *unixid = talloc(mem_ctx, struct unixid);
609 if (*unixid == NULL) {
610 status = NT_STATUS_NO_MEMORY;
611 goto failed;
614 (*unixid)->id = new_xid;
615 (*unixid)->type = ID_TYPE_BOTH;
616 talloc_free(tmp_ctx);
617 return NT_STATUS_OK;
619 failed:
620 if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb);
621 talloc_free(tmp_ctx);
622 return status;
626 * Convert an array of unixids to the corresponding array of SIDs
628 * \param idmap_ctx idmap context to use
629 * \param mem_ctx talloc context the memory for the dom_sids is allocated
630 * from.
631 * \param count length of id_mapping array.
632 * \param id array of id_mappings.
633 * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
634 * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
635 * did not.
638 NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
639 TALLOC_CTX *mem_ctx, int count,
640 struct id_mapping *id)
642 int i;
643 int error_count = 0;
645 for (i = 0; i < count; ++i) {
646 id[i].status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
647 id[i].unixid, &id[i].sid);
648 if (NT_STATUS_EQUAL(id[i].status, NT_STATUS_RETRY)) {
649 id[i].status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
650 id[i].unixid,
651 &id[i].sid);
653 if (!NT_STATUS_IS_OK(id[i].status)) {
654 DEBUG(1, ("idmapping xid_to_sid failed for id[%d]\n", i));
655 error_count++;
659 if (error_count == count) {
660 /* Mapping did not work at all. */
661 return NT_STATUS_NONE_MAPPED;
662 } else if (error_count > 0) {
663 /* Some mappings worked, some did not. */
664 return STATUS_SOME_UNMAPPED;
665 } else {
666 return NT_STATUS_OK;
671 * Convert an array of SIDs to the corresponding array of unixids
673 * \param idmap_ctx idmap context to use
674 * \param mem_ctx talloc context the memory for the unixids is allocated
675 * from.
676 * \param count length of id_mapping array.
677 * \param id array of id_mappings.
678 * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
679 * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
680 * did not.
683 NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
684 TALLOC_CTX *mem_ctx, int count,
685 struct id_mapping *id)
687 int i;
688 int error_count = 0;
690 for (i = 0; i < count; ++i) {
691 id[i].status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
692 id[i].sid, &id[i].unixid);
693 if (NT_STATUS_EQUAL(id[i].status, NT_STATUS_RETRY)) {
694 id[i].status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
695 id[i].sid,
696 &id[i].unixid);
698 if (!NT_STATUS_IS_OK(id[i].status)) {
699 DEBUG(1, ("idmapping sid_to_xid failed for id[%d]\n", i));
700 error_count++;
704 if (error_count == count) {
705 /* Mapping did not work at all. */
706 return NT_STATUS_NONE_MAPPED;
707 } else if (error_count > 0) {
708 /* Some mappings worked, some did not. */
709 return STATUS_SOME_UNMAPPED;
710 } else {
711 return NT_STATUS_OK;