~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/groupdb/mapping_ldb.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
 *  group mapping code on top of ldb
 
5
 *
 
6
 *  Copyright (C) Andrew Tridgell              2006
 
7
 *
 
8
 * based on tdb group mapping code from groupdb/mapping.c
 
9
 *  
 
10
 *  This program is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU General Public License as published by
 
12
 *  the Free Software Foundation; either version 3 of the License, or
 
13
 *  (at your option) any later version.
 
14
 *  
 
15
 *  This program is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU General Public License for more details.
 
19
 *  
 
20
 *  You should have received a copy of the GNU General Public License
 
21
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
22
 */
 
23
 
 
24
#include "includes.h"
 
25
#include "groupdb/mapping.h"
 
26
#include "lib/ldb/include/includes.h"
 
27
#include "lib/ldb/include/ldb_errors.h"
 
28
 
 
29
static struct ldb_context *ldb;
 
30
 
 
31
static bool mapping_upgrade(const char *tdb_path);
 
32
 
 
33
/*
 
34
  connect to the group mapping ldb
 
35
*/
 
36
static bool init_group_mapping(void)
 
37
{
 
38
        bool existed;
 
39
        const char *init_ldif[] = 
 
40
                { "dn: @ATTRIBUTES\n" \
 
41
                  "ntName: CASE_INSENSITIVE\n" \
 
42
                  "\n",
 
43
                  "dn: @INDEXLIST\n" \
 
44
                  "@IDXATTR: gidNumber\n" \
 
45
                  "@IDXATTR: ntName\n" \
 
46
                  "@IDXATTR: member\n" };
 
47
        const char *db_path, *tdb_path;
 
48
        int ret;
 
49
        int flags = 0;
 
50
 
 
51
        if (ldb != NULL) {
 
52
                return True;
 
53
        }
 
54
 
 
55
        /* this is needed as Samba3 doesn't have this globally yet */
 
56
        ldb_global_init();
 
57
 
 
58
        db_path = state_path("group_mapping.ldb");
 
59
 
 
60
        ldb = ldb_init(NULL);
 
61
        if (ldb == NULL) goto failed;
 
62
 
 
63
        /* Ensure this db is created read/write for root only. */
 
64
        ldb_set_create_perms(ldb, 0600);
 
65
 
 
66
        existed = file_exist(db_path);
 
67
 
 
68
        if (lp_parm_bool(-1, "groupmap", "nosync", False)) {
 
69
                flags |= LDB_FLG_NOSYNC;
 
70
        }
 
71
 
 
72
        if (!lp_use_mmap()) {
 
73
                flags |= LDB_FLG_NOMMAP;
 
74
        }
 
75
 
 
76
        ret = ldb_connect(ldb, db_path, flags, NULL);
 
77
        if (ret != LDB_SUCCESS) {
 
78
                goto failed;
 
79
        }
 
80
 
 
81
        /* force the permissions on the ldb to 0600 - this will fix
 
82
           existing databases as well as new ones */
 
83
        if (chmod(db_path, 0600) != 0) {
 
84
                goto failed;
 
85
        }
 
86
 
 
87
        if (!existed) {
 
88
                /* initialise the ldb with an index */
 
89
                struct ldb_ldif *ldif;
 
90
                int i;
 
91
                for (i=0;i<ARRAY_SIZE(init_ldif);i++) {
 
92
                        ldif = ldb_ldif_read_string(ldb, &init_ldif[i]);
 
93
                        if (ldif == NULL) goto failed;
 
94
                        ret = ldb_add(ldb, ldif->msg);
 
95
                        talloc_free(ldif);
 
96
                        if (ret == -1) goto failed;
 
97
                }
 
98
        }
 
99
 
 
100
        /* possibly upgrade */
 
101
        tdb_path = state_path("group_mapping.tdb");
 
102
        if (file_exist(tdb_path) && !mapping_upgrade(tdb_path)) {
 
103
                unlink(state_path("group_mapping.ldb"));
 
104
                goto failed;
 
105
        }
 
106
 
 
107
        return True;
 
108
 
 
109
failed:
 
110
        DEBUG(0,("Failed to open group mapping ldb '%s' - '%s'\n",
 
111
                 db_path, ldb?ldb_errstring(ldb):strerror(errno)));
 
112
        talloc_free(ldb);
 
113
        ldb = NULL;
 
114
        return False;
 
115
}
 
