s3/ldap: delay the ldap search alarm termination a bit
[Samba/gebeck_regimport.git] / source3 / groupdb / mapping_tdb.c
blob47f743d146540d48d3f9672c75da014f066fd974
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 "system/filesys.h"
25 #include "passdb.h"
26 #include "groupdb/mapping.h"
27 #include "dbwrap/dbwrap.h"
28 #include "dbwrap/dbwrap_open.h"
29 #include "util_tdb.h"
30 #include "../libcli/security/security.h"
32 static struct db_context *db; /* used for driver files */
34 static bool enum_group_mapping(const struct dom_sid *domsid,
35 enum lsa_SidType sid_name_use,
36 GROUP_MAP **pp_rmap,
37 size_t *p_num_entries,
38 bool unix_only);
39 static bool group_map_remove(const struct dom_sid *sid);
41 static bool mapping_switch(const char *ldb_path);
43 /****************************************************************************
44 Open the group mapping tdb.
45 ****************************************************************************/
46 static bool init_group_mapping(void)
48 const char *ldb_path;
50 if (db != NULL) {
51 return true;
54 db = db_open(NULL, state_path("group_mapping.tdb"), 0,
55 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
56 if (db == NULL) {
57 DEBUG(0, ("Failed to open group mapping database: %s\n",
58 strerror(errno)));
59 return false;
62 ldb_path = state_path("group_mapping.ldb");
63 if (file_exist(ldb_path) && !mapping_switch(ldb_path)) {
64 unlink(state_path("group_mapping.tdb"));
65 return false;
67 } else {
68 /* handle upgrade from old versions of the database */
69 #if 0 /* -- Needs conversion to dbwrap -- */
70 const char *vstring = "INFO/version";
71 int32 vers_id;
72 GROUP_MAP *map_table = NULL;
73 size_t num_entries = 0;
75 /* handle a Samba upgrade */
76 tdb_lock_bystring(tdb, vstring);
78 /* Cope with byte-reversed older versions of the db. */
79 vers_id = tdb_fetch_int32(tdb, vstring);
80 if ((vers_id == DATABASE_VERSION_V1)
81 || (IREV(vers_id) == DATABASE_VERSION_V1)) {
83 * Written on a bigendian machine with old fetch_int
84 * code. Save as le.
86 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
87 vers_id = DATABASE_VERSION_V2;
90 /* if its an unknown version we remove everthing in the db */
92 if (vers_id != DATABASE_VERSION_V2) {
93 tdb_wipe_all(tdb);
94 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
97 tdb_unlock_bystring(tdb, vstring);
99 /* cleanup any map entries with a gid == -1 */
101 if ( enum_group_mapping( NULL, SID_NAME_UNKNOWN, &map_table,
102 &num_entries, False ) ) {
103 int i;
105 for ( i=0; i<num_entries; i++ ) {
106 if ( map_table[i].gid == -1 ) {
107 group_map_remove( &map_table[i].sid );
111 SAFE_FREE( map_table );
113 #endif
115 return true;
118 static char *group_mapping_key(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
120 char *sidstr, *result;
122 sidstr = sid_string_talloc(talloc_tos(), sid);
123 if (sidstr == NULL) {
124 return NULL;
127 result = talloc_asprintf(mem_ctx, "%s%s", GROUP_PREFIX, sidstr);
129 TALLOC_FREE(sidstr);
130 return result;
133 /****************************************************************************
134 ****************************************************************************/
135 static bool add_mapping_entry(GROUP_MAP *map, int flag)
137 char *key, *buf;
138 int len;
139 NTSTATUS status;
141 key = group_mapping_key(talloc_tos(), &map->sid);
142 if (key == NULL) {
143 return false;
146 len = tdb_pack(NULL, 0, "ddff",
147 map->gid, map->sid_name_use, map->nt_name, map->comment);
149 buf = talloc_array(key, char, len);
150 if (!buf) {
151 TALLOC_FREE(key);
152 return false;
154 len = tdb_pack((uint8 *)buf, len, "ddff", map->gid,
155 map->sid_name_use, map->nt_name, map->comment);
157 status = dbwrap_trans_store(
158 db, string_term_tdb_data(key),
159 make_tdb_data((uint8_t *)buf, len), TDB_REPLACE);
161 TALLOC_FREE(key);
163 return NT_STATUS_IS_OK(status);
167 /****************************************************************************
168 Return the sid and the type of the unix group.
169 ****************************************************************************/
171 static bool get_group_map_from_sid(struct dom_sid sid, GROUP_MAP *map)
173 TDB_DATA dbuf;
174 char *key;
175 int ret = 0;
177 /* the key is the SID, retrieving is direct */
179 key = group_mapping_key(talloc_tos(), &sid);
180 if (key == NULL) {
181 return false;
184 dbuf = dbwrap_fetch_bystring(db, key, key);
185 if (dbuf.dptr == NULL) {
186 TALLOC_FREE(key);
187 return false;
190 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
191 &map->gid, &map->sid_name_use,
192 &map->nt_name, &map->comment);
194 TALLOC_FREE(key);
196 if ( ret == -1 ) {
197 DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
198 return false;
201 sid_copy(&map->sid, &sid);
203 return true;
206 static bool dbrec2map(const struct db_record *rec, GROUP_MAP *map)
208 if ((rec->key.dsize < strlen(GROUP_PREFIX))
209 || (strncmp((char *)rec->key.dptr, GROUP_PREFIX,
210 GROUP_PREFIX_LEN) != 0)) {
211 return False;
214 if (!string_to_sid(&map->sid, (const char *)rec->key.dptr
215 + GROUP_PREFIX_LEN)) {
216 return False;
219 return tdb_unpack(rec->value.dptr, rec->value.dsize, "ddff",
220 &map->gid, &map->sid_name_use, &map->nt_name,
221 &map->comment) != -1;
224 struct find_map_state {
225 bool found;
226 const char *name; /* If != NULL, look for name */
227 gid_t gid; /* valid iff name == NULL */
228 GROUP_MAP *map;
231 static int find_map(struct db_record *rec, void *private_data)
233 struct find_map_state *state = (struct find_map_state *)private_data;
235 if (!dbrec2map(rec, state->map)) {
236 DEBUG(10, ("failed to unpack map\n"));
237 return 0;
240 if (state->name != NULL) {
241 if (strequal(state->name, state->map->nt_name)) {
242 state->found = true;
243 return 1;
246 else {
247 if (state->map->gid == state->gid) {
248 state->found = true;
249 return 1;
253 return 0;
256 /****************************************************************************
257 Return the sid and the type of the unix group.
258 ****************************************************************************/
260 static bool get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
262 struct find_map_state state;
264 state.found = false;
265 state.name = NULL; /* Indicate we're looking for gid */
266 state.gid = gid;
267 state.map = map;
269 db->traverse_read(db, find_map, (void *)&state);
271 return state.found;
274 /****************************************************************************
275 Return the sid and the type of the unix group.
276 ****************************************************************************/
278 static bool get_group_map_from_ntname(const char *name, GROUP_MAP *map)
280 struct find_map_state state;
282 state.found = false;
283 state.name = name;
284 state.map = map;
286 db->traverse_read(db, find_map, (void *)&state);
288 return state.found;
291 /****************************************************************************
292 Remove a group mapping entry.
293 ****************************************************************************/
295 static bool group_map_remove(const struct dom_sid *sid)
297 char *key;
298 NTSTATUS status;
300 key = group_mapping_key(talloc_tos(), sid);
301 if (key == NULL) {
302 return false;
305 status = dbwrap_trans_delete(db, string_term_tdb_data(key));
307 TALLOC_FREE(key);
308 return NT_STATUS_IS_OK(status);
311 /****************************************************************************
312 Enumerate the group mapping.
313 ****************************************************************************/
315 struct enum_map_state {
316 const struct dom_sid *domsid;
317 enum lsa_SidType sid_name_use;
318 bool unix_only;
320 size_t num_maps;
321 GROUP_MAP *maps;
324 static int collect_map(struct db_record *rec, void *private_data)
326 struct enum_map_state *state = (struct enum_map_state *)private_data;
327 GROUP_MAP map;
328 GROUP_MAP *tmp;
330 if (!dbrec2map(rec, &map)) {
331 return 0;
333 /* list only the type or everything if UNKNOWN */
334 if (state->sid_name_use != SID_NAME_UNKNOWN
335 && state->sid_name_use != map.sid_name_use) {
336 DEBUG(11,("enum_group_mapping: group %s is not of the "
337 "requested type\n", map.nt_name));
338 return 0;
341 if ((state->unix_only == ENUM_ONLY_MAPPED) && (map.gid == -1)) {
342 DEBUG(11,("enum_group_mapping: group %s is non mapped\n",
343 map.nt_name));
344 return 0;
347 if ((state->domsid != NULL) &&
348 (dom_sid_compare_domain(state->domsid, &map.sid) != 0)) {
349 DEBUG(11,("enum_group_mapping: group %s is not in domain\n",
350 sid_string_dbg(&map.sid)));
351 return 0;
354 if (!(tmp = SMB_REALLOC_ARRAY(state->maps, GROUP_MAP,
355 state->num_maps+1))) {
356 DEBUG(0,("enum_group_mapping: Unable to enlarge group "
357 "map!\n"));
358 return 1;
361 state->maps = tmp;
362 state->maps[state->num_maps] = map;
363 state->num_maps++;
364 return 0;
367 static bool enum_group_mapping(const struct dom_sid *domsid,
368 enum lsa_SidType sid_name_use,
369 GROUP_MAP **pp_rmap,
370 size_t *p_num_entries, bool unix_only)
372 struct enum_map_state state;
374 state.domsid = domsid;
375 state.sid_name_use = sid_name_use;
376 state.unix_only = unix_only;
377 state.num_maps = 0;
378 state.maps = NULL;
380 if (db->traverse_read(db, collect_map, (void *)&state) < 0) {
381 return false;
384 *pp_rmap = state.maps;
385 *p_num_entries = state.num_maps;
387 return true;
390 /* This operation happens on session setup, so it should better be fast. We
391 * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
393 static NTSTATUS one_alias_membership(const struct dom_sid *member,
394 struct dom_sid **sids, size_t *num)
396 fstring tmp;
397 fstring key;
398 char *string_sid;
399 TDB_DATA dbuf;
400 const char *p;
401 NTSTATUS status = NT_STATUS_OK;
402 TALLOC_CTX *frame = talloc_stackframe();
404 slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX,
405 sid_to_fstring(tmp, member));
407 dbuf = dbwrap_fetch_bystring(db, frame, key);
408 if (dbuf.dptr == NULL) {
409 TALLOC_FREE(frame);
410 return NT_STATUS_OK;
413 p = (const char *)dbuf.dptr;
415 while (next_token_talloc(frame, &p, &string_sid, " ")) {
416 struct dom_sid alias;
417 uint32_t num_sids;
419 if (!string_to_sid(&alias, string_sid))
420 continue;
422 num_sids = *num;
423 status= add_sid_to_array_unique(NULL, &alias, sids, &num_sids);
424 if (!NT_STATUS_IS_OK(status)) {
425 goto done;
427 *num = num_sids;
430 done:
431 TALLOC_FREE(frame);
432 return status;
435 static NTSTATUS alias_memberships(const struct dom_sid *members, size_t num_members,
436 struct dom_sid **sids, size_t *num)
438 size_t i;
440 *num = 0;
441 *sids = NULL;
443 for (i=0; i<num_members; i++) {
444 NTSTATUS status = one_alias_membership(&members[i], sids, num);
445 if (!NT_STATUS_IS_OK(status))
446 return status;
448 return NT_STATUS_OK;
451 static bool is_aliasmem(const struct dom_sid *alias, const struct dom_sid *member)
453 struct dom_sid *sids;
454 size_t i;
455 size_t num;
457 /* This feels the wrong way round, but the on-disk data structure
458 * dictates it this way. */
459 if (!NT_STATUS_IS_OK(alias_memberships(member, 1, &sids, &num)))
460 return False;
462 for (i=0; i<num; i++) {
463 if (dom_sid_compare(alias, &sids[i]) == 0) {
464 TALLOC_FREE(sids);
465 return True;
468 TALLOC_FREE(sids);
469 return False;
473 static NTSTATUS add_aliasmem(const struct dom_sid *alias, const struct dom_sid *member)
475 GROUP_MAP map;
476 char *key;
477 fstring string_sid;
478 char *new_memberstring;
479 struct db_record *rec;
480 NTSTATUS status;
482 if (!get_group_map_from_sid(*alias, &map))
483 return NT_STATUS_NO_SUCH_ALIAS;
485 if ( (map.sid_name_use != SID_NAME_ALIAS) &&
486 (map.sid_name_use != SID_NAME_WKN_GRP) )
487 return NT_STATUS_NO_SUCH_ALIAS;
489 if (is_aliasmem(alias, member))
490 return NT_STATUS_MEMBER_IN_ALIAS;
492 sid_to_fstring(string_sid, member);
494 key = talloc_asprintf(talloc_tos(), "%s%s", MEMBEROF_PREFIX,
495 string_sid);
496 if (key == NULL) {
497 return NT_STATUS_NO_MEMORY;
500 if (db->transaction_start(db) != 0) {
501 DEBUG(0, ("transaction_start failed\n"));
502 return NT_STATUS_INTERNAL_DB_CORRUPTION;
505 rec = db->fetch_locked(db, key, string_term_tdb_data(key));
507 if (rec == NULL) {
508 DEBUG(10, ("fetch_lock failed\n"));
509 TALLOC_FREE(key);
510 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
511 goto cancel;
514 sid_to_fstring(string_sid, alias);
516 if (rec->value.dptr != NULL) {
517 new_memberstring = talloc_asprintf(
518 key, "%s %s", (char *)(rec->value.dptr), string_sid);
519 } else {
520 new_memberstring = talloc_strdup(key, string_sid);
523 if (new_memberstring == NULL) {
524 TALLOC_FREE(key);
525 status = NT_STATUS_NO_MEMORY;
526 goto cancel;
529 status = rec->store(rec, string_term_tdb_data(new_memberstring), 0);
531 TALLOC_FREE(key);
533 if (!NT_STATUS_IS_OK(status)) {
534 DEBUG(10, ("Could not store record: %s\n", nt_errstr(status)));
535 goto cancel;
538 if (db->transaction_commit(db) != 0) {
539 DEBUG(0, ("transaction_commit failed\n"));
540 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
541 return status;
544 return NT_STATUS_OK;
546 cancel:
547 if (db->transaction_cancel(db) != 0) {
548 smb_panic("transaction_cancel failed");
551 return status;
554 struct aliasmem_state {
555 TALLOC_CTX *mem_ctx;
556 const struct dom_sid *alias;
557 struct dom_sid **sids;
558 size_t *num;
561 static int collect_aliasmem(struct db_record *rec, void *priv)
563 struct aliasmem_state *state = (struct aliasmem_state *)priv;
564 const char *p;
565 char *alias_string;
566 TALLOC_CTX *frame;
568 if (strncmp((const char *)rec->key.dptr, MEMBEROF_PREFIX,
569 MEMBEROF_PREFIX_LEN) != 0)
570 return 0;
572 p = (const char *)rec->value.dptr;
574 frame = talloc_stackframe();
576 while (next_token_talloc(frame, &p, &alias_string, " ")) {
577 struct dom_sid alias, member;
578 const char *member_string;
579 uint32_t num_sids;
581 if (!string_to_sid(&alias, alias_string))
582 continue;
584 if (dom_sid_compare(state->alias, &alias) != 0)
585 continue;
587 /* Ok, we found the alias we're looking for in the membership
588 * list currently scanned. The key represents the alias
589 * member. Add that. */
591 member_string = strchr((const char *)rec->key.dptr, '/');
593 /* Above we tested for MEMBEROF_PREFIX which includes the
594 * slash. */
596 SMB_ASSERT(member_string != NULL);
597 member_string += 1;
599 if (!string_to_sid(&member, member_string))
600 continue;
602 num_sids = *state->num;
603 if (!NT_STATUS_IS_OK(add_sid_to_array(state->mem_ctx, &member,
604 state->sids,
605 &num_sids)))
607 /* talloc fail. */
608 break;
610 *state->num = num_sids;
613 TALLOC_FREE(frame);
614 return 0;
617 static NTSTATUS enum_aliasmem(const struct dom_sid *alias, TALLOC_CTX *mem_ctx,
618 struct dom_sid **sids, size_t *num)
620 GROUP_MAP map;
621 struct aliasmem_state state;
623 if (!get_group_map_from_sid(*alias, &map))
624 return NT_STATUS_NO_SUCH_ALIAS;
626 if ( (map.sid_name_use != SID_NAME_ALIAS) &&
627 (map.sid_name_use != SID_NAME_WKN_GRP) )
628 return NT_STATUS_NO_SUCH_ALIAS;
630 *sids = NULL;
631 *num = 0;
633 state.alias = alias;
634 state.sids = sids;
635 state.num = num;
636 state.mem_ctx = mem_ctx;
638 db->traverse_read(db, collect_aliasmem, &state);
639 return NT_STATUS_OK;
642 static NTSTATUS del_aliasmem(const struct dom_sid *alias, const struct dom_sid *member)
644 NTSTATUS status;
645 struct dom_sid *sids;
646 size_t i, num;
647 bool found = False;
648 char *member_string;
649 char *key;
650 fstring sid_string;
652 if (db->transaction_start(db) != 0) {
653 DEBUG(0, ("transaction_start failed\n"));
654 return NT_STATUS_INTERNAL_DB_CORRUPTION;
657 status = alias_memberships(member, 1, &sids, &num);
659 if (!NT_STATUS_IS_OK(status)) {
660 goto cancel;
663 for (i=0; i<num; i++) {
664 if (dom_sid_compare(&sids[i], alias) == 0) {
665 found = True;
666 break;
670 if (!found) {
671 TALLOC_FREE(sids);
672 status = NT_STATUS_MEMBER_NOT_IN_ALIAS;
673 goto cancel;
676 if (i < num)
677 sids[i] = sids[num-1];
679 num -= 1;
681 sid_to_fstring(sid_string, member);
683 key = talloc_asprintf(sids, "%s%s", MEMBEROF_PREFIX, sid_string);
684 if (key == NULL) {
685 TALLOC_FREE(sids);
686 status = NT_STATUS_NO_MEMORY;
687 goto cancel;
690 if (num == 0) {
691 status = dbwrap_delete_bystring(db, key);
692 goto commit;
695 member_string = talloc_strdup(sids, "");
696 if (member_string == NULL) {
697 TALLOC_FREE(sids);
698 status = NT_STATUS_NO_MEMORY;
699 goto cancel;
702 for (i=0; i<num; i++) {
704 sid_to_fstring(sid_string, &sids[i]);
706 member_string = talloc_asprintf_append_buffer(
707 member_string, " %s", sid_string);
709 if (member_string == NULL) {
710 TALLOC_FREE(sids);
711 status = NT_STATUS_NO_MEMORY;
712 goto cancel;
716 status = dbwrap_store_bystring(
717 db, key, string_term_tdb_data(member_string), 0);
718 commit:
719 TALLOC_FREE(sids);
721 if (!NT_STATUS_IS_OK(status)) {
722 DEBUG(10, ("dbwrap_store_bystring failed: %s\n",
723 nt_errstr(status)));
724 goto cancel;
727 if (db->transaction_commit(db) != 0) {
728 DEBUG(0, ("transaction_commit failed\n"));
729 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
730 return status;
733 return NT_STATUS_OK;
735 cancel:
736 if (db->transaction_cancel(db) != 0) {
737 smb_panic("transaction_cancel failed");
739 return status;
743 /* -- ldb->tdb switching code -------------------------------------------- */
745 /* change this if the data format ever changes */
746 #define LTDB_PACKING_FORMAT 0x26011967
748 /* old packing formats (not supported for now,
749 * it was never used for group mapping AFAIK) */
750 #define LTDB_PACKING_FORMAT_NODN 0x26011966
752 static unsigned int pull_uint32(uint8_t *p, int ofs)
754 p += ofs;
755 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
759 unpack a ldb message from a linear buffer in TDB_DATA
761 static int convert_ldb_record(TDB_CONTEXT *ltdb, TDB_DATA key,
762 TDB_DATA data, void *ptr)
764 TALLOC_CTX *tmp_ctx = talloc_tos();
765 GROUP_MAP map;
766 uint8_t *p;
767 uint32_t format;
768 uint32_t num_el;
769 unsigned int remaining;
770 unsigned int i, j;
771 size_t len;
772 char *name;
773 char *val;
774 char *q;
775 uint32_t num_mem = 0;
776 struct dom_sid *members = NULL;
778 p = (uint8_t *)data.dptr;
779 if (data.dsize < 8) {
780 errno = EIO;
781 goto failed;
784 format = pull_uint32(p, 0);
785 num_el = pull_uint32(p, 4);
786 p += 8;
788 remaining = data.dsize - 8;
790 switch (format) {
791 case LTDB_PACKING_FORMAT:
792 len = strnlen((char *)p, remaining);
793 if (len == remaining) {
794 errno = EIO;
795 goto failed;
798 if (*p == '@') {
799 /* ignore special LDB attributes */
800 return 0;
803 if (strncmp((char *)p, "rid=", 4)) {
804 /* unknown entry, ignore */
805 DEBUG(3, ("Found unknown entry in group mapping "
806 "database named [%s]\n", (char *)p));
807 return 0;
810 remaining -= len + 1;
811 p += len + 1;
812 break;
814 case LTDB_PACKING_FORMAT_NODN:
815 default:
816 errno = EIO;
817 goto failed;
820 if (num_el == 0) {
821 /* bad entry, ignore */
822 return 0;
825 if (num_el > remaining / 6) {
826 errno = EIO;
827 goto failed;
830 ZERO_STRUCT(map);
832 for (i = 0; i < num_el; i++) {
833 uint32_t num_vals;
835 if (remaining < 10) {
836 errno = EIO;
837 goto failed;
839 len = strnlen((char *)p, remaining - 6);
840 if (len == remaining - 6) {
841 errno = EIO;
842 goto failed;
844 name = talloc_strndup(tmp_ctx, (char *)p, len);
845 if (name == NULL) {
846 errno = ENOMEM;
847 goto failed;
849 remaining -= len + 1;
850 p += len + 1;
852 num_vals = pull_uint32(p, 0);
853 if (strcasecmp_m(name, "member") == 0) {
854 num_mem = num_vals;
855 members = talloc_array(tmp_ctx, struct dom_sid, num_mem);
856 if (members == NULL) {
857 errno = ENOMEM;
858 goto failed;
860 } else if (num_vals != 1) {
861 errno = EIO;
862 goto failed;
865 p += 4;
866 remaining -= 4;
868 for (j = 0; j < num_vals; j++) {
869 len = pull_uint32(p, 0);
870 if (len > remaining-5) {
871 errno = EIO;
872 goto failed;
875 val = talloc_strndup(tmp_ctx, (char *)(p + 4), len);
876 if (val == NULL) {
877 errno = ENOMEM;
878 goto failed;
881 remaining -= len+4+1;
882 p += len+4+1;
884 /* we ignore unknown or uninteresting attributes
885 * (objectclass, etc.) */
886 if (strcasecmp_m(name, "gidNumber") == 0) {
887 map.gid = strtoul(val, &q, 10);
888 if (*q) {
889 errno = EIO;
890 goto failed;
892 } else if (strcasecmp_m(name, "sid") == 0) {
893 if (!string_to_sid(&map.sid, val)) {
894 errno = EIO;
895 goto failed;
897 } else if (strcasecmp_m(name, "sidNameUse") == 0) {
898 map.sid_name_use = strtoul(val, &q, 10);
899 if (*q) {
900 errno = EIO;
901 goto failed;
903 } else if (strcasecmp_m(name, "ntname") == 0) {
904 strlcpy(map.nt_name, val,
905 sizeof(map.nt_name));
906 } else if (strcasecmp_m(name, "comment") == 0) {
907 strlcpy(map.comment, val,
908 sizeof(map.comment));
909 } else if (strcasecmp_m(name, "member") == 0) {
910 if (!string_to_sid(&members[j], val)) {
911 errno = EIO;
912 goto failed;
916 TALLOC_FREE(val);
919 TALLOC_FREE(name);
922 if (!add_mapping_entry(&map, 0)) {
923 errno = EIO;
924 goto failed;
927 if (num_mem) {
928 for (j = 0; j < num_mem; j++) {
929 NTSTATUS status;
930 status = add_aliasmem(&map.sid, &members[j]);
931 if (!NT_STATUS_IS_OK(status)) {
932 errno = EIO;
933 goto failed;
938 if (remaining != 0) {
939 DEBUG(0, ("Errror: %d bytes unread in ltdb_unpack_data\n",
940 remaining));
943 return 0;
945 failed:
946 return -1;
949 static bool mapping_switch(const char *ldb_path)
951 TDB_CONTEXT *ltdb;
952 TALLOC_CTX *frame;
953 char *new_path;
954 int ret;
956 frame = talloc_stackframe();
958 ltdb = tdb_open_log(ldb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
959 if (ltdb == NULL) goto failed;
961 /* ldb is just a very fancy tdb, read out raw data and perform
962 * conversion */
963 ret = tdb_traverse(ltdb, convert_ldb_record, NULL);
964 if (ret < 0) goto failed;
966 if (ltdb) {
967 tdb_close(ltdb);
968 ltdb = NULL;
971 /* now rename the old db out of the way */
972 new_path = state_path("group_mapping.ldb.replaced");
973 if (!new_path) {
974 goto failed;
976 if (rename(ldb_path, new_path) != 0) {
977 DEBUG(0,("Failed to rename old group mapping database\n"));
978 goto failed;
980 TALLOC_FREE(frame);
981 return True;
983 failed:
984 DEBUG(0, ("Failed to switch to tdb group mapping database\n"));
985 if (ltdb) tdb_close(ltdb);
986 TALLOC_FREE(frame);
987 return False;
990 static const struct mapping_backend tdb_backend = {
991 .add_mapping_entry = add_mapping_entry,
992 .get_group_map_from_sid = get_group_map_from_sid,
993 .get_group_map_from_gid = get_group_map_from_gid,
994 .get_group_map_from_ntname = get_group_map_from_ntname,
995 .group_map_remove = group_map_remove,
996 .enum_group_mapping = enum_group_mapping,
997 .one_alias_membership = one_alias_membership,
998 .add_aliasmem = add_aliasmem,
999 .del_aliasmem = del_aliasmem,
1000 .enum_aliasmem = enum_aliasmem
1004 initialise the tdb mapping backend
1006 const struct mapping_backend *groupdb_tdb_init(void)
1008 if (!init_group_mapping()) {
1009 DEBUG(0,("Failed to initialise tdb mapping backend\n"));
1010 return NULL;
1013 return &tdb_backend;