summaryrefslogtreecommitdiff
path: root/source3/groupdb/mapping_tdb.c
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2010-02-26 15:16:23 -0500
committerSimo Sorce <idra@samba.org>2010-03-01 16:09:58 -0500
commitbe026a6fd89b44ba7e6bdf5bef049959b242c61e (patch)
tree7438e43c03d916c6f331ad460fcb0d9dd2a1c127 /source3/groupdb/mapping_tdb.c
parent05bd8c17be83057b9bcfe405fb29d27a794b9b40 (diff)
downloadsamba-be026a6fd89b44ba7e6bdf5bef049959b242c61e.tar.gz
samba-be026a6fd89b44ba7e6bdf5bef049959b242c61e.tar.bz2
samba-be026a6fd89b44ba7e6bdf5bef049959b242c61e.zip
s3:groupmap revert to tdb storage
Group mapping needs to be cluster aware, and this means using the tdb backend. Remove ldb group mapping as this is not cluster aware.
Diffstat (limited to 'source3/groupdb/mapping_tdb.c')
-rw-r--r--source3/groupdb/mapping_tdb.c279
1 files changed, 267 insertions, 12 deletions
diff --git a/source3/groupdb/mapping_tdb.c b/source3/groupdb/mapping_tdb.c
index 8498f0c821..06d35fe7c2 100644
--- a/source3/groupdb/mapping_tdb.c
+++ b/source3/groupdb/mapping_tdb.c
@@ -25,15 +25,22 @@
static struct db_context *db; /* used for driver files */
-static bool enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use, GROUP_MAP **pp_rmap,
- size_t *p_num_entries, bool unix_only);
+static bool enum_group_mapping(const DOM_SID *domsid,
+ enum lsa_SidType sid_name_use,
+ GROUP_MAP **pp_rmap,
+ size_t *p_num_entries,
+ bool unix_only);
static bool group_map_remove(const DOM_SID *sid);
-
+
+static bool mapping_switch(const char *ldb_path);
+
/****************************************************************************
Open the group mapping tdb.
****************************************************************************/
static bool init_group_mapping(void)
{
+ const char *ldb_path;
+
if (db != NULL) {
return true;
}
@@ -46,13 +53,14 @@ static bool init_group_mapping(void)
return false;
}
-#if 0
- /*
- * This code was designed to handle a group mapping version
- * upgrade. mapping_tdb is not active by default anymore, so ignore
- * this here.
- */
- {
+ ldb_path = state_path("group_mapping.ldb");
+ if (file_exist(ldb_path) && !mapping_switch(ldb_path)) {
+ unlink(state_path("group_mapping.tdb"));
+ return false;
+
+ } else {
+ /* handle upgrade from old versions of the database */
+#if 0 /* -- Needs conversion to dbwrap -- */
const char *vstring = "INFO/version";
int32 vers_id;
GROUP_MAP *map_table = NULL;
@@ -96,9 +104,8 @@ static bool init_group_mapping(void)
SAFE_FREE( map_table );
}
- }
#endif
-
+ }
return true;
}
@@ -719,6 +726,254 @@ static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
return status;
}
+
+/* -- ldb->tdb switching code -------------------------------------------- */
+
+/* change this if the data format ever changes */
+#define LTDB_PACKING_FORMAT 0x26011967
+
+/* old packing formats (not supported for now,
+ * it was never used for group mapping AFAIK) */
+#define LTDB_PACKING_FORMAT_NODN 0x26011966
+
+static unsigned int pull_uint32(uint8_t *p, int ofs)
+{
+ p += ofs;
+ return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+}
+
+/*
+ unpack a ldb message from a linear buffer in TDB_DATA
+*/
+static int convert_ldb_record(TDB_CONTEXT *ltdb, TDB_DATA key,
+ TDB_DATA data, void *ptr)
+{
+ TALLOC_CTX *tmp_ctx = talloc_tos();
+ GROUP_MAP map;
+ uint8_t *p;
+ uint32_t format;
+ uint32_t num_el;
+ unsigned int remaining;
+ unsigned int i, j;
+ size_t len;
+ char *name;
+ char *val;
+ char *q;
+ uint32_t num_mem = 0;
+ DOM_SID *members;
+
+ p = (uint8_t *)data.dptr;
+ if (data.dsize < 8) {
+ errno = EIO;
+ goto failed;
+ }
+
+ format = pull_uint32(p, 0);
+ num_el = pull_uint32(p, 4);
+ p += 8;
+
+ remaining = data.dsize - 8;
+
+ switch (format) {
+ case LTDB_PACKING_FORMAT:
+ len = strnlen((char *)p, remaining);
+ if (len == remaining) {
+ errno = EIO;
+ goto failed;
+ }
+
+ if (*p == '@') {
+ /* ignore special LDB attributes */
+ return 0;
+ }
+
+ if (strncmp((char *)p, "rid=", 4)) {
+ /* unknown entry, ignore */
+ DEBUG(3, ("Found unknown entry in group mapping "
+ "database named [%s]\n", (char *)p));
+ return 0;
+ }
+
+ remaining -= len + 1;
+ p += len + 1;
+ break;
+
+ case LTDB_PACKING_FORMAT_NODN:
+ default:
+ errno = EIO;
+ goto failed;
+ }
+
+ if (num_el == 0) {
+ /* bad entry, ignore */
+ return 0;
+ }
+
+ if (num_el > remaining / 6) {
+ errno = EIO;
+ goto failed;
+ }
+
+ ZERO_STRUCT(map);
+
+ for (i = 0; i < num_el; i++) {
+ uint32_t num_vals;
+
+ if (remaining < 10) {
+ errno = EIO;
+ goto failed;
+ }
+ len = strnlen((char *)p, remaining - 6);
+ if (len == remaining - 6) {
+ errno = EIO;
+ goto failed;
+ }
+ name = talloc_strndup(tmp_ctx, (char *)p, len);
+ if (name == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
+ remaining -= len + 1;
+ p += len + 1;
+
+ num_vals = pull_uint32(p, 0);
+ if (StrCaseCmp(name, "member") == 0) {
+ num_mem = num_vals;
+ members = talloc_array(tmp_ctx, DOM_SID, num_mem);
+ if (members == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
+ } else if (num_vals != 1) {
+ errno = EIO;
+ goto failed;
+ }
+
+ p += 4;
+ remaining -= 4;
+
+ for (j = 0; j < num_vals; j++) {
+ len = pull_uint32(p, 0);
+ if (len > remaining-5) {
+ errno = EIO;
+ goto failed;
+ }
+
+ val = talloc_strndup(tmp_ctx, (char *)(p + 4), len);
+ if (val == NULL) {
+ errno = ENOMEM;
+ goto failed;
+ }
+
+ remaining -= len+4+1;
+ p += len+4+1;
+
+ /* we ignore unknown or uninteresting attributes
+ * (objectclass, etc.) */
+ if (StrCaseCmp(name, "gidNumber") == 0) {
+ map.gid = strtoul(val, &q, 10);
+ if (*q) {
+ errno = EIO;
+ goto failed;
+ }
+ } else if (StrCaseCmp(name, "sid") == 0) {
+ if (!string_to_sid(&map.sid, val)) {
+ errno = EIO;
+ goto failed;
+ }
+ } else if (StrCaseCmp(name, "sidNameUse") == 0) {
+ map.sid_name_use = strtoul(val, &q, 10);
+ if (*q) {
+ errno = EIO;
+ goto failed;
+ }
+ } else if (StrCaseCmp(name, "ntname") == 0) {
+ strlcpy(map.nt_name, val,
+ sizeof(map.nt_name) -1);
+ } else if (StrCaseCmp(name, "comment") == 0) {
+ strlcpy(map.comment, val,
+ sizeof(map.comment) -1);
+ } else if (StrCaseCmp(name, "member") == 0) {
+ if (!string_to_sid(&members[j], val)) {
+ errno = EIO;
+ goto failed;
+ }
+ }
+
+ TALLOC_FREE(val);
+ }
+
+ TALLOC_FREE(name);
+ }
+
+ if (!add_mapping_entry(&map, 0)) {
+ errno = EIO;
+ goto failed;
+ }
+
+ if (num_mem) {
+ for (j = 0; j < num_mem; j++) {
+ NTSTATUS status;
+ status = add_aliasmem(&map.sid, &members[j]);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = EIO;
+ goto failed;
+ }
+ }
+ }
+
+ if (remaining != 0) {
+ DEBUG(0, ("Errror: %d bytes unread in ltdb_unpack_data\n",
+ remaining));
+ }
+
+ return 0;
+
+failed:
+ return -1;
+}
+
+static bool mapping_switch(const char *ldb_path)
+{
+ static TALLOC_CTX *ltdb;
+ TALLOC_CTX *frame;
+ char *new_path;
+ int ret;
+
+ frame = talloc_stackframe();
+
+ ltdb = tdb_open_log(ldb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
+ if (ltdb == NULL) goto failed;
+
+ /* ldb is just a very fancy tdb, read out raw data and perform
+ * conversion */
+ ret = tdb_traverse(ltdb, convert_ldb_record, NULL);
+ if (ret == -1) goto failed;
+
+ if (ltdb) {
+ tdb_close(ltdb);
+ ltdb = NULL;
+ }
+
+ /* now rename the old db out of the way */
+ new_path = state_path("group_mapping.ldb.replaced");
+ if (!new_path) {
+ goto failed;
+ }
+ if (rename(ldb_path, new_path) != 0) {
+ DEBUG(0,("Failed to rename old group mapping database\n"));
+ goto failed;
+ }
+ TALLOC_FREE(frame);
+ return True;
+
+failed:
+ DEBUG(0,("Failed to swith to tdb group mapping database\n"));
+ if (ltdb) tdb_close(ltdb);
+ TALLOC_FREE(frame);
+ return False;
+}
+
static const struct mapping_backend tdb_backend = {
.add_mapping_entry = add_mapping_entry,
.get_group_map_from_sid = get_group_map_from_sid,