116
 
 
117
 
 
118
/*
 
119
  form the DN for a mapping entry from a SID
 
120
 */
 
121
static struct ldb_dn *mapping_dn(TALLOC_CTX *mem_ctx, const DOM_SID *sid)
 
122
{
 
123
        fstring string_sid;
 
124
        uint32_t rid;
 
125
        DOM_SID domsid;
 
126
 
 
127
        sid_copy(&domsid, sid);
 
128
        if (!sid_split_rid(&domsid, &rid)) {
 
129
                return NULL;
 
130
        }
 
131
        if (!sid_to_fstring(string_sid, &domsid)) {
 
132
                return NULL;
 
133
        }
 
134
        /* we split by domain and rid so we can do a subtree search
 
135
           when we only want one domain */
 
136
        return ldb_dn_string_compose(mem_ctx, NULL, "rid=%u,domain=%s", 
 
137
                                     rid, string_sid);
 
138
}
 
139
 
 
140
/*
 
141
  add a group mapping entry
 
142
 */
 
143
static bool add_mapping_entry(GROUP_MAP *map, int flag)
 
144
{
 
145
        struct ldb_message *msg;        
 
146
        int ret, i;
 
147
        fstring string_sid;
 
148
 
 
149
        msg = ldb_msg_new(ldb);
 
150
        if (msg == NULL) {
 
151
                return False;
 
152
        }
 
153
 
 
154
        msg->dn = mapping_dn(msg, &map->sid);
 
155
        if (msg->dn == NULL) {
 
156
                goto failed;
 
157
        }
 
158
 
 
159
        if (ldb_msg_add_string(msg, "objectClass", "groupMap") != LDB_SUCCESS ||
 
160
            ldb_msg_add_string(msg, "sid", 
 
161
                               sid_to_fstring(string_sid, &map->sid)) != LDB_SUCCESS ||
 
162
            ldb_msg_add_fmt(msg, "gidNumber", "%u", (unsigned)map->gid) != LDB_SUCCESS ||
 
163
            ldb_msg_add_fmt(msg, "sidNameUse", "%u", (unsigned)map->sid_name_use) != LDB_SUCCESS ||
 
164
            ldb_msg_add_string(msg, "comment", map->comment) != LDB_SUCCESS ||
 
165
            ldb_msg_add_string(msg, "ntName", map->nt_name) != LDB_SUCCESS) {
 
166
                goto failed;
 
167
        }
 
168
 
 
169
        ret = ldb_add(ldb, msg);
 
170
 
 
171
        /* if it exists we update it. This is a hangover from the semantics the
 
172
           tdb backend had */
 
173
        if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
 
174
                for (i=0;i<msg->num_elements;i++) {
 
175
                        msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
 
176
                }
 
177
                ret = ldb_modify(ldb, msg);
 
178
        }
 
179
 
 
180
        talloc_free(msg);
 
181
 
 
182
        return ret == LDB_SUCCESS;
 
183
 
 
184
failed:
 
185
        talloc_free(msg);
 
186
        return False;
 
187
}
 
188
 
 
189
/*
 
190
  unpack a ldb message into a GROUP_MAP structure
 
191
*/
 
192
static bool msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
 
