#include "net_idmap_check.h"
#include "includes.h"
#include "system/filesys.h"
-#include "dbwrap.h"
+#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_open.h"
+#include "dbwrap/dbwrap_rbt.h"
#include "net.h"
#include "../libcli/security/dom_sid.h"
#include "cbuf.h"
#include "srprs.h"
-#include <termios.h>
+#include "util_tdb.h"
+#include "interact.h"
static int traverse_commit(struct db_record *diff_rec, void* data);
static int traverse_check(struct db_record *rec, void* data);
-static char* interact_edit(TALLOC_CTX* mem_ctx, const char* str);
-static int interact_prompt(const char* msg, const char* accept, char def);
-
/* TDB_DATA *******************************************************************/
static char* print_data(TALLOC_CTX* mem_ctx, TDB_DATA d);
static TDB_DATA parse_data(TALLOC_CTX* mem_ctx, const char** ptr);
static TDB_DATA talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data);
-static bool is_empty(TDB_DATA data) {
- return (data.dsize == 0) || (data.dptr == NULL);
-}
/* record *********************************************************************/
enum DT {
DT_INV = 0,
DT_SID, DT_UID, DT_GID,
- DT_HWM, DT_VER
+ DT_HWM, DT_VER, DT_SEQ,
};
struct record {
d_printf("%s: %s ", a->name, print_data(r, r->key));
if (is_map(r)) {
d_printf("-> %s\n", print_data(r, r->val));
- } else {
+ } else if (r->key_type == DT_HWM ||
+ r->key_type == DT_VER ||
+ r->key_type == DT_SEQ)
+ {
d_printf(": %ld\n", r->id);
+ } else {
+ d_printf("\n");
}
} else {
d_printf(a->fmt, a->name,
#define DEBUG_DIFF(LEV,MEM,MSG,KEY,OLD,NEW) \
DEBUG(LEV, ("%s: %s\n", MSG, print_data(MEM, KEY))); \
- if (!is_empty(OLD)) { \
+ if (!tdb_data_is_empty(OLD)) { \
DEBUGADD(LEV, ("-%s\n", print_data(MEM, OLD))); \
} \
- if (!is_empty(NEW)) { \
+ if (!tdb_data_is_empty(NEW)) { \
DEBUGADD(LEV, ("+%s\n", print_data(MEM, NEW))); \
}
NTSTATUS status;
TDB_DATA_diff diff;
TALLOC_CTX* mem = talloc_new(ctx->diff);
- struct db_record* rec = ctx->diff->fetch_locked(ctx->diff, mem, key);
+ TDB_DATA recvalue;
+ struct db_record *rec = dbwrap_fetch_locked(ctx->diff, mem, key);
+
if (rec == NULL) {
return -1;
- };
- if (rec->value.dptr == 0) { /* first entry */
- diff.oval = dbwrap_fetch(ctx->db, ctx->diff, key);
+ }
+
+ recvalue = dbwrap_record_get_value(rec);
+
+ if (recvalue.dptr == 0) { /* first entry */
+ status = dbwrap_fetch(ctx->db, ctx->diff, key, &diff.oval);
+ if (!NT_STATUS_IS_OK(status)) {
+ diff.oval = tdb_null;
+ }
} else {
- diff = unpack_diff(rec->value);
+ diff = unpack_diff(recvalue);
talloc_free(diff.nval.dptr);
}
diff.nval = talloc_copy(ctx->diff, value);
DEBUG_DIFF(2, mem, "TDB DIFF", key, diff.oval, diff.nval);
- status = rec->store(rec, pack_diff(&diff), 0);
+ status = dbwrap_record_store(rec, pack_diff(&diff), 0);
talloc_free(mem);
fetch_record(struct check_ctx* ctx, TALLOC_CTX* mem_ctx, TDB_DATA key)
{
TDB_DATA tmp;
+ NTSTATUS status;
- if (ctx->diff->fetch(ctx->diff, mem_ctx, key, &tmp) == -1) {
- DEBUG(0, ("Out of memory!\n"));
- return tdb_null;
- }
- if (tmp.dptr != NULL) {
+ status = dbwrap_fetch(ctx->diff, mem_ctx, key, &tmp);
+
+ if (NT_STATUS_IS_OK(status)) {
TDB_DATA_diff diff = unpack_diff(tmp);
TDB_DATA ret = talloc_copy(mem_ctx, diff.nval);
talloc_free(tmp.dptr);
return ret;
}
- if (ctx->db->fetch(ctx->db, mem_ctx, key, &tmp) == -1) {
- DEBUG(0, ("Out of memory!\n"));
+ status = dbwrap_fetch(ctx->db, mem_ctx, key, &tmp);
+ if (!NT_STATUS_IS_OK(status)) {
return tdb_null;
}
static bool check_version(struct check_ctx* ctx) {
static const char* key = "IDMAP_VERSION";
uint32_t version;
- bool no_version = !dbwrap_fetch_uint32(ctx->db, key, &version);
+ NTSTATUS status;
char action = 's';
struct check_actions* act = &ctx->action;
- if (no_version) {
+
+ status = dbwrap_fetch_uint32(ctx->db, key, &version);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("No version number, assume 2\n");
action = get_action(&act->no_version, NULL, NULL);
} else if (version != 2) {
static void check_hwm(struct check_ctx* ctx, const char* key, uint32_t target) {
uint32_t hwm;
char action = 's';
- bool found = dbwrap_fetch_uint32(ctx->db, key, &hwm);
+ NTSTATUS status;
struct check_actions* act = &ctx->action;
- if (!found) {
+
+ status = dbwrap_fetch_uint32(ctx->db, key, &hwm);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("No %s should be %d\n", key, target);
action = get_action(&act->invalid_hwm, NULL, NULL);
} else if (target < hwm) {
struct check_ctx* ctx = (struct check_ctx*)data;
struct check_actions* act = &ctx->action;
TALLOC_CTX* mem = talloc_new(ctx->diff);
- struct record* r = parse_record(mem, rec->key, rec->value);
+ TDB_DATA key;
+ TDB_DATA value;
+ struct record *r;
char action = 's';
+ key = dbwrap_record_get_key(rec);
+ value = dbwrap_record_get_value(rec);
+
+ r = parse_record(mem, key, value);
+
if (is_invalid(r)) {
action = get_action(&act->invalid_record, r, NULL);
ctx->n_invalid_record++;
case 's': /* skip */
break;
case 'd': /* delete */
- del_record(ctx, rec->key);
+ del_record(ctx, key);
break;
case 'f': /* add reverse mapping */
- add_record(ctx, rec->value, rec->key);
+ add_record(ctx, value, key);
break;
case 'e': /* edit */
edit_record(r);
action = get_action(&act->invalid_edit, r,NULL);
continue;
}
- if (!tdb_data_equal(rec->key, r->key)) {
+ if (!tdb_data_equal(key, r->key)) {
TDB_DATA oval = fetch_record(ctx, mem, r->key);
- if (!is_empty(oval) &&
+ if (!tdb_data_is_empty(oval) &&
!tdb_data_equal(oval, r->val))
{
action = get_action(&act->record_exists,
}
if (is_map(r)) {
TDB_DATA okey = fetch_record(ctx, mem, r->val);
- if (!is_empty(okey) &&
+ if (!tdb_data_is_empty(okey) &&
!tdb_data_equal(okey, r->key))
{
action = get_action(&act->record_exists,
continue;
case 'o': /* overwrite */
adjust_hwm(ctx, r);
- if (!tdb_data_equal(rec->key, r->key)) {
- del_record(ctx, rec->key);
+ if (!tdb_data_equal(key, r->key)) {
+ del_record(ctx, key);
}
add_record(ctx, r->key, r->val);
if (is_map(r)) {
}
static bool is_cstr(TDB_DATA str) {
- return !is_empty(str) && str.dptr[str.dsize-1] == '\0';
+ return !tdb_data_is_empty(str) && str.dptr[str.dsize-1] == '\0';
}
static bool parse_sid (TDB_DATA str, enum DT* type, struct dom_sid* sid) {
ret->id = IVAL(val.dptr,0);
ret->val_type = DT_VER;
}
+ } else if (strcmp((const char*)key.dptr, "__db_sequence_number__") == 0) {
+ ret->key_type = DT_SEQ;
+ if (val.dsize == 8) {
+ ret->id = *(uint64_t*)val.dptr;
+ ret->val_type = DT_SEQ;
+ }
}
return ret;
/******************************************************************************/
-int interact_prompt(const char* msg, const char* acc, char def) {
- struct termios old_tio, new_tio;
- int c;
-
- tcgetattr(STDIN_FILENO, &old_tio);
- new_tio=old_tio;
- new_tio.c_lflag &=(~ICANON & ~ECHO);
- tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
-
- do {
- d_printf("%s? [%c]\n", msg, def);
- fflush(stdout);
- c = getchar();
- if (c == '\n') {
- c = def;
- break;
- }
- else if (strchr(acc, tolower(c)) != NULL) {
- break;
- }
- d_printf("Invalid input '%c'\n", c);
- } while(c != EOF);
- tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
- return c;
-}
char* print_data(TALLOC_CTX* mem_ctx, TDB_DATA d)
{
- if (!is_empty(d)) {
+ if (!tdb_data_is_empty(d)) {
char* ret = NULL;
cbuf* ost = cbuf_new(mem_ctx);
int len = cbuf_print_quoted(ost, (const char*)d.dptr, d.dsize);
return ret;
}
-static const char* get_editor(void) {
- static const char* editor = NULL;
- if (editor == NULL) {
- editor = getenv("VISUAL");
- if (editor == NULL) {
- editor = getenv("EDITOR");
- }
- if (editor == NULL) {
- editor = "vi";
- }
- }
- return editor;
-}
-
-char* interact_edit(TALLOC_CTX* mem_ctx, const char* str) {
- char fname[] = "/tmp/net_idmap_check.XXXXXX";
- char buf[128];
- char* ret = NULL;
- FILE* file;
-
- int fd = mkstemp(fname);
- if (fd == -1) {
- DEBUG(0, ("failed to mkstemp %s: %s\n", fname,
- strerror(errno)));
- return NULL;
- }
-
- file = fdopen(fd, "w");
- if (!file) {
- DEBUG(0, ("failed to open %s for writing: %s\n", fname,
- strerror(errno)));
- close(fd);
- unlink(fname);
- return NULL;
- }
-
- fprintf(file, "%s", str);
- fclose(file);
-
- snprintf(buf, sizeof(buf), "%s %s\n", get_editor(), fname);
- if (system(buf) != 0) {
- DEBUG(0, ("failed to start editor %s: %s\n", buf,
- strerror(errno)));
- unlink(fname);
- return NULL;
- }
-
- file = fopen(fname, "r");
- if (!file) {
- DEBUG(0, ("failed to open %s for reading: %s\n", fname,
- strerror(errno)));
- unlink(fname);
- return NULL;
- }
- while ( fgets(buf, sizeof(buf), file) ) {
- ret = talloc_strdup_append(ret, buf);
- }
- fclose(file);
- unlink(fname);
-
- return talloc_steal(mem_ctx, ret);
-}
-
-
static int traverse_print_diff(struct db_record *rec, void* data) {
struct check_ctx* ctx = (struct check_ctx*)data;
- TDB_DATA key = rec->key;
- TDB_DATA_diff diff = unpack_diff(rec->value);
+ TDB_DATA key;
+ TDB_DATA value;
+ TDB_DATA_diff diff;
TALLOC_CTX* mem = talloc_new(ctx->diff);
+ key = dbwrap_record_get_key(rec);
+ value = dbwrap_record_get_value(rec);
+ diff = unpack_diff(value);
+
DEBUG_DIFF(0, mem, "DIFF", key, diff.oval, diff.nval);
talloc_free(mem);
static int traverse_commit(struct db_record *diff_rec, void* data) {
struct check_ctx* ctx = (struct check_ctx*)data;
- TDB_DATA_diff diff = unpack_diff(diff_rec->value);
- TDB_DATA key = diff_rec->key;
+ TDB_DATA key;
+ TDB_DATA diff_value;
+ TDB_DATA_diff diff;
+ TDB_DATA value;
TALLOC_CTX* mem = talloc_new(ctx->diff);
int ret = -1;
NTSTATUS status;
struct check_actions* act = &ctx->action;
+ struct db_record* rec;
+
+ key = dbwrap_record_get_key(diff_rec);
+ diff_value = dbwrap_record_get_value(diff_rec);
+ diff = unpack_diff(diff_value);
- struct db_record* rec = ctx->db->fetch_locked(ctx->db, mem, key);
+ rec = dbwrap_fetch_locked(ctx->db, mem, key);
if (rec == NULL) {
goto done;
- };
+ }
+
+ value = dbwrap_record_get_value(rec);
- if (!tdb_data_equal(rec->value, diff.oval)) {
+ if (!tdb_data_equal(value, diff.oval)) {
char action;
d_printf("Warning: record has changed: %s\n"
"expected: %s got %s\n", print_data(mem, key),
print_data(mem, diff.oval),
- print_data(mem, rec->value));
+ print_data(mem, value));
action = get_action(&act->invalid_diff, NULL, NULL);
if (action == 's') {
DEBUG_DIFF(0, mem, "Commit", key, diff.oval, diff.nval);
- if (is_empty(diff.nval)) {
- status = rec->delete_rec(rec);
+ if (tdb_data_is_empty(diff.nval)) {
+ status = dbwrap_record_delete(rec);
} else {
- status = rec->store(rec, diff.nval, 0);
+ status = dbwrap_record_store(rec, diff.nval, 0);
}
if (!NT_STATUS_IS_OK(status)) {
}
}
- ctx->db = db_open(ctx, name, 0, TDB_DEFAULT, oflags, 0);
+ ctx->db = db_open(ctx, name, 0, TDB_DEFAULT, oflags, 0,
+ DBWRAP_LOCK_ORDER_1);
if (ctx->db == NULL) {
d_fprintf(stderr,
_("Could not open idmap db (%s) for writing: %s\n"),
return false;
}
- status = dbwrap_traverse(ctx->db, traverse_check, ctx);
+ status = dbwrap_traverse(ctx->db, traverse_check, ctx, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("failed to traverse %s\n", ctx->name));
}
static bool check_transaction_start(struct check_ctx* ctx) {
- return (ctx->db->transaction_start(ctx->db) == 0);
+ return (dbwrap_transaction_start(ctx->db) == 0);
}
static bool check_transaction_commit(struct check_ctx* ctx) {
- return (ctx->db->transaction_commit(ctx->db) == 0);
+ return (dbwrap_transaction_commit(ctx->db) == 0);
}
static bool check_transaction_cancel(struct check_ctx* ctx) {
- return (ctx->db->transaction_cancel(ctx->db) == 0);
+ return (dbwrap_transaction_cancel(ctx->db) == 0);
}
static void check_diff_list(struct check_ctx* ctx) {
- NTSTATUS status = dbwrap_traverse(ctx->diff, traverse_print_diff, ctx);
+ NTSTATUS status = dbwrap_traverse(ctx->diff, traverse_print_diff, ctx, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("failed to traverse diff\n"));
return false;
}
- status = dbwrap_traverse(ctx->diff, traverse_commit, ctx);
+ status = dbwrap_traverse(ctx->diff, traverse_commit, ctx, NULL);
if (!NT_STATUS_IS_OK(status)) {
check_transaction_cancel(ctx);
return false;
}
- if (ctx->opts.test) { //get_action?
+ if (ctx->opts.test) { /*get_action? */
return check_transaction_cancel(ctx);
} else {
return check_transaction_commit(ctx);