From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/utils/dbwrap_tool.c | 593 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 593 insertions(+) create mode 100644 source3/utils/dbwrap_tool.c (limited to 'source3/utils/dbwrap_tool.c') diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c new file mode 100644 index 0000000..eb97d64 --- /dev/null +++ b/source3/utils/dbwrap_tool.c @@ -0,0 +1,593 @@ +/* + Samba Unix/Linux CIFS implementation + + low level TDB/CTDB tool using the dbwrap interface + + Copyright (C) 2009 Michael Adam + Copyright (C) 2011 Bjoern Baumbach + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "lib/cmdline/cmdline.h" +#include "dbwrap/dbwrap.h" +#include "dbwrap/dbwrap_open.h" +#include "messages.h" +#include "util_tdb.h" +#include "cmdline_contexts.h" +#include "lib/param/param.h" + +enum dbwrap_op { OP_FETCH, OP_STORE, OP_DELETE, OP_ERASE, OP_LISTKEYS, + OP_EXISTS }; + +enum dbwrap_type { TYPE_INT32, TYPE_UINT32, TYPE_STRING, TYPE_HEX, TYPE_NONE }; + +static int dbwrap_tool_fetch_int32(struct db_context *db, + const char *keyname, + const char *data) +{ + int32_t value; + NTSTATUS status; + + status = dbwrap_fetch_int32_bystring(db, keyname, &value); + if (!NT_STATUS_IS_OK(status)) { + d_printf("Error fetching int32 from key '%s': %s\n", + keyname, nt_errstr(status)); + return -1; + } + d_printf("%d\n", value); + + return 0; +} + +static int dbwrap_tool_fetch_uint32(struct db_context *db, + const char *keyname, + const char *data) +{ + uint32_t value; + NTSTATUS ret; + + ret = dbwrap_fetch_uint32_bystring(db, keyname, &value); + if (NT_STATUS_IS_OK(ret)) { + d_printf("%u\n", value); + return 0; + } else { + d_fprintf(stderr, "ERROR: could not fetch uint32 key '%s': " + "%s\n", nt_errstr(ret), keyname); + return -1; + } +} + +static int dbwrap_tool_fetch_string(struct db_context *db, + const char *keyname, + const char *data) +{ + TDB_DATA tdbdata; + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + int ret; + + status = dbwrap_fetch_bystring(db, tmp_ctx, keyname, &tdbdata); + if (NT_STATUS_IS_OK(status)) { + d_printf("%-*.*s\n", (int)tdbdata.dsize, (int)tdbdata.dsize, + tdbdata.dptr); + ret = 0; + } else { + d_fprintf(stderr, "ERROR: could not fetch string key '%s': " + "%s\n", nt_errstr(status), keyname); + ret = -1; + } + + talloc_free(tmp_ctx); + return ret; +} + +static int dbwrap_tool_fetch_hex(struct db_context *db, + const char *keyname, + const char *data) +{ + TDB_DATA tdbdata; + DATA_BLOB datablob; + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + char *hex_string; + int ret; + + status = dbwrap_fetch_bystring(db, tmp_ctx, keyname, &tdbdata); + if (NT_STATUS_IS_OK(status)) { + datablob.data = tdbdata.dptr; + datablob.length = tdbdata.dsize; + + hex_string = data_blob_hex_string_upper(tmp_ctx, &datablob); + if (hex_string == NULL) { + d_fprintf(stderr, "ERROR: could not get hex string " + "from data blob\n"); + ret = -1; + } else { + d_printf("%s\n", hex_string); + ret = 0; + } + } else { + d_fprintf(stderr, "ERROR: could not fetch hex key '%s': " + "%s\n", nt_errstr(status), keyname); + ret = -1; + } + + talloc_free(tmp_ctx); + return ret; +} + +static int dbwrap_tool_store_int32(struct db_context *db, + const char *keyname, + const char *data) +{ + NTSTATUS status; + int32_t value = (int32_t)strtol(data, NULL, 10); + + if (dbwrap_is_persistent(db)) { + status = dbwrap_trans_store_int32_bystring(db, keyname, value); + } else { + status = dbwrap_store_int32_bystring(db, keyname, value); + } + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "ERROR: could not store int32 key '%s': %s\n", + keyname, nt_errstr(status)); + return -1; + } + + return 0; +} + +static int dbwrap_tool_store_uint32(struct db_context *db, + const char *keyname, + const char *data) +{ + NTSTATUS status; + uint32_t value = (uint32_t)strtol(data, NULL, 10); + + if (dbwrap_is_persistent(db)) { + status = dbwrap_trans_store_uint32_bystring(db, keyname, value); + } else { + status = dbwrap_store_uint32_bystring(db, keyname, value); + } + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "ERROR: could not store uint32 key '%s': %s\n", + keyname, nt_errstr(status)); + return -1; + } + + return 0; +} + +static int dbwrap_tool_store_string(struct db_context *db, + const char *keyname, + const char *data) +{ + NTSTATUS status; + TDB_DATA tdbdata; + + tdbdata = string_term_tdb_data(data); + + if (dbwrap_is_persistent(db)) { + status = dbwrap_trans_store_bystring(db, keyname, + tdbdata, + TDB_REPLACE); + } else { + status = dbwrap_store_bystring(db, keyname, + tdbdata, + TDB_REPLACE); + } + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "ERROR: could not store string key '%s': %s\n", + keyname, nt_errstr(status)); + return -1; + } + + return 0; +} + +static int dbwrap_tool_store_hex(struct db_context *db, + const char *keyname, + const char *data) +{ + NTSTATUS status; + DATA_BLOB datablob; + TDB_DATA tdbdata; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + datablob = strhex_to_data_blob(tmp_ctx, data); + if(strlen(data) > 0 && datablob.length == 0) { + d_fprintf(stderr, + "ERROR: could not convert hex string to data blob\n" + " Not a valid hex string?\n"); + talloc_free(tmp_ctx); + return -1; + } + + tdbdata.dptr = (unsigned char *)datablob.data; + tdbdata.dsize = datablob.length; + + if (dbwrap_is_persistent(db)) { + status = dbwrap_trans_store_bystring(db, keyname, + tdbdata, + TDB_REPLACE); + } else { + status = dbwrap_store_bystring(db, keyname, + tdbdata, + TDB_REPLACE); + } + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, + "ERROR: could not store string key '%s': %s\n", + keyname, nt_errstr(status)); + talloc_free(tmp_ctx); + return -1; + } + + talloc_free(tmp_ctx); + return 0; +} + +static int dbwrap_tool_delete(struct db_context *db, + const char *keyname, + const char *data) +{ + NTSTATUS status; + + if (dbwrap_is_persistent(db)) { + status = dbwrap_trans_delete_bystring(db, keyname); + } else { + status = dbwrap_delete_bystring(db, keyname); + } + + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "ERROR deleting record %s : %s\n", + keyname, nt_errstr(status)); + return -1; + } + + return 0; +} + +static int dbwrap_tool_exists(struct db_context *db, + const char *keyname, + const char *data) +{ + bool result; + + result = dbwrap_exists(db, string_term_tdb_data(keyname)); + + if (result) { + d_fprintf(stdout, "Key %s exists\n", keyname); + } else { + d_fprintf(stdout, "Key %s does not exist\n", keyname); + } + + return (result)?0:1; +} + +/** + * dbwrap_tool_erase: erase the whole data base + * the keyname argument is not used. + */ +static int dbwrap_tool_erase(struct db_context *db, + const char *keyname, + const char *data) +{ + int ret; + + ret = dbwrap_wipe(db); + + if (ret != 0) { + d_fprintf(stderr, "ERROR erasing the database\n"); + return -1; + } + + return 0; +} + +static int listkey_fn(struct db_record *rec, void *private_data) +{ + TDB_DATA key = dbwrap_record_get_key(rec); + size_t length = key.dsize; + unsigned char *p = (unsigned char *)key.dptr; + + while (length--) { + if (isprint(*p) && !strchr("\"\\", *p)) { + d_printf("%c", *p); + } else { + d_printf("\\%02X", *p); + } + p++; + } + + d_printf("\n"); + + return 0; +} + +static int dbwrap_tool_listkeys(struct db_context *db, + const char *keyname, + const char *data) +{ + NTSTATUS status; + + status = dbwrap_traverse_read(db, listkey_fn, NULL, NULL); + + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "ERROR listing db keys\n"); + return -1; + } + + return 0; +} + +struct dbwrap_op_dispatch_table { + enum dbwrap_op op; + enum dbwrap_type type; + int (*cmd)(struct db_context *db, + const char *keyname, + const char *data); +}; + +struct dbwrap_op_dispatch_table dispatch_table[] = { + { OP_FETCH, TYPE_INT32, dbwrap_tool_fetch_int32 }, + { OP_FETCH, TYPE_UINT32, dbwrap_tool_fetch_uint32 }, + { OP_FETCH, TYPE_STRING, dbwrap_tool_fetch_string }, + { OP_FETCH, TYPE_HEX, dbwrap_tool_fetch_hex }, + { OP_STORE, TYPE_INT32, dbwrap_tool_store_int32 }, + { OP_STORE, TYPE_UINT32, dbwrap_tool_store_uint32 }, + { OP_STORE, TYPE_STRING, dbwrap_tool_store_string }, + { OP_STORE, TYPE_HEX, dbwrap_tool_store_hex }, + { OP_DELETE, TYPE_INT32, dbwrap_tool_delete }, + { OP_ERASE, TYPE_INT32, dbwrap_tool_erase }, + { OP_LISTKEYS, TYPE_INT32, dbwrap_tool_listkeys }, + { OP_EXISTS, TYPE_STRING, dbwrap_tool_exists }, + { 0, 0, NULL }, +}; + +int main(int argc, const char **argv) +{ + struct tevent_context *evt_ctx; + struct messaging_context *msg_ctx; + struct db_context *db; + + uint16_t count; + + const char *dbname; + const char *opname; + enum dbwrap_op op; + const char *keyname = ""; + const char *keytype = "int32"; + enum dbwrap_type type; + const char *valuestr = "0"; + int persistent = 0; + int non_persistent = 0; + int tdb_flags = TDB_DEFAULT; + + TALLOC_CTX *mem_ctx = talloc_stackframe(); + struct loadparm_context *lp_ctx = NULL; + + int ret = 1; + bool ok; + + struct poptOption popt_options[] = { + POPT_AUTOHELP + POPT_COMMON_SAMBA + { "non-persistent", 0, POPT_ARG_NONE, &non_persistent, 0, + "treat the database as non-persistent " + "(CAVEAT: This mode might wipe your database!)", + NULL }, + { "persistent", 0, POPT_ARG_NONE, &persistent, 0, + "treat the database as persistent", + NULL }, + POPT_COMMON_VERSION + POPT_TABLEEND + }; + int opt; + const char **extra_argv; + int extra_argc = 0; + poptContext pc; + + smb_init_locale(); + + setup_logging(argv[0], DEBUG_DEFAULT_STDERR); + + ok = samba_cmdline_init(mem_ctx, + SAMBA_CMDLINE_CONFIG_CLIENT, + false /* require_smbconf */); + if (!ok) { + DBG_ERR("Failed to init cmdline parser!\n"); + TALLOC_FREE(mem_ctx); + exit(1); + } + lp_ctx = samba_cmdline_get_lp_ctx(); + lpcfg_set_cmdline(lp_ctx, "log level", "0"); + + pc = samba_popt_get_context(getprogname(), + argc, + argv, + popt_options, + POPT_CONTEXT_KEEP_FIRST); + if (!ok) { + DBG_ERR("Failed to setup popt context!\n"); + TALLOC_FREE(mem_ctx); + exit(1); + } + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + default: + fprintf(stderr, "Invalid option %s: %s\n", + poptBadOption(pc, 0), poptStrerror(opt)); + goto done; + } + } + + /* setup the remaining options for the main program to use */ + extra_argv = poptGetArgs(pc); + if (extra_argv) { + extra_argv++; + while (extra_argv[extra_argc]) extra_argc++; + } + + if ((extra_argc < 2) || (extra_argc > 5)) { + d_fprintf(stderr, + "USAGE: %s [options] [ [ " + "[]]]\n" + " ops: fetch, store, delete, exists, " + "erase, listkeys\n" + " types: int32, uint32, string, hex\n", + argv[0]); + goto done; + } + + if ((persistent + non_persistent) != 1) { + d_fprintf(stderr, "ERROR: you must specify exactly one " + "of --persistent and --non-persistent\n"); + goto done; + } + if (non_persistent == 1) { + tdb_flags |= TDB_CLEAR_IF_FIRST; + } + + dbname = extra_argv[0]; + opname = extra_argv[1]; + + if (strcmp(opname, "store") == 0) { + if (extra_argc != 5) { + d_fprintf(stderr, "ERROR: operation 'store' requires " + "value argument\n"); + goto done; + } + valuestr = extra_argv[4]; + keytype = extra_argv[3]; + keyname = extra_argv[2]; + op = OP_STORE; + } else if (strcmp(opname, "fetch") == 0) { + if (extra_argc != 4) { + d_fprintf(stderr, "ERROR: operation 'fetch' requires " + "type but not value argument\n"); + goto done; + } + op = OP_FETCH; + keytype = extra_argv[3]; + keyname = extra_argv[2]; + } else if (strcmp(opname, "delete") == 0) { + if (extra_argc != 3) { + d_fprintf(stderr, "ERROR: operation 'delete' does " + "not allow type nor value argument\n"); + goto done; + } + keyname = extra_argv[2]; + op = OP_DELETE; + } else if (strcmp(opname, "erase") == 0) { + if (extra_argc != 2) { + d_fprintf(stderr, "ERROR: operation 'erase' does " + "not take a key argument\n"); + goto done; + } + op = OP_ERASE; + } else if (strcmp(opname, "listkeys") == 0) { + if (extra_argc != 2) { + d_fprintf(stderr, "ERROR: operation 'listkeys' does " + "not take a key argument\n"); + goto done; + } + op = OP_LISTKEYS; + } else if (strcmp(opname, "exists") == 0) { + if (extra_argc != 3) { + d_fprintf(stderr, "ERROR: operation 'exists' does " + "not allow type nor value argument\n"); + goto done; + } + keyname = extra_argv[2]; + op = OP_EXISTS; + keytype = "string"; + } else { + d_fprintf(stderr, + "ERROR: invalid op '%s' specified\n" + " supported ops: fetch, store, delete, exists, " + "erase, listkeys\n", + opname); + goto done; + } + + if (strcmp(keytype, "int32") == 0) { + type = TYPE_INT32; + } else if (strcmp(keytype, "uint32") == 0) { + type = TYPE_UINT32; + } else if (strcmp(keytype, "string") == 0) { + type = TYPE_STRING; + } else if (strcmp(keytype, "hex") == 0) { + type = TYPE_HEX; + } else if (strcmp(keytype, "none") == 0) { + type = TYPE_NONE; + } else { + d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n" + " supported types: int32, uint32, " + "string, hex, none\n", + keytype); + goto done; + } + + evt_ctx = samba_tevent_context_init(mem_ctx); + if (evt_ctx == NULL) { + d_fprintf(stderr, "ERROR: could not init event context\n"); + goto done; + } + + msg_ctx = messaging_init(mem_ctx, evt_ctx); + if (msg_ctx == NULL) { + d_fprintf(stderr, "ERROR: could not init messaging context\n"); + goto done; + } + + switch (op) { + case OP_FETCH: + case OP_STORE: + case OP_DELETE: + case OP_ERASE: + case OP_LISTKEYS: + case OP_EXISTS: + db = db_open(mem_ctx, dbname, 0, tdb_flags, O_RDWR | O_CREAT, + 0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + if (db == NULL) { + d_fprintf(stderr, "ERROR: could not open dbname\n"); + goto done; + } + break; + default: + db = NULL; + break; + } + + for (count = 0; dispatch_table[count].cmd != NULL; count++) { + if ((op == dispatch_table[count].op) && + (type == dispatch_table[count].type)) + { + ret = dispatch_table[count].cmd(db, keyname, valuestr); + break; + } + } + +done: + poptFreeContext(pc); + TALLOC_FREE(mem_ctx); + return ret; +} -- cgit v1.2.3