193
{
 
194
        const char *sidstr;
 
195
 
 
196
        map->gid          = ldb_msg_find_attr_as_int(msg, "gidNumber", -1);
 
197
        map->sid_name_use = ldb_msg_find_attr_as_int(msg, "sidNameUse", -1);
 
198
        fstrcpy(map->nt_name, ldb_msg_find_attr_as_string(msg, "ntName", NULL));
 
199
        fstrcpy(map->comment, ldb_msg_find_attr_as_string(msg, "comment", NULL));
 
200
        sidstr = ldb_msg_find_attr_as_string(msg, "sid", NULL);
 
201
 
 
202
        if (!string_to_sid(&map->sid, sidstr) ||
 
203
            map->gid == (gid_t)-1 ||
 
204
            map->sid_name_use == (enum lsa_SidType)-1) {
 
205
                DEBUG(0,("Unable to unpack group mapping\n"));
 
206
                return False;
 
207
        }
 
208
 
 
209
        return True;
 
210
}
 
211
 
 
212
/*
 
213
 return a group map entry for a given sid
 
214
*/
 
215
static bool get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
 
216
{
 
217
        int ret;
 
218
        struct ldb_dn *dn;
 
219
        struct ldb_result *res=NULL;
 
220
        bool result = false;
 
221
 
 
222
        dn = mapping_dn(talloc_tos(), &sid);
 
223
        if (dn == NULL) {
 
224
                goto failed;
 
225
        }
 
226
 
 
227
        ret = ldb_search(ldb, dn, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
 
228
        if (ret != LDB_SUCCESS || res->count != 1) {
 
229
                goto failed;
 
230
        }
 
231
 
 
232
        if (!msg_to_group_map(res->msgs[0], map)) {
 
233
                goto failed;
 
234
        }
 
235
 
 
236
        result = true;
 
237
 failed:
 
238
        talloc_free(dn);
 
239
        return result;
 
240
}
 
241
 
 
242
/*
 
243
 return a group map entry for a given gid
 
244
*/
 
245
static bool get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
 
246
{
 
247
        int ret;
 
248
        struct ldb_result *res=NULL;
 
249
        bool result = false;
 
250
 
 
251
        ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
 
252
                         NULL, "(&(gidNumber=%u)(objectClass=groupMap))",
 
253
                         (unsigned)gid);
 
254
        if (ret != LDB_SUCCESS || res->count != 1) {
 
255
                goto failed;
 
256
        }
 
257
 
 
258
        if (!msg_to_group_map(res->msgs[0], map)) {
 
259
                goto failed;
 
260
        }
 
261
 
 
262
        result = true;
 
263
failed:
 
264
        TALLOC_FREE(res);
 
265
        return result;
 
266
}
 
267
 
 
268
/*
 
269
  Return the sid and the type of the unix group.
 
270
*/
 
271
static bool get_group_map_from_ntname(const char *name, GROUP_MAP *map)
 
272
{
 
273
        int ret;
 
274
        struct ldb_result *res=NULL;
 
275
        bool result = false;
 
276
 
 
277
        ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
 
278
                         NULL, "(&(ntName=%s)(objectClass=groupMap))", name);
 
279
        if (ret != LDB_SUCCESS || res->count != 1) {
 
280
                goto failed;
 
281
        }
 
282
 
 
283
        if (!msg_to_group_map(res->msgs[0], map)) {
 
284
                goto failed;
 
285
        }
 
286
 
 
287
        result = true;
 
288
 failed:
 
289
        TALLOC_FREE(res);
 
290
        return result;
 
291
}
 
292
 
 
293
/*
 
294
 Remove a group mapping entry.
 
295
*/
 
296
static bool group_map_remove(const DOM_SID *sid)
 
297
{
 
298
        struct ldb_dn *dn;
 
299
        int ret;
 
300
        
 
301
        dn = mapping_dn(ldb, sid);
 
302
        if (dn == NULL) {
 
303
                return False;
 
304
        }
 
305
        ret = ldb_delete(ldb, dn);
 
306
        talloc_free(dn);
 
307
 
 
308
        return ret == LDB_SUCCESS;
 
309
}
 
