~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/winbind/idmap.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/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"
 
34
 
 
35
/**
 
36
 * Get uid/gid bounds from idmap database
 
37
 *
 
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
 
42
 */
 
43
static int idmap_get_bounds(struct idmap_context *idmap_ctx, uint32_t *low,
 
44
                uint32_t *high)
 
45
{
 
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;
 
53
 
 
54
        dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
 
55
        if (dn == NULL) goto failed;
 
56
 
 
57
        ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
 
58
        if (ret != LDB_SUCCESS) goto failed;
 
59
 
 
60
        if (res->count != 1) {
 
61
                ret = -1;
 
62
                goto failed;
 
63
        }
 
64
 
 
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;
 
71
        }
 
72
 
 
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;
 
78
        }
 
79
 
 
80
failed:
 
81
        talloc_free(tmp_ctx);
 
82
        *low  = lower_bound;
 
83
        *high = upper_bound;
 
84
        return ret;
 
85
}
 
86
 
 
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.
 
95
 */
 
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)
 
99
{
 
100
        struct ldb_val val;
 
101
        enum ndr_err_code ndr_err;
 
102
 
 
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);
 
107
 
 
108
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
109
                return -1;
 
110
        }
 
111
 
 
112
        return ldb_msg_add_value(msg, attr_name, &val, NULL);
 
113
}
 
114
 
 
115
/**
 
116
 * Get a dom_sid structure from a ldb message.
 
117
 *
 
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
 
122
 */
 
123
static struct dom_sid *idmap_msg_get_dom_sid(TALLOC_CTX *mem_ctx,
 
124
                struct ldb_message *msg, const char *attr_name)
 
125
{
 
126
        struct dom_sid *sid;
 
127
        const struct ldb_val *val;
 
128
        enum ndr_err_code ndr_err;
 
129
 
 
130
        val = ldb_msg_find_ldb_val(msg, attr_name);
 
131
        if (val == NULL) {
 
132
                return NULL;
 
133
        }
 
134
 
 
135
        sid = talloc(mem_ctx, struct dom_sid);
 
136
        if (sid == NULL) {
 
137
                return NULL;
 
138
        }
 
139
 
 
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;
 
145
        }
 
146
 
 
147
        return sid;
 
148
}
 
149
 
 
150
/**
 
151
 * Initialize idmap context
 
152
 *
 
153
 * talloc_free to close.
 
154
 *
 
155
 * \param mem_ctx talloc context to use.
 
156
 * \return allocated idmap_context on success, NULL on error
 
157
 */
 
158
struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
 
159
                                 struct tevent_context *ev_ctx,
 
160
                struct loadparm_context *lp_ctx)
 
161
{
 
162
        struct idmap_context *idmap_ctx;
 
163
 
 
164
        idmap_ctx = talloc(mem_ctx, struct idmap_context);
 
165
        if (idmap_ctx == NULL) {
 
166
                return NULL;
 
167
        }
 
168
 
 
169
        idmap_ctx->lp_ctx = lp_ctx;
 
170
 
 
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;
 
177
        }
 
178
 
 
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;
 
182
        }
 
183
 
 
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;
 
187
        }
 
188
 
 
189
        return idmap_ctx;
 
190
}
 
191
 
 
192
/**
 
193
 * Convert an unixid to the corresponding SID
 
194
 *
 
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.
 
203
 */
 
204
 
 
205
NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
 
206
                const struct unixid *unixid, struct dom_sid **sid)
 
207
{
 
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;
 
215
 
 
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;
 
227
        }
 
228
 
 
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;
 
236
        }
 
237
 
 
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;
 
245
                }
 
246
                talloc_free(tmp_ctx);
 
247
                return NT_STATUS_OK;
 
248
        }
 
249
 
 
250
        DEBUG(6, ("xid not found in idmap db, create S-1-22- SID.\n"));
 
251
 
 
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");
 
257
        }
 
258
        if (unix_sid == NULL) {
 
259
                status = NT_STATUS_NO_MEMORY;
 
260
                goto failed;
 
261
        }
 
262
 
 
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;
 
267
        }
 
268
 
 
269
        *sid = new_sid;
 
270
        talloc_free(tmp_ctx);
 
