* Unix SMB/CIFS implementation.
* Virtual Windows Registry Layer
* Copyright (C) Gerald Carter 2002-2005
- * Copyright (C) Michael Adam 2007-2009
+ * Copyright (C) Michael Adam 2007-2011
+ * Copyright (C) Gregor Beck 2011
*
* 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
#include "reg_objects.h"
#include "nt_printing.h"
#include "util_tdb.h"
-#include "dbwrap.h"
+#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_open.h"
#include "../libcli/security/secdesc.h"
#undef DBGC_CLASS
static int regdb_refcount;
static bool regdb_key_exists(struct db_context *db, const char *key);
-static bool regdb_key_is_base_key(const char *key);
static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
struct regsubkey_ctr *ctr);
static bool regdb_store_keys_internal(struct db_context *db, const char *key,
const char *key;
const char *subkey;
const char *path;
+ bool lazy;
};
static NTSTATUS regdb_delete_subkey_action(struct db_context *db,
werr = regdb_delete_key_lists(db, delete_ctx->path);
W_ERROR_NOT_OK_GOTO_DONE(werr);
+ if (delete_ctx->lazy) {
+ goto done;
+ }
+
werr = regsubkey_ctr_init(mem_ctx, &subkeys);
W_ERROR_NOT_OK_GOTO_DONE(werr);
return werror_to_ntstatus(werr);
}
-static WERROR regdb_delete_subkey(const char *key, const char *subkey)
+static WERROR regdb_delete_subkey(const char *key, const char *subkey, bool lazy)
{
WERROR werr;
char *path;
delete_ctx.key = key;
delete_ctx.subkey = subkey;
delete_ctx.path = path;
+ delete_ctx.lazy = lazy;
werr = ntstatus_to_werror(dbwrap_trans_do(regdb,
regdb_delete_subkey_action,
/**
- * check whether a given key name represents a base key,
- * i.e one without a subkey separator ('\').
+ * Check for the existence of a key.
+ *
+ * Existence of a key is authoritatively defined by
+ * the existence of the record that contains the list
+ * of its subkeys.
+ *
+ * Return false, if the record does not match the correct
+ * structure of an initial 4-byte counter and then a
+ * list of the corresponding number of zero-terminated
+ * strings.
*/
-static bool regdb_key_is_base_key(const char *key)
+static bool regdb_key_exists(struct db_context *db, const char *key)
{
TALLOC_CTX *mem_ctx = talloc_stackframe();
+ TDB_DATA value;
bool ret = false;
char *path;
+ uint32_t buflen;
+ const char *buf;
+ uint32_t num_items, i;
+ int32_t len;
if (key == NULL) {
goto done;
goto done;
}
- ret = (strrchr(path, '\\') == NULL);
-
-done:
- TALLOC_FREE(mem_ctx);
- return ret;
-}
+ value = regdb_fetch_key_internal(db, mem_ctx, path);
+ if (value.dptr == NULL) {
+ goto done;
+ }
-/**
- * Check for the existence of a key.
- *
- * Existence of a key is authoritatively defined by
- * the existence of the record that contains the list
- * of its subkeys.
- */
-static bool regdb_key_exists(struct db_context *db, const char *key)
-{
- TALLOC_CTX *mem_ctx = talloc_stackframe();
- TDB_DATA value;
- bool ret = false;
- char *path;
+ if (value.dsize == 0) {
+ DEBUG(10, ("regdb_key_exists: subkeylist-record for key "
+ "[%s] is empty: Could be a deleted record in a "
+ "clustered (ctdb) environment?\n",
+ path));
+ goto done;
+ }
- if (key == NULL) {
+ len = tdb_unpack(value.dptr, value.dsize, "d", &num_items);
+ if (len == (int32_t)-1) {
+ DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
+ "[%s] is invalid: Could not parse initial 4-byte "
+ "counter. record data length is %u.\n",
+ path, (unsigned int)value.dsize));
goto done;
}
- path = normalize_reg_path(mem_ctx, key);
- if (path == NULL) {
- DEBUG(0, ("out of memory! (talloc failed)\n"));
+ /*
+ * Note: the tdb_unpack check above implies that len <= value.dsize
+ */
+ buflen = value.dsize - len;
+ buf = (const char *)value.dptr + len;
+
+ len = 0;
+
+ for (i = 0; i < num_items; i++) {
+ if (buflen == 0) {
+ break;
+ }
+ len = strnlen(buf, buflen) + 1;
+ if (buflen < len) {
+ DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record "
+ "for key [%s] is corrupt: %u items expected, "
+ "item number %u is not zero terminated.\n",
+ path, num_items, i+1));
+ goto done;
+ }
+
+ buf += len;
+ buflen -= len;
+ }
+
+ if (buflen > 0) {
+ DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
+ "[%s] is corrupt: %u items expected and found, but "
+ "the record contains additional %u bytes\n",
+ path, num_items, buflen));
goto done;
}
- if (*path == '\0') {
+ if (i < num_items) {
+ DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
+ "[%s] is corrupt: %u items expected, but only %u "
+ "items found.\n",
+ path, num_items, i+1));
goto done;
}
- value = regdb_fetch_key_internal(db, mem_ctx, path);
- ret = (value.dptr != NULL);
+ ret = true;
done:
TALLOC_FREE(mem_ctx);
goto done;
}
+ werr = regsubkey_ctr_reinit(ctr);
+ W_ERROR_NOT_OK_GOTO_DONE(werr);
+
werr = regsubkey_ctr_set_seqnum(ctr, db->get_seqnum(db));
W_ERROR_NOT_OK_GOTO_DONE(werr);
goto done;
}
- werr = regsubkey_ctr_reinit(ctr);
- W_ERROR_NOT_OK_GOTO_DONE(werr);
-
for (i=0; i<num_items; i++) {
len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
werr = regsubkey_ctr_addkey(ctr, subkeyname);