310
 
 
311
 
 
312
/*
 
313
  Enumerate the group mappings for a domain
 
314
*/
 
315
static bool enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use, 
 
316
                               GROUP_MAP **pp_rmap,
 
317
                               size_t *p_num_entries, bool unix_only)
 
318
{
 
319
        int i, ret;
 
320
        fstring name;
 
321
        struct ldb_result *res = NULL;
 
322
        struct ldb_dn *basedn=NULL;
 
323
        TALLOC_CTX *tmp_ctx;
 
324
 
 
325
        tmp_ctx = talloc_new(ldb);
 
326
        if (tmp_ctx == NULL) goto failed;
 
327
 
 
328
        /* we do a subtree search on the domain */
 
329
        if (domsid != NULL) {
 
330
                sid_to_fstring(name, domsid);
 
331
                basedn = ldb_dn_string_compose(tmp_ctx, NULL, "domain=%s", name);
 
332
                if (basedn == NULL) goto failed;
 
333
        }
 
334
 
 
335
        if (sid_name_use == SID_NAME_UNKNOWN) {
 
336
                ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
 
337
                                 NULL, "(&(objectClass=groupMap))");
 
338
        } else {
 
339
                ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
 
340
                                 NULL, "(&(sidNameUse=%u)(objectClass=groupMap))",
 
341
                                 sid_name_use);
 
342
        }
 
343
 
 
344
        if (ret != LDB_SUCCESS) goto failed;
 
345
 
 
346
        (*pp_rmap) = NULL;
 
347
        *p_num_entries = 0;
 
348
 
 
349
        for (i=0;i<res->count;i++) {
 
350
                (*pp_rmap) = SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, 
 
351
                                               (*p_num_entries)+1);
 
352
                if (!(*pp_rmap)) goto failed;
 
353
 
 
354
                if (!msg_to_group_map(res->msgs[i], &(*pp_rmap)[*p_num_entries])) {
 
355
                        goto failed;
 
356
                }
 
357
 
 
358
                (*p_num_entries)++;
 
359
        }
 
360
 
 
361
        talloc_free(tmp_ctx);
 
362
        return True;
 
363
 
 
364
failed:
 
365
        talloc_free(tmp_ctx);
 
366
        return False;   
 
367
}
 
368
 
 
369
/* 
 
370
   This operation happens on session setup, so it should better be fast. We
 
371
   store a list of aliases a SID is member of hanging off MEMBEROF/SID. 
 
372
*/
 
373
static NTSTATUS one_alias_membership(const DOM_SID *member,
 
374
                                     DOM_SID **sids, size_t *num)
 
375
{
 
376
        const char *attrs[] = {
 
377
                "sid",
 
378
                NULL
 
379
        };
 
380
        DOM_SID alias;
 
381
        int ret, i;
 
382
        struct ldb_result *res=NULL;
 
383
        fstring string_sid;
 
384
        NTSTATUS status;
 
385
 
 
386
        if (!sid_to_fstring(string_sid, member)) {
 
387
                return NT_STATUS_INVALID_PARAMETER;
 
388
        }
 
389
 
 
390
        ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
 
391
                         attrs, "(&(member=%s)(objectClass=groupMap))",
 
392
                         string_sid);
 
393
        if (ret != LDB_SUCCESS) {
 
394
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
395
                goto failed;
 
396
        }
 
397
 
 
398
        for (i=0;i<res->count;i++) {
 
399
                struct ldb_message_element *el;
 
400
                el = ldb_msg_find_element(res->msgs[i], "sid");
 
401
                if (el == NULL || el->num_values != 1) {
 
402
                        status = NT_STATUS_INTERNAL_DB_CORRUPTION;
 
403
                        goto failed;
 
404
                }
 
405
                string_to_sid(&alias, (char *)el->values[0].data);
 
406
                status = add_sid_to_array_unique(NULL, &alias, sids, num);
 
407
                if (!NT_STATUS_IS_OK(status)) {
 
408
                        goto failed;
 
409
                }
 
410
        }
 