271
        return NT_STATUS_OK;
 
272
 
 
273
failed:
 
274
        talloc_free(tmp_ctx);
 
275
        return status;
 
276
}
 
277
 
 
278
 
 
279
/**
 
280
 * Map a SID to an unixid struct.
 
281
 *
 
282
 * If no mapping exists, a new mapping will be created.
 
283
 *
 
284
 * \todo Check if SIDs can be resolved if lp_idmap_trusted_only() == true
 
285
 * \todo Fix backwards compatibility for Samba3
 
286
 *
 
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.
 
294
 */
 
295
NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
 
296
                const struct dom_sid *sid, 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)) goto failed;
 
315
 
 
316
                *unixid = talloc(mem_ctx, struct unixid);
 
317
                if (*unixid == NULL) {
 
318
                        status = NT_STATUS_NO_MEMORY;
 
319
                        goto failed;
 
320
                }
 
321
                (*unixid)->id = rid;
 
322
                (*unixid)->type = ID_TYPE_UID;
 
323
 
 
324
                talloc_free(tmp_ctx);
 
325
                return NT_STATUS_OK;
 
326
        }
 
327
 
 
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;
 
333
 
 
334
                *unixid = talloc(mem_ctx, struct unixid);
 
335
                if (*unixid == NULL) {
 
336
                        status = NT_STATUS_NO_MEMORY;
 
337
                        goto failed;
 
338
                }
 
339
                (*unixid)->id = rid;
 
340
                (*unixid)->type = ID_TYPE_GID;
 
341
 
 
342
                talloc_free(tmp_ctx);
 
343
                return NT_STATUS_OK;
 
344
         }
 
345
 
 
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;
 
353
        }
 
354
 
 
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;
 
364
                }
 
365
 
 
366
                if (type == NULL) {
 
367
                        DEBUG(1, ("Invalid type for mapping entry.\n"));
 
368
                        status = NT_STATUS_NONE_MAPPED;
 
369
                        goto failed;
 
370
                }
 
371
 
 
372
                *unixid = talloc(mem_ctx, struct unixid);
 
373
                if (*unixid == NULL) {
 
374
                        status = NT_STATUS_NO_MEMORY;
 
375
                        goto failed;
 
376
                }
 
377
 
 
378
                (*unixid)->id = new_xid;
 
379
 
 
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;
 
386
                }
 
387
 
 
388
                talloc_free(tmp_ctx);
 
389
                return NT_STATUS_OK;
 
390
        }
 
391
 
 
392
        DEBUG(6, ("No existing mapping found, attempting to create one.\n"));
 
393
 
 
394
        trans = ldb_transaction_start(ldb);
 
395
        if (trans != LDB_SUCCESS) {
 
396
                status = NT_STATUS_NONE_MAPPED;
 
397
                goto failed;
 
398
        }
 
399
 
 
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;
 
409
        }
 
410
 
 
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;
 
415
        }
 
416
 
 
417
        /*FIXME: if lp_idmap_trusted_only() == true, check if SID can be
 
418
         * resolved here. */
 
419
 
 
420
        ret = idmap_get_bounds(idmap_ctx, &low, &high);
 
421
        if (ret != LDB_SUCCESS) {
 
422
                status = NT_STATUS_NONE_MAPPED;
 
423
                goto failed;
 
424
        }
 
425
 
 
426
        dn = ldb_dn_new(tmp_ctx, ldb, "CN=CONFIG");
 
427
        if (dn == NULL) {
 
428
                status = NT_STATUS_NO_MEMORY;
 
429
                goto failed;
 
430
        }
 
431
 
 
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;
 
437
        }
 
438
 
 
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;
 
443
        }
 
444
 
 
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;
 
451
        }
 
452
 
 
453
        if (hwm > high) {
 
454
                DEBUG(1, ("Out of xids to allocate.\n"));
 
455
                status = NT_STATUS_NONE_MAPPED;
 
456
                goto failed;
 
457
        }
 
458
 
 
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;
 
464
        }
 
465
 
 
466
        hwm_msg->dn = dn;
 
467
 
 
468
        new_xid = hwm;
 
469
        hwm++;
 
