source: vendor/current/source4/winbind/idmap.c@ 740

Last change on this file since 740 was 740, checked in by Silvan Scherrer, 12 years ago

Samba Server: update vendor to 3.6.0

File size: 18.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Map SIDs to unixids and back
5
6 Copyright (C) Kai Blin 2008
7
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.
12
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.
17
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/>.
20*/
21
22#include "includes.h"
23#include "auth/auth.h"
24#include "librpc/gen_ndr/ndr_security.h"
25#include <ldb.h>
26#include "ldb_wrap.h"
27#include "param/param.h"
28#include "winbind/idmap.h"
29#include "libcli/security/security.h"
30#include "libcli/ldap/ldap_ndr.h"
31
32/**
33 * Get uid/gid bounds from idmap database
34 *
35 * \param idmap_ctx idmap context to use
36 * \param low lower uid/gid bound is stored here
37 * \param high upper uid/gid bound is stored here
38 * \return 0 on success, nonzero on failure
39 */
40static int idmap_get_bounds(struct idmap_context *idmap_ctx, uint32_t *low,
41 uint32_t *high)
42{
43 int ret = -1;
44 struct ldb_context *ldb = idmap_ctx->ldb_ctx;
45 struct ldb_dn *dn;
46 struct ldb_result *res = NULL;
47 TALLOC_CTX *tmp_ctx = talloc_new(idmap_ctx);
48 uint32_t lower_bound = (uint32_t) -1;
49 uint32_t upper_bound = (uint32_t) -1;
50
51 dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
52 if (dn == NULL) goto failed;
53
54 ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
55 if (ret != LDB_SUCCESS) goto failed;
56
57 if (res->count != 1) {
58 ret = -1;
59 goto failed;
60 }
61
62 lower_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "lowerBound", -1);
63 if (lower_bound != (uint32_t) -1) {
64 ret = LDB_SUCCESS;
65 } else {
66 ret = -1;
67 goto failed;
68 }
69
70 upper_bound = ldb_msg_find_attr_as_uint(res->msgs[0], "upperBound", -1);
71 if (upper_bound != (uint32_t) -1) {
72 ret = LDB_SUCCESS;
73 } else {
74 ret = -1;
75 }
76
77failed:
78 talloc_free(tmp_ctx);
79 *low = lower_bound;
80 *high = upper_bound;
81 return ret;
82}
83
84/**
85 * Add a dom_sid structure to a ldb_message
86 * \param idmap_ctx idmap context to use
87 * \param mem_ctx talloc context to use
88 * \param ldb_message ldb message to add dom_sid to
89 * \param attr_name name of the attribute to store the dom_sid in
90 * \param sid dom_sid to store
91 * \return 0 on success, an ldb error code on failure.
92 */
93static int idmap_msg_add_dom_sid(struct idmap_context *idmap_ctx,
94 TALLOC_CTX *mem_ctx, struct ldb_message *msg,
95 const char *attr_name, const struct dom_sid *sid)
96{
97 struct ldb_val val;
98 enum ndr_err_code ndr_err;
99
100 ndr_err = ndr_push_struct_blob(&val, mem_ctx, sid,
101 (ndr_push_flags_fn_t)ndr_push_dom_sid);
102
103 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
104 return -1;
105 }
106
107 return ldb_msg_add_value(msg, attr_name, &val, NULL);
108}
109
110/**
111 * Get a dom_sid structure from a ldb message.
112 *
113 * \param mem_ctx talloc context to allocate dom_sid memory in
114 * \param msg ldb_message to get dom_sid from
115 * \param attr_name key that has the dom_sid as data
116 * \return dom_sid structure on success, NULL on failure
117 */
118static struct dom_sid *idmap_msg_get_dom_sid(TALLOC_CTX *mem_ctx,
119 struct ldb_message *msg, const char *attr_name)
120{
121 struct dom_sid *sid;
122 const struct ldb_val *val;
123 enum ndr_err_code ndr_err;
124
125 val = ldb_msg_find_ldb_val(msg, attr_name);
126 if (val == NULL) {
127 return NULL;
128 }
129
130 sid = talloc(mem_ctx, struct dom_sid);
131 if (sid == NULL) {
132 return NULL;
133 }
134
135 ndr_err = ndr_pull_struct_blob(val, sid, sid,
136 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
137 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
138 talloc_free(sid);
139 return NULL;
140 }
141
142 return sid;
143}
144
145/**
146 * Initialize idmap context
147 *
148 * talloc_free to close.
149 *
150 * \param mem_ctx talloc context to use.
151 * \return allocated idmap_context on success, NULL on error
152 */
153struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
154 struct tevent_context *ev_ctx,
155 struct loadparm_context *lp_ctx)
156{
157 struct idmap_context *idmap_ctx;
158
159 idmap_ctx = talloc(mem_ctx, struct idmap_context);
160 if (idmap_ctx == NULL) {
161 return NULL;
162 }
163
164 idmap_ctx->lp_ctx = lp_ctx;
165
166 idmap_ctx->ldb_ctx = ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx,
167 lpcfg_idmap_url(lp_ctx),
168 system_session(lp_ctx),
169 NULL, 0);
170 if (idmap_ctx->ldb_ctx == NULL) {
171 return NULL;
172 }
173
174 idmap_ctx->unix_groups_sid = dom_sid_parse_talloc(mem_ctx, "S-1-22-2");
175 if (idmap_ctx->unix_groups_sid == NULL) {
176 return NULL;
177 }
178
179 idmap_ctx->unix_users_sid = dom_sid_parse_talloc(mem_ctx, "S-1-22-1");
180 if (idmap_ctx->unix_users_sid == NULL) {
181 return NULL;
182 }
183
184 return idmap_ctx;
185}
186
187/**
188 * Convert an unixid to the corresponding SID
189 *
190 * \param idmap_ctx idmap context to use
191 * \param mem_ctx talloc context the memory for the struct dom_sid is allocated
192 * from.
193 * \param unixid pointer to a unixid struct to convert
194 * \param sid pointer that will take the struct dom_sid pointer if the mapping
195 * succeeds.
196 * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping not
197 * possible or some other NTSTATUS that is more descriptive on failure.
198 */
199
200static NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx,
201 TALLOC_CTX *mem_ctx,
202 const struct unixid *unixid,
203 struct dom_sid **sid)
204{
205 int ret;
206 NTSTATUS status = NT_STATUS_NONE_MAPPED;
207 struct ldb_context *ldb = idmap_ctx->ldb_ctx;
208 struct ldb_result *res = NULL;
209 struct dom_sid *unix_sid, *new_sid;
210 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
211 const char *id_type;
212
213 switch (unixid->type) {
214 case ID_TYPE_UID:
215 id_type = "ID_TYPE_UID";
216 break;
217 case ID_TYPE_GID:
218 id_type = "ID_TYPE_GID";
219 break;
220 default:
221 DEBUG(1, ("unixid->type must be type gid or uid (got %u) for lookup with id %lu\n",
222 (unsigned)unixid->type, (unsigned long)unixid->id));
223 status = NT_STATUS_NONE_MAPPED;
224 goto failed;
225 }
226
227 ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
228 NULL, "(&(|(type=ID_TYPE_BOTH)(type=%s))"
229 "(xidNumber=%u))", id_type, unixid->id);
230 if (ret != LDB_SUCCESS) {
231 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
232 status = NT_STATUS_NONE_MAPPED;
233 goto failed;
234 }
235
236 if (res->count == 1) {
237 *sid = idmap_msg_get_dom_sid(mem_ctx, res->msgs[0],
238 "objectSid");
239 if (*sid == NULL) {
240 DEBUG(1, ("Failed to get sid from db: %u\n", ret));
241 status = NT_STATUS_NONE_MAPPED;
242 goto failed;
243 }
244 talloc_free(tmp_ctx);
245 return NT_STATUS_OK;
246 }
247
248 DEBUG(6, ("xid not found in idmap db, create S-1-22- SID.\n"));
249
250 /* For local users/groups , we just create a rid = uid/gid */
251 if (unixid->type == ID_TYPE_UID) {
252 unix_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-1");
253 } else {
254 unix_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-22-2");
255 }
256 if (unix_sid == NULL) {
257 status = NT_STATUS_NO_MEMORY;
258 goto failed;
259 }
260
261 new_sid = dom_sid_add_rid(mem_ctx, unix_sid, unixid->id);
262 if (new_sid == NULL) {
263 status = NT_STATUS_NO_MEMORY;
264 goto failed;
265 }
266
267 *sid = new_sid;
268 talloc_free(tmp_ctx);
269 return NT_STATUS_OK;
270
271failed:
272 talloc_free(tmp_ctx);
273 return status;
274}
275
276
277/**
278 * Map a SID to an unixid struct.
279 *
280 * If no mapping exists, a new mapping will be created.
281 *
282 * \todo Check if SIDs can be resolved if lpcfg_idmap_trusted_only() == true
283 * \todo Fix backwards compatibility for Samba3
284 *
285 * \param idmap_ctx idmap context to use
286 * \param mem_ctx talloc context to use
287 * \param sid SID to map to an unixid struct
288 * \param unixid pointer to a unixid struct
289 * \return NT_STATUS_OK on success, NT_STATUS_INVALID_SID if the sid is not from
290 * a trusted domain and idmap trusted only = true, NT_STATUS_NONE_MAPPED if the
291 * mapping failed.
292 */
293static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx,
294 TALLOC_CTX *mem_ctx,
295 const struct dom_sid *sid,
296 struct unixid *unixid)
297{
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);
309
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)) {
315 talloc_free(tmp_ctx);
316 return status;
317 }
318
319 unixid->id = rid;
320 unixid->type = ID_TYPE_UID;
321
322 talloc_free(tmp_ctx);
323 return NT_STATUS_OK;
324 }
325
326 if (dom_sid_in_domain(idmap_ctx->unix_groups_sid, sid)) {
327 uint32_t rid;
328 DEBUG(6, ("This is a local unix gid, just calculate that.\n"));
329 status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
330 if (!NT_STATUS_IS_OK(status)) {
331 talloc_free(tmp_ctx);
332 return status;
333 }
334
335 unixid->id = rid;
336 unixid->type = ID_TYPE_GID;
337
338 talloc_free(tmp_ctx);
339 return NT_STATUS_OK;
340 }
341
342 ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
343 NULL, "(&(objectClass=sidMap)(objectSid=%s))",
344 ldap_encode_ndr_dom_sid(tmp_ctx, sid));
345 if (ret != LDB_SUCCESS) {
346 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
347 talloc_free(tmp_ctx);
348 return NT_STATUS_NONE_MAPPED;
349 }
350
351 if (res->count == 1) {
352 const char *type = ldb_msg_find_attr_as_string(res->msgs[0],
353 "type", NULL);
354 new_xid = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber",
355 -1);
356 if (new_xid == (uint32_t) -1) {
357 DEBUG(1, ("Invalid xid mapping.\n"));
358 talloc_free(tmp_ctx);
359 return NT_STATUS_NONE_MAPPED;
360 }
361
362 if (type == NULL) {
363 DEBUG(1, ("Invalid type for mapping entry.\n"));
364 talloc_free(tmp_ctx);
365 return NT_STATUS_NONE_MAPPED;
366 }
367
368 unixid->id = new_xid;
369
370 if (strcmp(type, "ID_TYPE_BOTH") == 0) {
371 unixid->type = ID_TYPE_BOTH;
372 } else if (strcmp(type, "ID_TYPE_UID") == 0) {
373 unixid->type = ID_TYPE_UID;
374 } else {
375 unixid->type = ID_TYPE_GID;
376 }
377
378 talloc_free(tmp_ctx);
379 return NT_STATUS_OK;
380 }
381
382 DEBUG(6, ("No existing mapping found, attempting to create one.\n"));
383
384 trans = ldb_transaction_start(ldb);
385 if (trans != LDB_SUCCESS) {
386 status = NT_STATUS_NONE_MAPPED;
387 goto failed;
388 }
389
390 /* Redo the search to make sure noone changed the mapping while we
391 * weren't looking */
392 ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
393 NULL, "(&(objectClass=sidMap)(objectSid=%s))",
394 ldap_encode_ndr_dom_sid(tmp_ctx, sid));
395 if (ret != LDB_SUCCESS) {
396 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
397 status = NT_STATUS_NONE_MAPPED;
398 goto failed;
399 }
400
401 if (res->count > 0) {
402 DEBUG(1, ("Database changed while trying to add a sidmap.\n"));
403 status = NT_STATUS_RETRY;
404 goto failed;
405 }
406
407 /*FIXME: if lpcfg_idmap_trusted_only() == true, check if SID can be
408 * resolved here. */
409
410 ret = idmap_get_bounds(idmap_ctx, &low, &high);
411 if (ret != LDB_SUCCESS) {
412 status = NT_STATUS_NONE_MAPPED;
413 goto failed;
414 }
415
416 dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
417 if (dn == NULL) {
418 status = NT_STATUS_NO_MEMORY;
419 goto failed;
420 }
421
422 ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
423 if (ret != LDB_SUCCESS) {
424 DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
425 status = NT_STATUS_NONE_MAPPED;
426 goto failed;
427 }
428
429 if (res->count != 1) {
430 DEBUG(1, ("No CN=CONFIG record, idmap database is broken.\n"));
431 status = NT_STATUS_NONE_MAPPED;
432 goto failed;
433 }
434
435 hwm = ldb_msg_find_attr_as_uint(res->msgs[0], "xidNumber", -1);
436 if (hwm == (uint32_t)-1) {
437 hwm = low;
438 hwm_entry_exists = false;
439 } else {
440 hwm_entry_exists = true;
441 }
442
443 if (hwm > high) {
444 DEBUG(1, ("Out of xids to allocate.\n"));
445 status = NT_STATUS_NONE_MAPPED;
446 goto failed;
447 }
448
449 hwm_msg = ldb_msg_new(tmp_ctx);
450 if (hwm_msg == NULL) {
451 DEBUG(1, ("Out of memory when creating ldb_message\n"));
452 status = NT_STATUS_NO_MEMORY;
453 goto failed;
454 }
455
456 hwm_msg->dn = dn;
457
458 new_xid = hwm;
459 hwm++;
460
461 hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm);
462 if (hwm_string == NULL) {
463 status = NT_STATUS_NO_MEMORY;
464 goto failed;
465 }
466
467 sid_string = dom_sid_string(tmp_ctx, sid);
468 if (sid_string == NULL) {
469 status = NT_STATUS_NO_MEMORY;
470 goto failed;
471 }
472
473 unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid);
474 if (unixid_string == NULL) {
475 status = NT_STATUS_NO_MEMORY;
476 goto failed;
477 }
478
479 if (hwm_entry_exists) {
480 struct ldb_message_element *els;
481 struct ldb_val *vals;
482
483 /* We're modifying the entry, not just adding a new one. */
484 els = talloc_array(tmp_ctx, struct ldb_message_element, 2);
485 if (els == NULL) {
486 status = NT_STATUS_NO_MEMORY;
487 goto failed;
488 }
489
490 vals = talloc_array(tmp_ctx, struct ldb_val, 2);
491 if (els == NULL) {
492 status = NT_STATUS_NO_MEMORY;
493 goto failed;
494 }
495
496 hwm_msg->num_elements = 2;
497 hwm_msg->elements = els;
498
499 els[0].num_values = 1;
500 els[0].values = &vals[0];
501 els[0].flags = LDB_FLAG_MOD_DELETE;
502 els[0].name = talloc_strdup(tmp_ctx, "xidNumber");
503 if (els[0].name == NULL) {
504 status = NT_STATUS_NO_MEMORY;
505 goto failed;
506 }
507
508 els[1].num_values = 1;
509 els[1].values = &vals[1];
510 els[1].flags = LDB_FLAG_MOD_ADD;
511 els[1].name = els[0].name;
512
513 vals[0].data = (uint8_t *)unixid_string;
514 vals[0].length = strlen(unixid_string);
515 vals[1].data = (uint8_t *)hwm_string;
516 vals[1].length = strlen(hwm_string);
517 } else {
518 ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD,
519 NULL);
520 if (ret != LDB_SUCCESS) {
521 status = NT_STATUS_NONE_MAPPED;
522 goto failed;
523 }
524
525 ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string);
526 if (ret != LDB_SUCCESS)
527 {
528 status = NT_STATUS_NONE_MAPPED;
529 goto failed;
530 }
531 }
532
533 ret = ldb_modify(ldb, hwm_msg);
534 if (ret != LDB_SUCCESS) {
535 DEBUG(1, ("Updating the xid high water mark failed: %s\n",
536 ldb_errstring(ldb)));
537 status = NT_STATUS_NONE_MAPPED;
538 goto failed;
539 }
540
541 map_msg = ldb_msg_new(tmp_ctx);
542 if (map_msg == NULL) {
543 status = NT_STATUS_NO_MEMORY;
544 goto failed;
545 }
546
547 map_msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s", sid_string);
548 if (map_msg->dn == NULL) {
549 status = NT_STATUS_NO_MEMORY;
550 goto failed;
551 }
552
553 ret = ldb_msg_add_string(map_msg, "xidNumber", unixid_string);
554 if (ret != LDB_SUCCESS) {
555 status = NT_STATUS_NONE_MAPPED;
556 goto failed;
557 }
558
559 ret = idmap_msg_add_dom_sid(idmap_ctx, tmp_ctx, map_msg, "objectSid",
560 sid);
561 if (ret != LDB_SUCCESS) {
562 status = NT_STATUS_NONE_MAPPED;
563 goto failed;
564 }
565
566 ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap");
567 if (ret != LDB_SUCCESS) {
568 status = NT_STATUS_NONE_MAPPED;
569 goto failed;
570 }
571
572 ret = ldb_msg_add_string(map_msg, "type", "ID_TYPE_BOTH");
573 if (ret != LDB_SUCCESS) {
574 status = NT_STATUS_NONE_MAPPED;
575 goto failed;
576 }
577
578 ret = ldb_msg_add_string(map_msg, "cn", sid_string);
579 if (ret != LDB_SUCCESS) {
580 status = NT_STATUS_NONE_MAPPED;
581 goto failed;
582 }
583
584 ret = ldb_add(ldb, map_msg);
585 if (ret != LDB_SUCCESS) {
586 DEBUG(1, ("Adding a sidmap failed: %s\n", ldb_errstring(ldb)));
587 status = NT_STATUS_NONE_MAPPED;
588 goto failed;
589 }
590
591 trans = ldb_transaction_commit(ldb);
592 if (trans != LDB_SUCCESS) {
593 DEBUG(1, ("Transaction failed: %s\n", ldb_errstring(ldb)));
594 status = NT_STATUS_NONE_MAPPED;
595 goto failed;
596 }
597
598 unixid->id = new_xid;
599 unixid->type = ID_TYPE_BOTH;
600 talloc_free(tmp_ctx);
601 return NT_STATUS_OK;
602
603failed:
604 if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb);
605 talloc_free(tmp_ctx);
606 return status;
607}
608
609/**
610 * Convert an array of unixids to the corresponding array of SIDs
611 *
612 * \param idmap_ctx idmap context to use
613 * \param mem_ctx talloc context the memory for the dom_sids is allocated
614 * from.
615 * \param count length of id_mapping array.
616 * \param id array of id_mappings.
617 * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
618 * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
619 * did not.
620 */
621
622NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
623 TALLOC_CTX *mem_ctx,
624 struct id_map **id)
625{
626 unsigned int i, error_count = 0;
627 NTSTATUS status;
628
629 for (i = 0; id && id[i]; i++) {
630 status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
631 &id[i]->xid, &id[i]->sid);
632 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
633 status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
634 &id[i]->xid,
635 &id[i]->sid);
636 }
637 if (!NT_STATUS_IS_OK(status)) {
638 DEBUG(1, ("idmapping xid_to_sid failed for id[%d]=%lu: %s\n",
639 i, (unsigned long)id[i]->xid.id, nt_errstr(status)));
640 error_count++;
641 id[i]->status = ID_UNMAPPED;
642 } else {
643 id[i]->status = ID_MAPPED;
644 }
645 }
646
647 if (error_count == i) {
648 /* Mapping did not work at all. */
649 return NT_STATUS_NONE_MAPPED;
650 } else if (error_count > 0) {
651 /* Some mappings worked, some did not. */
652 return STATUS_SOME_UNMAPPED;
653 } else {
654 return NT_STATUS_OK;
655 }
656}
657
658/**
659 * Convert an array of SIDs to the corresponding array of unixids
660 *
661 * \param idmap_ctx idmap context to use
662 * \param mem_ctx talloc context the memory for the unixids is allocated
663 * from.
664 * \param count length of id_mapping array.
665 * \param id array of id_mappings.
666 * \return NT_STATUS_OK on success, NT_STATUS_NONE_MAPPED if mapping is not
667 * possible at all, NT_STATUS_SOME_UNMAPPED if some mappings worked and some
668 * did not.
669 */
670
671NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
672 TALLOC_CTX *mem_ctx,
673 struct id_map **id)
674{
675 unsigned int i, error_count = 0;
676 NTSTATUS status;
677
678 for (i = 0; id && id[i]; i++) {
679 status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
680 id[i]->sid, &id[i]->xid);
681 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
682 status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
683 id[i]->sid,
684 &id[i]->xid);
685 }
686 if (!NT_STATUS_IS_OK(status)) {
687 char *str = dom_sid_string(mem_ctx, id[i]->sid);
688 DEBUG(1, ("idmapping sid_to_xid failed for id[%d]=%s: %s\n",
689 i, str, nt_errstr(status)));
690 talloc_free(str);
691 error_count++;
692 id[i]->status = ID_UNMAPPED;
693 } else {
694 id[i]->status = ID_MAPPED;
695 }
696 }
697
698 if (error_count == i) {
699 /* Mapping did not work at all. */
700 return NT_STATUS_NONE_MAPPED;
701 } else if (error_count > 0) {
702 /* Some mappings worked, some did not. */
703 return STATUS_SOME_UNMAPPED;
704 } else {
705 return NT_STATUS_OK;
706 }
707}
708
Note: See TracBrowser for help on using the repository browser.