411
 
 
412
        status = NT_STATUS_OK;
 
413
 failed:
 
414
        TALLOC_FREE(res);
 
415
        return status;
 
416
}
 
417
 
 
418
/*
 
419
  add/remove a member field
 
420
*/
 
421
static NTSTATUS modify_aliasmem(const DOM_SID *alias, const DOM_SID *member,
 
422
                                int operation)
 
423
{
 
424
        fstring string_sid;
 
425
        int ret;
 
426
        struct ldb_message msg;
 
427
        struct ldb_message_element el;
 
428
        struct ldb_val val;
 
429
        TALLOC_CTX *tmp_ctx;
 
430
        GROUP_MAP map;
 
431
 
 
432
        if (!get_group_map_from_sid(*alias, &map)) {
 
433
                sid_to_fstring(string_sid, alias);
 
434
                return NT_STATUS_NO_SUCH_ALIAS;
 
435
        }
 
436
 
 
437
        if ((map.sid_name_use != SID_NAME_ALIAS) &&
 
438
            (map.sid_name_use != SID_NAME_WKN_GRP)) {
 
439
                DEBUG(0,("sid_name_use=%d\n", map.sid_name_use));
 
440
                return NT_STATUS_NO_SUCH_ALIAS;
 
441
        }
 
442
 
 
443
        tmp_ctx = talloc_new(NULL);
 
444
        if (tmp_ctx == NULL) {
 
445
                return NT_STATUS_NO_MEMORY;
 
446
        }
 
447
 
 
448
        msg.dn = mapping_dn(tmp_ctx, alias);
 
449
        if (msg.dn == NULL) {
 
450
                return NT_STATUS_NO_MEMORY;
 
451
        }
 
452
        msg.num_elements = 1;
 
453
        msg.elements = &el;
 
454
        el.flags = operation;
 
455
        el.name = talloc_strdup(tmp_ctx, "member");
 
456
        el.num_values = 1;
 
457
        el.values = &val;
 
458
        sid_to_fstring(string_sid, member);
 
459
        val.data = (uint8_t *)string_sid;
 
460
        val.length = strlen(string_sid);
 
461
 
 
462
        ret = ldb_modify(ldb, &msg);
 
463
        talloc_free(tmp_ctx);
 
464
 
 
465
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 
466
                return NT_STATUS_NO_SUCH_ALIAS;
 
467
        }
 
468
 
 
469
        if (operation == LDB_FLAG_MOD_ADD &&
 
470
            ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
 
471
                return NT_STATUS_MEMBER_IN_ALIAS;
 
472
        }
 
473
 
 
474
        return (ret == LDB_SUCCESS ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED);
 
475
}
 
476
 
 
477
static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
 
478
{
 
479
        return modify_aliasmem(alias, member, LDB_FLAG_MOD_ADD);
 
480
}
 
481
 
 
482
static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
 
483
{
 
484
        return modify_aliasmem(alias, member, LDB_FLAG_MOD_DELETE);
 
485
}
 
486
 
 
487
 
 
488
/*
 
489
  enumerate sids that have the given alias set in member
 
490
*/
 
491
static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
 
