diff options
-rw-r--r-- | source3/winbindd/idmap_tdb.c | 467 |
1 files changed, 223 insertions, 244 deletions
diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 4c8cceb691..99821ae501 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -40,41 +40,50 @@ static struct idmap_tdb_state { } idmap_tdb_state; +struct convert_fn_state { + struct db_context *db; + bool failed; +}; + /***************************************************************************** For idmap conversion: convert one record to new format Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid instead of the SID. *****************************************************************************/ -static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state) +static int convert_fn(struct db_record *rec, void *private_data) { struct winbindd_domain *domain; char *p; + NTSTATUS status; DOM_SID sid; uint32 rid; fstring keystr; fstring dom_name; TDB_DATA key2; - bool *failed = (bool *)state; + struct convert_fn_state *s = (struct convert_fn_state *)private_data; - DEBUG(10,("Converting %s\n", (const char *)key.dptr)); + DEBUG(10,("Converting %s\n", (const char *)rec->key.dptr)); - p = strchr((const char *)key.dptr, '/'); + p = strchr((const char *)rec->key.dptr, '/'); if (!p) return 0; *p = 0; - fstrcpy(dom_name, (const char *)key.dptr); + fstrcpy(dom_name, (const char *)rec->key.dptr); *p++ = '/'; domain = find_domain_from_name(dom_name); if (domain == NULL) { /* We must delete the old record. */ DEBUG(0,("Unable to find domain %s\n", dom_name )); - DEBUG(0,("deleting record %s\n", (const char *)key.dptr )); - - if (tdb_delete(tdb, key) != 0) { - DEBUG(0, ("Unable to delete record %s\n", (const char *)key.dptr)); - *failed = True; + DEBUG(0,("deleting record %s\n", (const char *)rec->key.dptr )); + + status = rec->delete_rec(rec); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Unable to delete record %s:%s\n", + (const char *)rec->key.dptr, + nt_errstr(status))); + s->failed = true; return -1; } @@ -89,21 +98,30 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state sid_to_fstring(keystr, &sid); key2 = string_term_tdb_data(keystr); - if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) { - DEBUG(0,("Unable to add record %s\n", (const char *)key2.dptr )); - *failed = True; + status = dbwrap_store(s->db, key2, rec->value, TDB_INSERT); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to add record %s:%s\n", + (const char *)key2.dptr, + nt_errstr(status))); + s->failed = true; return -1; } - if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) { - DEBUG(0,("Unable to update record %s\n", (const char *)data.dptr )); - *failed = True; + status = dbwrap_store(s->db, rec->value, key2, TDB_REPLACE); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to update record %s:%s\n", + (const char *)rec->value.dptr, + nt_errstr(status))); + s->failed = true; return -1; } - if (tdb_delete(tdb, key) != 0) { - DEBUG(0,("Unable to delete record %s\n", (const char *)key.dptr )); - *failed = True; + status = rec->delete_rec(rec); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to delete record %s:%s\n", + (const char *)rec->key.dptr, + nt_errstr(status))); + s->failed = true; return -1; } @@ -114,25 +132,17 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state Convert the idmap database from an older version. *****************************************************************************/ -static bool idmap_tdb_upgrade(const char *idmap_name) +static bool idmap_tdb_upgrade(struct db_context *db) { int32 vers; bool bigendianheader; - bool failed = False; - TDB_CONTEXT *idmap_tdb; + struct convert_fn_state s; DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n")); - if (!(idmap_tdb = tdb_open_log(idmap_name, 0, - TDB_DEFAULT, O_RDWR, - 0600))) { - DEBUG(0, ("Unable to open idmap database\n")); - return False; - } - - bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False; + bigendianheader = (db->get_flags(db) & TDB_BIGENDIAN) ? True : False; - vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); + vers = dbwrap_fetch_int32(db, "IDMAP_VERSION"); if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) { /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ @@ -143,7 +153,7 @@ static bool idmap_tdb_upgrade(const char *idmap_name) int32 wm; - wm = tdb_fetch_int32(idmap_tdb, HWM_USER); + wm = dbwrap_fetch_int32(db, HWM_USER); if (wm != -1) { wm = IREV(wm); @@ -151,66 +161,87 @@ static bool idmap_tdb_upgrade(const char *idmap_name) wm = idmap_tdb_state.low_uid; } - if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { + if (dbwrap_store_int32(db, HWM_USER, wm) == -1) { DEBUG(0, ("Unable to byteswap user hwm in idmap database\n")); - tdb_close(idmap_tdb); return False; } - wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); + wm = dbwrap_fetch_int32(db, HWM_GROUP); if (wm != -1) { wm = IREV(wm); } else { wm = idmap_tdb_state.low_gid; } - if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { + if (dbwrap_store_int32(db, HWM_GROUP, wm) == -1) { DEBUG(0, ("Unable to byteswap group hwm in idmap database\n")); - tdb_close(idmap_tdb); return False; } } + s.db = db; + s.failed = false; + /* the old format stored as DOMAIN/rid - now we store the SID direct */ - tdb_traverse(idmap_tdb, convert_fn, &failed); + db->traverse(db, convert_fn, &s); - if (failed) { + if (s.failed) { DEBUG(0, ("Problem during conversion\n")); - tdb_close(idmap_tdb); return False; } - if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) { + if (dbwrap_store_int32(db, "IDMAP_VERSION", IDMAP_VERSION) == -1) { DEBUG(0, ("Unable to dtore idmap version in databse\n")); - tdb_close(idmap_tdb); return False; } - tdb_close(idmap_tdb); return True; } -/* WARNING: We can't open a tdb twice inthe same process, for that reason - * I'm going to use a hack with open ref counts to open the winbindd_idmap.tdb - * only once. We will later decide whether to split the db in multiple files - * or come up with a better solution to share them. */ - -static TDB_CONTEXT *idmap_tdb_common_ctx; -static int idmap_tdb_open_ref_count = 0; - -static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx) +static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, + bool check_config, + struct db_context **dbctx) { NTSTATUS ret; TALLOC_CTX *ctx; - SMB_STRUCT_STAT stbuf; char *tdbfile = NULL; - int32 version; - bool tdb_is_new = False; + struct db_context *db = NULL; + int32_t version; + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; + bool config_error = false; - if (idmap_tdb_open_ref_count) { /* the tdb has already been opened */ - idmap_tdb_open_ref_count++; - *tdbctx = idmap_tdb_common_ctx; - return NT_STATUS_OK; + /* load ranges */ + if (!lp_idmap_uid(&low_uid, &high_uid) + || !lp_idmap_gid(&low_gid, &high_gid)) { + DEBUG(1, ("idmap uid or idmap gid missing\n")); + config_error = true; + if (check_config) { + return NT_STATUS_UNSUCCESSFUL; + } + } + + idmap_tdb_state.low_uid = low_uid; + idmap_tdb_state.high_uid = high_uid; + idmap_tdb_state.low_gid = low_gid; + idmap_tdb_state.high_gid = high_gid; + + if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) { + DEBUG(1, ("idmap uid range missing or invalid\n")); + config_error = true; + if (check_config) { + return NT_STATUS_UNSUCCESSFUL; + } + } + + if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) { + DEBUG(1, ("idmap gid range missing or invalid\n")); + config_error = true; + if (check_config) { + return NT_STATUS_UNSUCCESSFUL; + } } /* use our own context here */ @@ -228,52 +259,47 @@ static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx, TDB_CONTEXT **tdbctx) goto done; } - if (!file_exist_stat(tdbfile, &stbuf)) { - tdb_is_new = True; - } - DEBUG(10,("Opening tdbfile %s\n", tdbfile )); /* Open idmap repository */ - if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) { + db = db_open(ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644); + if (!db) { DEBUG(0, ("Unable to open idmap database\n")); ret = NT_STATUS_UNSUCCESSFUL; goto done; } - if (tdb_is_new) { - /* the file didn't existed before opening it, let's - * store idmap version as nobody else yet opened and - * stored it. I do not like this method but didn't - * found a way to understand if an opened tdb have - * been just created or not --- SSS */ - tdb_store_int32(idmap_tdb_common_ctx, "IDMAP_VERSION", IDMAP_VERSION); - } - /* check against earlier versions */ - version = tdb_fetch_int32(idmap_tdb_common_ctx, "IDMAP_VERSION"); + version = dbwrap_fetch_int32(db, "IDMAP_VERSION"); if (version != IDMAP_VERSION) { - - /* backup_tdb expects the tdb not to be open */ - tdb_close(idmap_tdb_common_ctx); + if (config_error) { + DEBUG(0,("Upgrade of IDMAP_VERSION from %d to %d is not " + "possible with incomplete configuration\n", + version, IDMAP_VERSION)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + if (db->transaction_start(db) != 0) { + DEBUG(0, ("Unable to start upgrade transaction!\n")); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } - if ( ! idmap_tdb_upgrade(tdbfile)) { - + if (!idmap_tdb_upgrade(db)) { + db->transaction_cancel(db); DEBUG(0, ("Unable to open idmap database, it's in an old formati, and upgrade failed!\n")); ret = NT_STATUS_INTERNAL_DB_ERROR; goto done; } - /* Re-Open idmap repository */ - if (!(idmap_tdb_common_ctx = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644))) { - DEBUG(0, ("Unable to open idmap database\n")); - ret = NT_STATUS_UNSUCCESSFUL; + if (db->transaction_commit(db) != 0) { + DEBUG(0, ("Unable to commit upgrade transaction!\n")); + ret = NT_STATUS_INTERNAL_DB_ERROR; goto done; } } - *tdbctx = idmap_tdb_common_ctx; - idmap_tdb_open_ref_count++; + *dbctx = talloc_move(memctx, &db); ret = NT_STATUS_OK; done: @@ -281,29 +307,11 @@ done: return ret; } - /* NEVER use tdb_close() except for the conversion routines that are guaranteed - * to run only when the database is opened the first time, always use this function. */ - -bool idmap_tdb_tdb_close(TDB_CONTEXT *tdbctx) -{ - if (tdbctx != idmap_tdb_common_ctx) { - DEBUG(0, ("ERROR: Invalid tdb context!")); - return False; - } - - idmap_tdb_open_ref_count--; - if (idmap_tdb_open_ref_count) { - return True; - } - - return tdb_close(idmap_tdb_common_ctx); -} - /********************************************************************** IDMAP ALLOC TDB BACKEND **********************************************************************/ -static TDB_CONTEXT *idmap_alloc_tdb; +static struct db_context *idmap_alloc_db; /********************************** Initialise idmap alloc database. @@ -311,74 +319,70 @@ static TDB_CONTEXT *idmap_alloc_tdb; static NTSTATUS idmap_tdb_alloc_init( const char *params ) { - NTSTATUS ret; - TALLOC_CTX *ctx; - uid_t low_uid = 0; - uid_t high_uid = 0; - gid_t low_gid = 0; - gid_t high_gid = 0; - uint32_t low_id; + int ret; + NTSTATUS status; + uint32_t low_uid; + uint32_t low_gid; + bool update_uid = false; + bool update_gid = false; - /* use our own context here */ - ctx = talloc_new(NULL); - if (!ctx) { - DEBUG(0, ("Out of memory!\n")); - return NT_STATUS_NO_MEMORY; + status = idmap_tdb_open_db(NULL, true, &idmap_alloc_db); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("idmap will be unable to map foreign SIDs: %s\n", + nt_errstr(status))); + return status; } - ret = idmap_tdb_open_db(ctx, &idmap_alloc_tdb); - if ( ! NT_STATUS_IS_OK(ret)) { - talloc_free(ctx); - return ret; + low_uid = dbwrap_fetch_int32(idmap_alloc_db, HWM_USER); + if (low_uid == -1 || low_uid < idmap_tdb_state.low_uid) { + update_uid = true; } - talloc_free(ctx); - - /* load ranges */ - - if (!lp_idmap_uid(&low_uid, &high_uid) - || !lp_idmap_gid(&low_gid, &high_gid)) { - DEBUG(1, ("idmap uid or idmap gid missing\n")); - return NT_STATUS_UNSUCCESSFUL; + low_gid = dbwrap_fetch_int32(idmap_alloc_db, HWM_GROUP); + if (low_gid == -1 || low_gid < idmap_tdb_state.low_gid) { + update_gid = true; } - idmap_tdb_state.low_uid = low_uid; - idmap_tdb_state.high_uid = high_uid; - idmap_tdb_state.low_gid = low_gid; - idmap_tdb_state.high_gid = high_gid; - - if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) { - DEBUG(1, ("idmap uid range missing or invalid\n")); - DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); - return NT_STATUS_UNSUCCESSFUL; + if (!update_uid && !update_gid) { + return NT_STATUS_OK; } - if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) { - DEBUG(1, ("idmap gid range missing or invalid\n")); - DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n")); - return NT_STATUS_UNSUCCESSFUL; + if (idmap_alloc_db->transaction_start(idmap_alloc_db) != 0) { + TALLOC_FREE(idmap_alloc_db); + DEBUG(0, ("Unable to start upgrade transaction!\n")); + return NT_STATUS_INTERNAL_DB_ERROR; } - if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_USER)) == -1) || - (low_id < idmap_tdb_state.low_uid)) { - if (tdb_store_int32(idmap_alloc_tdb, HWM_USER, - idmap_tdb_state.low_uid) == -1) { + if (update_uid) { + ret = dbwrap_store_int32(idmap_alloc_db, HWM_USER, + idmap_tdb_state.low_uid); + if (ret == -1) { + idmap_alloc_db->transaction_cancel(idmap_alloc_db); + TALLOC_FREE(idmap_alloc_db); DEBUG(0, ("Unable to initialise user hwm in idmap " "database\n")); return NT_STATUS_INTERNAL_DB_ERROR; } } - if (((low_id = tdb_fetch_int32(idmap_alloc_tdb, HWM_GROUP)) == -1) || - (low_id < idmap_tdb_state.low_gid)) { - if (tdb_store_int32(idmap_alloc_tdb, HWM_GROUP, - idmap_tdb_state.low_gid) == -1) { + if (update_gid) { + ret = dbwrap_store_int32(idmap_alloc_db, HWM_GROUP, + idmap_tdb_state.low_gid); + if (ret == -1) { + idmap_alloc_db->transaction_cancel(idmap_alloc_db); + TALLOC_FREE(idmap_alloc_db); DEBUG(0, ("Unable to initialise group hwm in idmap " "database\n")); return NT_STATUS_INTERNAL_DB_ERROR; } } + if (idmap_alloc_db->transaction_commit(idmap_alloc_db) != 0) { + TALLOC_FREE(idmap_alloc_db); + DEBUG(0, ("Unable to commit upgrade transaction!\n")); + return NT_STATUS_INTERNAL_DB_ERROR; + } + return NT_STATUS_OK; } @@ -414,7 +418,7 @@ static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid) return NT_STATUS_INVALID_PARAMETER; } - if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) { + if ((hwm = dbwrap_fetch_int32(idmap_alloc_db, hwmkey)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -426,9 +430,9 @@ static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid) } /* fetch a new id and increment it */ - ret = tdb_change_uint32_atomic(idmap_alloc_tdb, hwmkey, &hwm, 1); - if (!ret) { - DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype)); + ret = dbwrap_change_uint32_atomic(idmap_alloc_db, hwmkey, &hwm, 1); + if (ret != 0) { + DEBUG(0, ("Fatal error while fetching a new %s value\n!", hwmtype)); return NT_STATUS_UNSUCCESSFUL; } @@ -475,7 +479,7 @@ static NTSTATUS idmap_tdb_get_hwm(struct unixid *xid) return NT_STATUS_INVALID_PARAMETER; } - if ((hwm = tdb_fetch_int32(idmap_alloc_tdb, hwmkey)) == -1) { + if ((hwm = dbwrap_fetch_int32(idmap_alloc_db, hwmkey)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -522,7 +526,7 @@ static NTSTATUS idmap_tdb_set_hwm(struct unixid *xid) hwm = xid->id; - if ((hwm = tdb_store_int32(idmap_alloc_tdb, hwmkey, hwm)) == -1) { + if ((hwm = dbwrap_store_uint32(idmap_alloc_db, hwmkey, hwm)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } @@ -541,13 +545,7 @@ static NTSTATUS idmap_tdb_set_hwm(struct unixid *xid) static NTSTATUS idmap_tdb_alloc_close(void) { - if (idmap_alloc_tdb) { - if (idmap_tdb_tdb_close(idmap_alloc_tdb) == 0) { - return NT_STATUS_OK; - } else { - return NT_STATUS_UNSUCCESSFUL; - } - } + TALLOC_FREE(idmap_alloc_db); return NT_STATUS_OK; } @@ -556,7 +554,7 @@ static NTSTATUS idmap_tdb_alloc_close(void) **********************************************************************/ struct idmap_tdb_context { - TDB_CONTEXT *tdb; + struct db_context *db; uint32_t filter_low_id; uint32_t filter_high_id; }; @@ -585,7 +583,7 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params) goto failed; } - ret = idmap_tdb_open_db(ctx, &ctx->tdb); + ret = idmap_tdb_open_db(ctx, false, &ctx->db); if ( ! NT_STATUS_IS_OK(ret)) { goto failed; } @@ -657,7 +655,7 @@ static NTSTATUS idmap_tdb_id_to_sid(struct idmap_tdb_context *ctx, struct id_map DEBUG(10,("Fetching record %s\n", keystr)); /* Check if the mapping exists */ - data = tdb_fetch_bystring(ctx->tdb, keystr); + data = dbwrap_fetch_bystring(ctx->db, NULL, keystr); if (!data.dptr) { DEBUG(10,("Record %s not found\n", keystr)); @@ -676,7 +674,7 @@ static NTSTATUS idmap_tdb_id_to_sid(struct idmap_tdb_context *ctx, struct id_map ret = NT_STATUS_OK; done: - SAFE_FREE(data.dptr); + talloc_free(data.dptr); talloc_free(keystr); return ret; } @@ -703,7 +701,7 @@ static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map DEBUG(10,("Fetching record %s\n", keystr)); /* Check if sid is present in database */ - data = tdb_fetch_bystring(ctx->tdb, keystr); + data = dbwrap_fetch_bystring(ctx->db, NULL, keystr); if (!data.dptr) { DEBUG(10,("Record %s not found\n", keystr)); ret = NT_STATUS_NONE_MAPPED; @@ -728,7 +726,7 @@ static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map ret = NT_STATUS_INTERNAL_DB_ERROR; } - SAFE_FREE(data.dptr); + TALLOC_FREE(data.dptr); /* apply filters before returning result */ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) || @@ -828,7 +826,7 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, { struct idmap_tdb_context *ctx; NTSTATUS ret; - TDB_DATA ksid, kid, data; + TDB_DATA ksid, kid; char *ksidstr, *kidstr; fstring tmp; @@ -837,7 +835,6 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, } ksidstr = kidstr = NULL; - data.dptr = NULL; /* TODO: should we filter a set_mapping using low/high filters ? */ @@ -877,64 +874,41 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, kid = string_term_tdb_data(kidstr); ksid = string_term_tdb_data(ksidstr); - /* *DELETE* previous mappings if any. - * This is done for both the SID and [U|G]ID passed in */ - - /* NOTE: We should lock both the ksid and kid records here, before - * making modifications. However, because tdb_chainlock() is a - * blocking call we could create an unrecoverable deadlock, so for now - * we only lock the ksid record. */ - - /* Lock the record for this SID. */ - if (tdb_chainlock(ctx->tdb, ksid) != 0) { - DEBUG(10,("Failed to lock record %s. Error %s\n", - ksidstr, tdb_errorstr(ctx->tdb) )); - return NT_STATUS_UNSUCCESSFUL; - } - - data = tdb_fetch(ctx->tdb, ksid); - if (data.dptr) { - DEBUG(10, ("Deleting existing mapping %s <-> %s\n", - (const char *)data.dptr, ksidstr )); - tdb_delete(ctx->tdb, data); - tdb_delete(ctx->tdb, ksid); - SAFE_FREE(data.dptr); + if (ctx->db->transaction_start(ctx->db) != 0) { + DEBUG(0, ("Failed to start transaction for %s\n", + ksidstr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; } - data = tdb_fetch(ctx->tdb, kid); - if (data.dptr) { - DEBUG(10,("Deleting existing mapping %s <-> %s\n", - (const char *)data.dptr, kidstr )); - tdb_delete(ctx->tdb, data); - tdb_delete(ctx->tdb, kid); - SAFE_FREE(data.dptr); + ret = dbwrap_store(ctx->db, ksid, kid, TDB_REPLACE); + if (!NT_STATUS_IS_OK(ret)) { + ctx->db->transaction_cancel(ctx->db); + DEBUG(0, ("Error storing SID -> ID (%s -> %s): %s\n", + ksidstr, kidstr, nt_errstr(ret))); + goto done; } - - if (tdb_store(ctx->tdb, ksid, kid, TDB_INSERT) == -1) { - DEBUG(0, ("Error storing SID -> ID: %s\n", - tdb_errorstr(ctx->tdb))); - tdb_chainunlock(ctx->tdb, ksid); - ret = NT_STATUS_UNSUCCESSFUL; + ret = dbwrap_store(ctx->db, kid, ksid, TDB_REPLACE); + if (!NT_STATUS_IS_OK(ret)) { + ctx->db->transaction_cancel(ctx->db); + DEBUG(0, ("Error storing ID -> SID (%s -> %s): %s\n", + kidstr, ksidstr, nt_errstr(ret))); goto done; } - if (tdb_store(ctx->tdb, kid, ksid, TDB_INSERT) == -1) { - DEBUG(0, ("Error storing ID -> SID: %s\n", - tdb_errorstr(ctx->tdb))); - /* try to remove the previous stored SID -> ID map */ - tdb_delete(ctx->tdb, ksid); - tdb_chainunlock(ctx->tdb, ksid); - ret = NT_STATUS_UNSUCCESSFUL; + + if (ctx->db->transaction_commit(ctx->db) != 0) { + DEBUG(0, ("Failed to commit transaction for (%s -> %s)\n", + ksidstr, kidstr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; goto done; } - tdb_chainunlock(ctx->tdb, ksid); DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr)); ret = NT_STATUS_OK; done: talloc_free(ksidstr); talloc_free(kidstr); - SAFE_FREE(data.dptr); return ret; } @@ -996,23 +970,17 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, ksid = string_term_tdb_data(ksidstr); kid = string_term_tdb_data(kidstr); - /* NOTE: We should lock both the ksid and kid records here, before - * making modifications. However, because tdb_chainlock() is a - * blocking call we could create an unrecoverable deadlock, so for now - * we only lock the ksid record. */ - - /* Lock the record for this SID. */ - if (tdb_chainlock(ctx->tdb, ksid) != 0) { - DEBUG(10,("Failed to lock record %s. Error %s\n", - ksidstr, tdb_errorstr(ctx->tdb) )); - return NT_STATUS_UNSUCCESSFUL; + if (ctx->db->transaction_start(ctx->db) != 0) { + DEBUG(0, ("Failed to start transaction for %s\n", + ksidstr)); + return NT_STATUS_INTERNAL_DB_ERROR; } /* Check if sid is present in database */ - data = tdb_fetch(ctx->tdb, ksid); + data = dbwrap_fetch(ctx->db, NULL, ksid); if (!data.dptr) { + ctx->db->transaction_cancel(ctx->db); DEBUG(10,("Record %s not found\n", ksidstr)); - tdb_chainunlock(ctx->tdb, ksid); ret = NT_STATUS_NONE_MAPPED; goto done; } @@ -1020,10 +988,10 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, /* Check if sid is mapped to the specified ID */ if ((data.dsize != kid.dsize) || (memcmp(data.dptr, kid.dptr, data.dsize) != 0)) { + ctx->db->transaction_cancel(ctx->db); DEBUG(10,("Specified SID does not map to specified ID\n")); DEBUGADD(10,("Actual mapping is %s -> %s\n", ksidstr, (const char *)data.dptr)); - tdb_chainunlock(ctx->tdb, ksid); ret = NT_STATUS_NONE_MAPPED; goto done; } @@ -1033,18 +1001,32 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, /* Delete previous mappings. */ DEBUG(10, ("Deleting existing mapping %s -> %s\n", ksidstr, kidstr )); - tdb_delete(ctx->tdb, ksid); + ret = dbwrap_delete(ctx->db, ksid); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Warning: Failed to delete %s: %s\n", + ksidstr, nt_errstr(ret))); + } DEBUG(10,("Deleting existing mapping %s -> %s\n", kidstr, ksidstr )); - tdb_delete(ctx->tdb, kid); + ret = dbwrap_delete(ctx->db, kid); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Warning: Failed to delete %s: %s\n", + kidstr, nt_errstr(ret))); + } + + if (ctx->db->transaction_commit(ctx->db) != 0) { + DEBUG(0, ("Failed to commit transaction for (%s -> %s)\n", + ksidstr, kidstr)); + ret = NT_STATUS_INTERNAL_DB_ERROR; + goto done; + } - tdb_chainunlock(ctx->tdb, ksid); ret = NT_STATUS_OK; done: talloc_free(ksidstr); talloc_free(kidstr); - SAFE_FREE(data.dptr); + talloc_free(data.dptr); return ret; } @@ -1059,11 +1041,7 @@ static NTSTATUS idmap_tdb_close(struct idmap_domain *dom) if (dom->private_data) { ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context); - if (idmap_tdb_tdb_close(ctx->tdb) == 0) { - return NT_STATUS_OK; - } else { - return NT_STATUS_UNSUCCESSFUL; - } + TALLOC_FREE(ctx->db); } return NT_STATUS_OK; } @@ -1075,14 +1053,14 @@ struct dump_data { NTSTATUS ret; }; -static int idmap_tdb_dump_one_entry(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, void *pdata) +static int idmap_tdb_dump_one_entry(struct db_record *rec, void *pdata) { struct dump_data *data = talloc_get_type(pdata, struct dump_data); struct id_map *maps; int num_maps = *data->num_maps; /* ignore any record but the ones with a SID as key */ - if (strncmp((const char *)key.dptr, "S-", 2) == 0) { + if (strncmp((const char *)rec->key.dptr, "S-", 2) == 0) { maps = talloc_realloc(NULL, *data->maps, struct id_map, num_maps+1); if ( ! maps) { @@ -1098,21 +1076,21 @@ static int idmap_tdb_dump_one_entry(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA val return -1; } - if (!string_to_sid(maps[num_maps].sid, (const char *)key.dptr)) { - DEBUG(10,("INVALID record %s\n", (const char *)key.dptr)); + if (!string_to_sid(maps[num_maps].sid, (const char *)rec->key.dptr)) { + DEBUG(10,("INVALID record %s\n", (const char *)rec->key.dptr)); /* continue even with errors */ return 0; } /* Try a UID record. */ - if (sscanf((const char *)value.dptr, "UID %u", &(maps[num_maps].xid.id)) == 1) { + if (sscanf((const char *)rec->value.dptr, "UID %u", &(maps[num_maps].xid.id)) == 1) { maps[num_maps].xid.type = ID_TYPE_UID; maps[num_maps].status = ID_MAPPED; *data->num_maps = num_maps + 1; /* Try a GID record. */ } else - if (sscanf((const char *)value.dptr, "GID %u", &(maps[num_maps].xid.id)) == 1) { + if (sscanf((const char *)rec->value.dptr, "GID %u", &(maps[num_maps].xid.id)) == 1) { maps[num_maps].xid.type = ID_TYPE_GID; maps[num_maps].status = ID_MAPPED; *data->num_maps = num_maps + 1; @@ -1121,7 +1099,8 @@ static int idmap_tdb_dump_one_entry(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA val } else { maps[num_maps].status = ID_UNKNOWN; DEBUG(2, ("Found INVALID record %s -> %s\n", - (const char *)key.dptr, (const char *)value.dptr)); + (const char *)rec->key.dptr, + (const char *)rec->value.dptr)); /* do not increment num_maps */ } } @@ -1150,7 +1129,7 @@ static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **ma data->num_maps = num_maps; data->ret = NT_STATUS_OK; - tdb_traverse(ctx->tdb, idmap_tdb_dump_one_entry, data); + ctx->db->traverse_read(ctx->db, idmap_tdb_dump_one_entry, data); if ( ! NT_STATUS_IS_OK(data->ret)) { ret = data->ret; |