470
 
 
471
        hwm_string = talloc_asprintf(tmp_ctx, "%u", hwm);
 
472
        if (hwm_string == NULL) {
 
473
                status = NT_STATUS_NO_MEMORY;
 
474
                goto failed;
 
475
        }
 
476
 
 
477
        sid_string = dom_sid_string(tmp_ctx, sid);
 
478
        if (sid_string == NULL) {
 
479
                status = NT_STATUS_NO_MEMORY;
 
480
                goto failed;
 
481
        }
 
482
 
 
483
        unixid_string = talloc_asprintf(tmp_ctx, "%u", new_xid);
 
484
        if (unixid_string == NULL) {
 
485
                status = NT_STATUS_NO_MEMORY;
 
486
                goto failed;
 
487
        }
 
488
 
 
489
        if (hwm_entry_exists) {
 
490
                struct ldb_message_element *els;
 
491
                struct ldb_val *vals;
 
492
 
 
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;
 
498
                }
 
499
 
 
500
                vals = talloc_array(tmp_ctx, struct ldb_val, 2);
 
501
                if (els == NULL) {
 
502
                        status = NT_STATUS_NO_MEMORY;
 
503
                        goto failed;
 
504
                }
 
505
 
 
506
                hwm_msg->num_elements = 2;
 
507
                hwm_msg->elements = els;
 
508
 
 
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;
 
516
                }
 
517
 
 
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;
 
522
 
 
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;
 
533
                }
 
534
 
 
535
                ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string);
 
536
                if (ret != LDB_SUCCESS)
 
537
                {
 
538
                        status = NT_STATUS_NONE_MAPPED;
 
539
                        goto failed;
 
540
                }
 
541
        }
 
542
 
 
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;
 
549
        }
 
550
 
 
551
        map_msg = ldb_msg_new(tmp_ctx);
 
552
        if (map_msg == NULL) {
 
553
                status = NT_STATUS_NO_MEMORY;
 
554
                goto failed;
 
555
        }
 
556
 
 
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;
 
561
        }
 
562
 
 
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;
 
567
        }
 
568
 
 
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;
 
574
        }
 
575
 
 
576
        ret = ldb_msg_add_string(map_msg, "objectClass", "sidMap");
 
577
        if (ret != LDB_SUCCESS) {
 
578
                status = NT_STATUS_NONE_MAPPED;
 
579
                goto failed;
 
580
        }
 
581
 
 
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;
 
586
        }
 
587
 
 
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;
 
592
        }
 
593
 
 
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;
 
599
        }
 
600
 
 
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;
 
606
        }
 
607
 
 
608
        *unixid = talloc(mem_ctx, struct unixid);
 
609
        if (*unixid == NULL) {
 
610
                status = NT_STATUS_NO_MEMORY;
 
611
                goto failed;
 
612
        }
 
613
 
 
614
        (*unixid)->id = new_xid;
 
615
        (*unixid)->type = ID_TYPE_BOTH;
 
616
        talloc_free(tmp_ctx);
 
617
        return NT_STATUS_OK;
 
618
 
 
619
failed:
 
620
        if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb);
 
621
        talloc_free(tmp_ctx);
 
622
        return status;
 
623
}
 
624
 
 
625
/**
 
626
 * Convert an array of unixids to the corresponding array of SIDs
 
627
 *
 
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.
 
636
 */
 
637
 
 
638
NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
 
639
                            TALLOC_CTX *mem_ctx, int count,
 
640
                            struct id_mapping *id)
 
641
{
 
642
        int i;
 
643
        int error_count = 0;
 
644
 
 
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);
 
652
                }
 
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++;
 
656
                }
 
657
        }
 
658
 
 
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;
 
667
        }
 
668
}
 
669
 
 
670
/**
 
671
 * Convert an array of SIDs to the corresponding array of unixids
 
672
 *
 
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.
 
681
 */
 
682
 
 
683
NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
 
684
                            TALLOC_CTX *mem_ctx, int count,
 
685
                            struct id_mapping *id)
 
686
{
 
687
        int i;
 
688
        int error_count = 0;
 
689
 
 
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);
 
697
                }
 
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++;
 
701
                }
 
702
        }
 
703
 
 
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;
 
712
        }
 
713
}
 
714