492
{
 
493
        const char *attrs[] = {
 
494
                "member",
 
495
                NULL
 
496
        };
 
497
        int ret, i;
 
498
        NTSTATUS status = NT_STATUS_OK;
 
499
        struct ldb_result *res=NULL;
 
500
        struct ldb_dn *dn;
 
501
        struct ldb_message_element *el;
 
502
        
 
503
        *sids = NULL;
 
504
        *num = 0;
 
505
 
 
506
        dn = mapping_dn(ldb, alias);
 
507
        if (dn == NULL) {
 
508
                return NT_STATUS_NO_MEMORY;
 
509
        }
 
510
 
 
511
        ret = ldb_search(ldb, ldb, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
 
512
        if (ret == LDB_SUCCESS && res->count == 0) {
 
513
                talloc_free(res);
 
514
                talloc_free(dn);
 
515
                return NT_STATUS_OK;
 
516
        }
 
517
        if (ret != LDB_SUCCESS) {
 
518
                talloc_free(dn);
 
519
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
520
        }
 
521
 
 
522
        talloc_steal(dn, res);
 
523
        el = ldb_msg_find_element(res->msgs[0], "member");
 
524
        if (el == NULL) {
 
525
                talloc_free(dn);
 
526
                return NT_STATUS_OK;
 
527
        }
 
528
        
 
529
        for (i=0;i<el->num_values;i++) {
 
530
                DOM_SID sid;
 
531
                string_to_sid(&sid, (const char *)el->values[i].data);
 
532
                status = add_sid_to_array_unique(NULL, &sid, sids, num);
 
533
                if (!NT_STATUS_IS_OK(status)) {
 
534
                        goto done;
 
535
                }
 
536
        }
 
537
 
 
538
done:
 
539
        talloc_free(dn);
 
540
        return status;
 
541
}
 
542
 
 
543
/*
 
544
  upgrade one group mapping record from the old tdb format
 
545
*/
 
546
static int upgrade_map_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key, 
 
547
                              TDB_DATA data, void *state)
 
548
{
 
549
        int ret;
 
550
        GROUP_MAP map;
 
551
 
 
552
        if (strncmp((char *)key.dptr, GROUP_PREFIX, 
 
553
                    MIN(key.dsize, strlen(GROUP_PREFIX))) != 0) {
 
554
                return 0;
 
555
        }
 
556
 
 
557
        if (!string_to_sid(&map.sid, strlen(GROUP_PREFIX) + (const char *)key.dptr)) {
 
558
                DEBUG(0,("Bad sid key '%s' during upgrade\n", (const char *)key.dptr));
 
559
                *(int *)state = -1;
 
560
                return -1;
 
561
        }
 
562
 
 
563
        ret = tdb_unpack(data.dptr, data.dsize, "ddff",
 
564
                         &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
 
565
        if (ret == -1) {
 
566
                DEBUG(0,("Failed to unpack group map record during upgrade\n"));
 
567
                *(int *)state = -1;
 
568
                return -1;
 
569
        }
 
570
 
 
571
        if ((int)map.gid == -1) {
 
572
                /*
 
573
                 * Ignore old invalid mappings
 
574
                 */
 
575
                return 0;
 
576
        }
 
577
 
 
578
        if (!add_mapping_entry(&map, 0)) {
 
579
                DEBUG(0,("Failed to add mapping entry during upgrade\n"));
 
580
                *(int *)state = -1;
 
581
                return -1;
 
582
        }
 
583
 
 
584
        return 0;
 
585
}
 
586
 
 
587
/*
 
588
  upgrade one alias record from the old tdb format
 
589
*/
 
590
static int upgrade_alias_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key, 
 
591
                                TDB_DATA data, void *state)
 
