s3: re-run make samba3-idl.
[Samba/cd1.git] / source3 / groupdb / mapping_tdb.c
blobee8d7526a0a49df423179bb467d42db50919502b
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2006,
5 * Copyright (C) Jean François Micouleau 1998-2001.
6 * Copyright (C) Volker Lendecke 2006.
7 * Copyright (C) Gerald Carter 2006.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "groupdb/mapping.h"
26 static struct db_context *db; /* used for driver files */
28 static bool enum_group_mapping(const DOM_SID *domsid,
29 enum lsa_SidType sid_name_use,
30 GROUP_MAP **pp_rmap,
31 size_t *p_num_entries,
32 bool unix_only);
33 static bool group_map_remove(const DOM_SID *sid);
35 static bool mapping_switch(const char *ldb_path);
37 /****************************************************************************
38 Open the group mapping tdb.
39 ****************************************************************************/
40 static bool init_group_mapping(void)
42 const char *ldb_path;
44 if (db != NULL) {
45 return true;
48 db = db_open(NULL, state_path("group_mapping.tdb"), 0,
49 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
50 if (db == NULL) {
51 DEBUG(0, ("Failed to open group mapping database: %s\n",
52 strerror(errno)));
53 return false;
56 ldb_path = state_path("group_mapping.ldb");
57 if (file_exist(ldb_path) && !mapping_switch(ldb_path)) {
58 unlink(state_path("group_mapping.tdb"));
59 return false;
61 } else {
62 /* handle upgrade from old versions of the database */
63 #if 0 /* -- Needs conversion to dbwrap -- */
64 const char *vstring = "INFO/version";
65 int32 vers_id;
66 GROUP_MAP *map_table = NULL;
67 size_t num_entries = 0;
69 /* handle a Samba upgrade */
70 tdb_lock_bystring(tdb, vstring);
72 /* Cope with byte-reversed older versions of the db. */
73 vers_id = tdb_fetch_int32(tdb, vstring);
74 if ((vers_id == DATABASE_VERSION_V1)
75 || (IREV(vers_id) == DATABASE_VERSION_V1)) {
77 * Written on a bigendian machine with old fetch_int
78 * code. Save as le.
80 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
81 vers_id = DATABASE_VERSION_V2;
84 /* if its an unknown version we remove everthing in the db */
86 if (vers_id != DATABASE_VERSION_V2) {
87 tdb_wipe_all(tdb);
88 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
91 tdb_unlock_bystring(tdb, vstring);
93 /* cleanup any map entries with a gid == -1 */
95 if ( enum_group_mapping( NULL, SID_NAME_UNKNOWN, &map_table,
96 &num_entries, False ) ) {
97 int i;
99 for ( i=0; i<num_entries; i++ ) {
100 if ( map_table[i].gid == -1 ) {
101 group_map_remove( &map_table[i].sid );
105 SAFE_FREE( map_table );
107 #endif
109 return true;
112 static char *group_mapping_key(TALLOC_CTX *mem_ctx, const DOM_SID *sid)
114 char *sidstr, *result;
116 sidstr = sid_string_talloc(talloc_tos(), sid);
117 if (sidstr == NULL) {
118 return NULL;
121 result = talloc_asprintf(mem_ctx, "%s%s", GROUP_PREFIX, sidstr);
123 TALLOC_FREE(sidstr);
124 return result;
127 /****************************************************************************
128 ****************************************************************************/
129 static bool add_mapping_entry(GROUP_MAP *map, int flag)
131 char *key, *buf;
132 int len;
133 NTSTATUS status;
135 key = group_mapping_key(talloc_tos(), &map->sid);
136 if (key == NULL) {
137 return false;
140 len = tdb_pack(NULL, 0, "ddff",
141 map->gid, map->sid_name_use, map->nt_name, map->comment);
143 buf = TALLOC_ARRAY(key, char, len);
144 if (!buf) {
145 TALLOC_FREE(key);
146 return false;
148 len = tdb_pack((uint8 *)buf, len, "ddff", map->gid,
149 map->sid_name_use, map->nt_name, map->comment);
151 status = dbwrap_trans_store(
152 db, string_term_tdb_data(key),
153 make_tdb_data((uint8_t *)buf, len), TDB_REPLACE);
155 TALLOC_FREE(key);
157 return NT_STATUS_IS_OK(status);
161 /****************************************************************************
162 Return the sid and the type of the unix group.
163 ****************************************************************************/
165 static bool get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
167 TDB_DATA dbuf;
168 char *key;
169 int ret = 0;
171 /* the key is the SID, retrieving is direct */
173 key = group_mapping_key(talloc_tos(), &sid);
174 if (key == NULL) {
175 return false;
178 dbuf = dbwrap_fetch_bystring(db, key, key);
179 if (dbuf.dptr == NULL) {
180 TALLOC_FREE(key);
181 return false;
184 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
185 &map->gid, &map->sid_name_use,
186 &map->nt_name, &map->comment);
188 TALLOC_FREE(key);
190 if ( ret == -1 ) {
191 DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
192 return false;
195 sid_copy(&map->sid, &sid);
197 return true;
200 static bool dbrec2map(const struct db_record *rec, GROUP_MAP *map)
202 if ((rec->key.dsize < strlen(GROUP_PREFIX))
203 || (strncmp((char *)rec->key.dptr, GROUP_PREFIX,
204 GROUP_PREFIX_LEN) != 0)) {
205 return False;
208 if (!string_to_sid(&map->sid, (const char *)rec->key.dptr
209 + GROUP_PREFIX_LEN)) {
210 return False;
213 return tdb_unpack(rec->value.dptr, rec->value.dsize, "ddff",
214 &map->gid, &map->sid_name_use, &map->nt_name,
215 &map->comment) != -1;
218 struct find_map_state {
219 bool found;
220 const char *name; /* If != NULL, look for name */
221 gid_t gid; /* valid iff name == NULL */
222 GROUP_MAP *map;
225 static int find_map(struct db_record *rec, void *private_data)
227 struct find_map_state *state = (struct find_map_state *)private_data;
229 if (!dbrec2map(rec, state->map)) {
230 DEBUG(10, ("failed to unpack map\n"));
231 return 0;
234 if (state->name != NULL) {
235 if (strequal(state->name, state->map->nt_name)) {
236 state->found = true;
237 return 1;
240 else {
241 if (state->map->gid == state->gid) {
242 state->found = true;
243 return 1;
247 return 0;
250 /****************************************************************************
251 Return the sid and the type of the unix group.
252 ****************************************************************************/
254 static bool get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
256 struct find_map_state state;
258 state.found = false;
259 state.name = NULL; /* Indicate we're looking for gid */
260 state.gid = gid;
261 state.map = map;
263 db->traverse_read(db, find_map, (void *)&state);
265 return state.found;
268 /****************************************************************************
269 Return the sid and the type of the unix group.
270 ****************************************************************************/
272 static bool get_group_map_from_ntname(const char *name, GROUP_MAP *map)
274 struct find_map_state state;
276 state.found = false;
277 state.name = name;
278 state.map = map;
280 db->traverse_read(db, find_map, (void *)&state);
282 return state.found;
285 /****************************************************************************
286 Remove a group mapping entry.
287 ****************************************************************************/
289 static bool group_map_remove(const DOM_SID *sid)
291 char *key;
292 NTSTATUS status;
294 key = group_mapping_key(talloc_tos(), sid);
295 if (key == NULL) {
296 return false;
299 status = dbwrap_trans_delete(db, string_term_tdb_data(key));
301 TALLOC_FREE(key);
302 return NT_STATUS_IS_OK(status);
305 /****************************************************************************
306 Enumerate the group mapping.
307 ****************************************************************************/
309 struct enum_map_state {
310 const DOM_SID *domsid;
311 enum lsa_SidType sid_name_use;
312 bool unix_only;
314 size_t num_maps;
315 GROUP_MAP *maps;
318 static int collect_map(struct db_record *rec, void *private_data)
320 struct enum_map_state *state = (struct enum_map_state *)private_data;
321 GROUP_MAP map;
322 GROUP_MAP *tmp;
324 if (!dbrec2map(rec, &map)) {
325 return 0;
327 /* list only the type or everything if UNKNOWN */
328 if (state->sid_name_use != SID_NAME_UNKNOWN
329 && state->sid_name_use != map.sid_name_use) {
330 DEBUG(11,("enum_group_mapping: group %s is not of the "
331 "requested type\n", map.nt_name));
332 return 0;
335 if ((state->unix_only == ENUM_ONLY_MAPPED) && (map.gid == -1)) {
336 DEBUG(11,("enum_group_mapping: group %s is non mapped\n",
337 map.nt_name));
338 return 0;
341 if ((state->domsid != NULL) &&
342 (sid_compare_domain(state->domsid, &map.sid) != 0)) {
343 DEBUG(11,("enum_group_mapping: group %s is not in domain\n",
344 sid_string_dbg(&map.sid)));
345 return 0;
348 if (!(tmp = SMB_REALLOC_ARRAY(state->maps, GROUP_MAP,
349 state->num_maps+1))) {
350 DEBUG(0,("enum_group_mapping: Unable to enlarge group "
351 "map!\n"));
352 return 1;
355 state->maps = tmp;
356 state->maps[state->num_maps] = map;
357 state->num_maps++;
358 return 0;
361 static bool enum_group_mapping(const DOM_SID *domsid,
362 enum lsa_SidType sid_name_use,
363 GROUP_MAP **pp_rmap,
364 size_t *p_num_entries, bool unix_only)
366 struct enum_map_state state;
368 state.domsid = domsid;
369 state.sid_name_use = sid_name_use;
370 state.unix_only = unix_only;
371 state.num_maps = 0;
372 state.maps = NULL;
374 if (db->traverse_read(db, collect_map, (void *)&state) < 0) {
375 return false;
378 *pp_rmap = state.maps;
379 *p_num_entries = state.num_maps;
381 return true;
384 /* This operation happens on session setup, so it should better be fast. We
385 * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
387 static NTSTATUS one_alias_membership(const DOM_SID *member,
388 DOM_SID **sids, size_t *num)
390 fstring tmp;
391 fstring key;
392 char *string_sid;
393 TDB_DATA dbuf;
394 const char *p;
395 NTSTATUS status = NT_STATUS_OK;
396 TALLOC_CTX *frame = talloc_stackframe();
398 slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX,
399 sid_to_fstring(tmp, member));
401 dbuf = dbwrap_fetch_bystring(db, frame, key);
402 if (dbuf.dptr == NULL) {
403 TALLOC_FREE(frame);
404 return NT_STATUS_OK;
407 p = (const char *)dbuf.dptr;
409 while (next_token_talloc(frame, &p, &string_sid, " ")) {
410 DOM_SID alias;
412 if (!string_to_sid(&alias, string_sid))
413 continue;
415 status= add_sid_to_array_unique(NULL, &alias, sids, num);
416 if (!NT_STATUS_IS_OK(status)) {
417 goto done;
421 done:
422 TALLOC_FREE(frame);
423 return status;
426 static NTSTATUS alias_memberships(const DOM_SID *members, size_t num_members,
427 DOM_SID **sids, size_t *num)
429 size_t i;
431 *num = 0;
432 *sids = NULL;
434 for (i=0; i<num_members; i++) {
435 NTSTATUS status = one_alias_membership(&members[i], sids, num);
436 if (!NT_STATUS_IS_OK(status))
437 return status;
439 return NT_STATUS_OK;
442 static bool is_aliasmem(const DOM_SID *alias, const DOM_SID *member)
444 DOM_SID *sids;
445 size_t i, num;
447 /* This feels the wrong way round, but the on-disk data structure
448 * dictates it this way. */
449 if (!NT_STATUS_IS_OK(alias_memberships(member, 1, &sids, &num)))
450 return False;
452 for (i=0; i<num; i++) {
453 if (sid_compare(alias, &sids[i]) == 0) {
454 TALLOC_FREE(sids);
455 return True;
458 TALLOC_FREE(sids);
459 return False;
463 static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
465 GROUP_MAP map;
466 char *key;
467 fstring string_sid;
468 char *new_memberstring;
469 struct db_record *rec;
470 NTSTATUS status;
472 if (!get_group_map_from_sid(*alias, &map))
473 return NT_STATUS_NO_SUCH_ALIAS;
475 if ( (map.sid_name_use != SID_NAME_ALIAS) &&
476 (map.sid_name_use != SID_NAME_WKN_GRP) )
477 return NT_STATUS_NO_SUCH_ALIAS;
479 if (is_aliasmem(alias, member))
480 return NT_STATUS_MEMBER_IN_ALIAS;
482 sid_to_fstring(string_sid, member);
484 key = talloc_asprintf(talloc_tos(), "%s%s", MEMBEROF_PREFIX,
485 string_sid);
486 if (key == NULL) {
487 return NT_STATUS_NO_MEMORY;
490 if (db->transaction_start(db) != 0) {
491 DEBUG(0, ("transaction_start failed\n"));
492 return NT_STATUS_INTERNAL_DB_CORRUPTION;
495 rec = db->fetch_locked(db, key, string_term_tdb_data(key));
497 if (rec == NULL) {
498 DEBUG(10, ("fetch_lock failed\n"));
499 TALLOC_FREE(key);
500 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
501 goto cancel;
504 sid_to_fstring(string_sid, alias);
506 if (rec->value.dptr != NULL) {
507 new_memberstring = talloc_asprintf(
508 key, "%s %s", (char *)(rec->value.dptr), string_sid);
509 } else {
510 new_memberstring = talloc_strdup(key, string_sid);
513 if (new_memberstring == NULL) {
514 TALLOC_FREE(key);
515 status = NT_STATUS_NO_MEMORY;
516 goto cancel;
519 status = rec->store(rec, string_term_tdb_data(new_memberstring), 0);
521 TALLOC_FREE(key);
523 if (!NT_STATUS_IS_OK(status)) {
524 DEBUG(10, ("Could not store record: %s\n", nt_errstr(status)));
525 goto cancel;
528 if (db->transaction_commit(db) != 0) {
529 DEBUG(0, ("transaction_commit failed\n"));
530 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
531 return status;
534 return NT_STATUS_OK;
536 cancel:
537 if (db->transaction_cancel(db) != 0) {
538 smb_panic("transaction_cancel failed");
541 return status;
544 struct aliasmem_state {
545 TALLOC_CTX *mem_ctx;
546 const DOM_SID *alias;
547 DOM_SID **sids;
548 size_t *num;
551 static int collect_aliasmem(struct db_record *rec, void *priv)
553 struct aliasmem_state *state = (struct aliasmem_state *)priv;
554 const char *p;
555 char *alias_string;
556 TALLOC_CTX *frame;
558 if (strncmp((const char *)rec->key.dptr, MEMBEROF_PREFIX,
559 MEMBEROF_PREFIX_LEN) != 0)
560 return 0;
562 p = (const char *)rec->value.dptr;
564 frame = talloc_stackframe();
566 while (next_token_talloc(frame, &p, &alias_string, " ")) {
567 DOM_SID alias, member;
568 const char *member_string;
570 if (!string_to_sid(&alias, alias_string))
571 continue;
573 if (sid_compare(state->alias, &alias) != 0)
574 continue;
576 /* Ok, we found the alias we're looking for in the membership
577 * list currently scanned. The key represents the alias
578 * member. Add that. */
580 member_string = strchr((const char *)rec->key.dptr, '/');
582 /* Above we tested for MEMBEROF_PREFIX which includes the
583 * slash. */
585 SMB_ASSERT(member_string != NULL);
586 member_string += 1;
588 if (!string_to_sid(&member, member_string))
589 continue;
591 if (!NT_STATUS_IS_OK(add_sid_to_array(state->mem_ctx, &member,
592 state->sids,
593 state->num)))
595 /* talloc fail. */
596 break;
600 TALLOC_FREE(frame);
601 return 0;
604 static NTSTATUS enum_aliasmem(const DOM_SID *alias, TALLOC_CTX *mem_ctx,
605 DOM_SID **sids, size_t *num)
607 GROUP_MAP map;
608 struct aliasmem_state state;
610 if (!get_group_map_from_sid(*alias, &map))
611 return NT_STATUS_NO_SUCH_ALIAS;
613 if ( (map.sid_name_use != SID_NAME_ALIAS) &&
614 (map.sid_name_use != SID_NAME_WKN_GRP) )
615 return NT_STATUS_NO_SUCH_ALIAS;
617 *sids = NULL;
618 *num = 0;
620 state.alias = alias;
621 state.sids = sids;
622 state.num = num;
623 state.mem_ctx = mem_ctx;
625 db->traverse_read(db, collect_aliasmem, &state);
626 return NT_STATUS_OK;
629 static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
631 NTSTATUS status;
632 DOM_SID *sids;
633 size_t i, num;
634 bool found = False;
635 char *member_string;
636 char *key;
637 fstring sid_string;
639 if (db->transaction_start(db) != 0) {
640 DEBUG(0, ("transaction_start failed\n"));
641 return NT_STATUS_INTERNAL_DB_CORRUPTION;
644 status = alias_memberships(member, 1, &sids, &num);
646 if (!NT_STATUS_IS_OK(status)) {
647 goto cancel;
650 for (i=0; i<num; i++) {
651 if (sid_compare(&sids[i], alias) == 0) {
652 found = True;
653 break;
657 if (!found) {
658 TALLOC_FREE(sids);
659 status = NT_STATUS_MEMBER_NOT_IN_ALIAS;
660 goto cancel;
663 if (i < num)
664 sids[i] = sids[num-1];
666 num -= 1;
668 sid_to_fstring(sid_string, member);
670 key = talloc_asprintf(sids, "%s%s", MEMBEROF_PREFIX, sid_string);
671 if (key == NULL) {
672 TALLOC_FREE(sids);
673 status = NT_STATUS_NO_MEMORY;
674 goto cancel;
677 if (num == 0) {
678 status = dbwrap_delete_bystring(db, key);
679 goto commit;
682 member_string = talloc_strdup(sids, "");
683 if (member_string == NULL) {
684 TALLOC_FREE(sids);
685 status = NT_STATUS_NO_MEMORY;
686 goto cancel;
689 for (i=0; i<num; i++) {
691 sid_to_fstring(sid_string, &sids[i]);
693 member_string = talloc_asprintf_append_buffer(
694 member_string, " %s", sid_string);
696 if (member_string == NULL) {
697 TALLOC_FREE(sids);
698 status = NT_STATUS_NO_MEMORY;
699 goto cancel;
703 status = dbwrap_store_bystring(
704 db, key, string_term_tdb_data(member_string), 0);
705 commit:
706 TALLOC_FREE(sids);
708 if (!NT_STATUS_IS_OK(status)) {
709 DEBUG(10, ("dbwrap_store_bystring failed: %s\n",
710 nt_errstr(status)));
711 goto cancel;
714 if (db->transaction_commit(db) != 0) {
715 DEBUG(0, ("transaction_commit failed\n"));
716 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
717 return status;
720 return NT_STATUS_OK;
722 cancel:
723 if (db->transaction_cancel(db) != 0) {
724 smb_panic("transaction_cancel failed");
726 return status;
730 /* -- ldb->tdb switching code -------------------------------------------- */
732 /* change this if the data format ever changes */
733 #define LTDB_PACKING_FORMAT 0x26011967
735 /* old packing formats (not supported for now,
736 * it was never used for group mapping AFAIK) */
737 #define LTDB_PACKING_FORMAT_NODN 0x26011966
739 static unsigned int pull_uint32(uint8_t *p, int ofs)
741 p += ofs;
742 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
746 unpack a ldb message from a linear buffer in TDB_DATA
748 static int convert_ldb_record(TDB_CONTEXT *ltdb, TDB_DATA key,
749 TDB_DATA data, void *ptr)
751 TALLOC_CTX *tmp_ctx = talloc_tos();
752 GROUP_MAP map;
753 uint8_t *p;
754 uint32_t format;
755 uint32_t num_el;
756 unsigned int remaining;
757 unsigned int i, j;
758 size_t len;
759 char *name;
760 char *val;
761 char *q;
762 uint32_t num_mem = 0;
763 DOM_SID *members = NULL;
765 p = (uint8_t *)data.dptr;
766 if (data.dsize < 8) {
767 errno = EIO;
768 goto failed;
771 format = pull_uint32(p, 0);
772 num_el = pull_uint32(p, 4);
773 p += 8;
775 remaining = data.dsize - 8;
777 switch (format) {
778 case LTDB_PACKING_FORMAT:
779 len = strnlen((char *)p, remaining);
780 if (len == remaining) {
781 errno = EIO;
782 goto failed;
785 if (*p == '@') {
786 /* ignore special LDB attributes */
787 return 0;
790 if (strncmp((char *)p, "rid=", 4)) {
791 /* unknown entry, ignore */
792 DEBUG(3, ("Found unknown entry in group mapping "
793 "database named [%s]\n", (char *)p));
794 return 0;
797 remaining -= len + 1;
798 p += len + 1;
799 break;
801 case LTDB_PACKING_FORMAT_NODN:
802 default:
803 errno = EIO;
804 goto failed;
807 if (num_el == 0) {
808 /* bad entry, ignore */
809 return 0;
812 if (num_el > remaining / 6) {
813 errno = EIO;
814 goto failed;
817 ZERO_STRUCT(map);
819 for (i = 0; i < num_el; i++) {
820 uint32_t num_vals;
822 if (remaining < 10) {
823 errno = EIO;
824 goto failed;
826 len = strnlen((char *)p, remaining - 6);
827 if (len == remaining - 6) {
828 errno = EIO;
829 goto failed;
831 name = talloc_strndup(tmp_ctx, (char *)p, len);
832 if (name == NULL) {
833 errno = ENOMEM;
834 goto failed;
836 remaining -= len + 1;
837 p += len + 1;
839 num_vals = pull_uint32(p, 0);
840 if (StrCaseCmp(name, "member") == 0) {
841 num_mem = num_vals;
842 members = talloc_array(tmp_ctx, DOM_SID, num_mem);
843 if (members == NULL) {
844 errno = ENOMEM;
845 goto failed;
847 } else if (num_vals != 1) {
848 errno = EIO;
849 goto failed;
852 p += 4;
853 remaining -= 4;
855 for (j = 0; j < num_vals; j++) {
856 len = pull_uint32(p, 0);
857 if (len > remaining-5) {
858 errno = EIO;
859 goto failed;
862 val = talloc_strndup(tmp_ctx, (char *)(p + 4), len);
863 if (val == NULL) {
864 errno = ENOMEM;
865 goto failed;
868 remaining -= len+4+1;
869 p += len+4+1;
871 /* we ignore unknown or uninteresting attributes
872 * (objectclass, etc.) */
873 if (StrCaseCmp(name, "gidNumber") == 0) {
874 map.gid = strtoul(val, &q, 10);
875 if (*q) {
876 errno = EIO;
877 goto failed;
879 } else if (StrCaseCmp(name, "sid") == 0) {
880 if (!string_to_sid(&map.sid, val)) {
881 errno = EIO;
882 goto failed;
884 } else if (StrCaseCmp(name, "sidNameUse") == 0) {
885 map.sid_name_use = strtoul(val, &q, 10);
886 if (*q) {
887 errno = EIO;
888 goto failed;
890 } else if (StrCaseCmp(name, "ntname") == 0) {
891 strlcpy(map.nt_name, val,
892 sizeof(map.nt_name) -1);
893 } else if (StrCaseCmp(name, "comment") == 0) {
894 strlcpy(map.comment, val,
895 sizeof(map.comment) -1);
896 } else if (StrCaseCmp(name, "member") == 0) {
897 if (!string_to_sid(&members[j], val)) {
898 errno = EIO;
899 goto failed;
903 TALLOC_FREE(val);
906 TALLOC_FREE(name);
909 if (!add_mapping_entry(&map, 0)) {
910 errno = EIO;
911 goto failed;
914 if (num_mem) {
915 for (j = 0; j < num_mem; j++) {
916 NTSTATUS status;
917 status = add_aliasmem(&map.sid, &members[j]);
918 if (!NT_STATUS_IS_OK(status)) {
919 errno = EIO;
920 goto failed;
925 if (remaining != 0) {
926 DEBUG(0, ("Errror: %d bytes unread in ltdb_unpack_data\n",
927 remaining));
930 return 0;
932 failed:
933 return -1;
936 static bool mapping_switch(const char *ldb_path)
938 TDB_CONTEXT *ltdb;
939 TALLOC_CTX *frame;
940 char *new_path;
941 int ret;
943 frame = talloc_stackframe();
945 ltdb = tdb_open_log(ldb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
946 if (ltdb == NULL) goto failed;
948 /* ldb is just a very fancy tdb, read out raw data and perform
949 * conversion */
950 ret = tdb_traverse(ltdb, convert_ldb_record, NULL);
951 if (ret == -1) goto failed;
953 if (ltdb) {
954 tdb_close(ltdb);
955 ltdb = NULL;
958 /* now rename the old db out of the way */
959 new_path = state_path("group_mapping.ldb.replaced");
960 if (!new_path) {
961 goto failed;
963 if (rename(ldb_path, new_path) != 0) {
964 DEBUG(0,("Failed to rename old group mapping database\n"));
965 goto failed;
967 TALLOC_FREE(frame);
968 return True;
970 failed:
971 DEBUG(0,("Failed to swith to tdb group mapping database\n"));
972 if (ltdb) tdb_close(ltdb);
973 TALLOC_FREE(frame);
974 return False;
977 static const struct mapping_backend tdb_backend = {
978 .add_mapping_entry = add_mapping_entry,
979 .get_group_map_from_sid = get_group_map_from_sid,
980 .get_group_map_from_gid = get_group_map_from_gid,
981 .get_group_map_from_ntname = get_group_map_from_ntname,
982 .group_map_remove = group_map_remove,
983 .enum_group_mapping = enum_group_mapping,
984 .one_alias_membership = one_alias_membership,
985 .add_aliasmem = add_aliasmem,
986 .del_aliasmem = del_aliasmem,
987 .enum_aliasmem = enum_aliasmem
991 initialise the tdb mapping backend
993 const struct mapping_backend *groupdb_tdb_init(void)
995 if (!init_group_mapping()) {
996 DEBUG(0,("Failed to initialise tdb mapping backend\n"));
997 return NULL;
1000 return &tdb_backend;