592
{
 
593
        const char *p = (const char *)data.dptr;
 
594
        char *string_sid;
 
595
        DOM_SID member;
 
596
        TALLOC_CTX *frame;
 
597
 
 
598
        if (strncmp((char *)key.dptr, MEMBEROF_PREFIX, 
 
599
                    MIN(key.dsize, strlen(MEMBEROF_PREFIX))) != 0) {
 
600
                return 0;
 
601
        }
 
602
 
 
603
        if (!string_to_sid(&member, strlen(MEMBEROF_PREFIX) + (const char *)key.dptr)) {
 
604
                DEBUG(0,("Bad alias key %s during upgrade\n",
 
605
                         (const char *)key.dptr));
 
606
                *(int *)state = -1;
 
607
        }
 
608
 
 
609
        frame = talloc_stackframe();
 
610
        while (next_token_talloc(frame,&p, &string_sid, " ")) {
 
611
                DOM_SID alias;
 
612
                NTSTATUS status;
 
613
                string_to_sid(&alias, string_sid);
 
614
                status = add_aliasmem(&alias, &member);
 
615
                if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_ALIAS)) {
 
616
                        DEBUG(0,("Ignoring orphaned alias record '%s'\n", 
 
617
                                 string_sid));
 
618
                } else if (!NT_STATUS_IS_OK(status)) {
 
619
                        DEBUG(0,("Failed to add alias member during upgrade - %s\n",
 
620
                                 nt_errstr(status)));
 
621
                        *(int *)state = -1;
 
622
                        TALLOC_FREE(frame);
 
623
                        return -1;
 
624
                }
 
625
        }
 
626
        TALLOC_FREE(frame);
 
627
        return 0;
 
628
}
 
629
 
 
630
/*
 
631
  upgrade from a old style tdb
 
632
*/
 
633
static bool mapping_upgrade(const char *tdb_path)
 
634
{
 
635
        static TDB_CONTEXT *tdb;
 
636
        int ret, status=0;
 
637
 
 
638
        tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDWR, 0600);
 
639
        if (tdb == NULL) goto failed;
 
640
 
 
641
        /* we have to do the map records first, as alias records may
 
642
           reference them */
 
643
        ret = tdb_traverse(tdb, upgrade_map_record, &status);
 
644
        if (ret == -1 || status == -1) goto failed;
 
645
 
 
646
        ret = tdb_traverse(tdb, upgrade_alias_record, &status);
 
647
        if (ret == -1 || status == -1) goto failed;
 
648
 
 
649
        if (tdb) {
 
650
                tdb_close(tdb);
 
651
                tdb = NULL;
 
652
        }
 
653
 
 
654
        {
 
655
                const char *old_path = tdb_path;
 
656
                char *new_path = state_path("group_mapping.tdb.upgraded");
 
657
 
 
658
                if (!new_path) {
 
659
                        goto failed;
 
660
                }
 
661
                if (rename(old_path, new_path) != 0) {
 
662
                        DEBUG(0,("Failed to rename old group mapping database\n"));
 
663
                        goto failed;
 
664
                }
 
665
        }
 
666
        return True;
 
667
 
 
668
failed:
 
669
        DEBUG(0,("Failed to upgrade group mapping database\n"));
 
670
        if (tdb) tdb_close(tdb);
 
671
        return False;
 
672
}
 
673
 
 
674
 
 
675
 
 
676
static const struct mapping_backend ldb_backend = {
 
677
        .add_mapping_entry         = add_mapping_entry,
 
678
        .get_group_map_from_sid    = get_group_map_from_sid,
 
679
        .get_group_map_from_gid    = get_group_map_from_gid,
 
680
        .get_group_map_from_ntname = get_group_map_from_ntname,
 
681
        .group_map_remove          = group_map_remove,
 
682
        .enum_group_mapping        = enum_group_mapping,
 
683
        .one_alias_membership      = one_alias_membership,
 
684
        .add_aliasmem              = add_aliasmem,
 
685
        .del_aliasmem              = del_aliasmem,
 
686
        .enum_aliasmem             = enum_aliasmem      
 
687
};
 
688
 
 
689
/*
 
690
  initialise the ldb mapping backend
 
691
 */
 
692
const struct mapping_backend *groupdb_ldb_init(void)
 
693
{
 
694
        if (!init_group_mapping()) {
 
695
                DEBUG(0,("Failed to initialise ldb mapping backend\n"));
 
696
                return NULL;
 
697
        }
 
698
 
 
699
        return &ldb_backend;
 
700
}