summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorGregor Beck <gbeck@sernet.de>2012-05-04 13:51:01 +0200
committerMichael Adam <obnox@samba.org>2012-06-26 19:57:19 +0200
commit0fb847b7380cafffa75976de6cfe48b212eefc55 (patch)
tree6d8fe238e75468777f966cf8e5cfb761be9c3aee /source3
parente78d647ebcdd353af3c270903b88d08ab5004a28 (diff)
downloadsamba-0fb847b7380cafffa75976de6cfe48b212eefc55.tar.gz
samba-0fb847b7380cafffa75976de6cfe48b212eefc55.tar.bz2
samba-0fb847b7380cafffa75976de6cfe48b212eefc55.zip
s3:net registry import: add option --precheck
Signed-off-by: Michael Adam <obnox@samba.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/utils/net.c2
-rw-r--r--source3/utils/net.h1
-rw-r--r--source3/utils/net_registry.c199
3 files changed, 197 insertions, 5 deletions
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 1ce5ee6582..eccb522dc9 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -823,6 +823,8 @@ static struct functable net_func[] = {
{"reg-version", 0, POPT_ARG_INT, &c->opt_reg_version},
{"output", 'o', POPT_ARG_STRING, &c->opt_output},
{"wipe", 0, POPT_ARG_NONE, &c->opt_wipe},
+ /* Options for 'net registry import' */
+ {"precheck", 0, POPT_ARG_STRING, &c->opt_precheck},
POPT_COMMON_SAMBA
{ 0, 0, 0, 0}
};
diff --git a/source3/utils/net.h b/source3/utils/net.h
index 5b9db10bad..2056d894d5 100644
--- a/source3/utils/net.h
+++ b/source3/utils/net.h
@@ -83,6 +83,7 @@ struct net_context {
int opt_reg_version;
const char *opt_output;
int opt_wipe;
+ const char *opt_precheck;
int opt_have_ip;
struct sockaddr_storage opt_dest_ip;
diff --git a/source3/utils/net_registry.c b/source3/utils/net_registry.c
index b466e7e7b7..8a65e0db51 100644
--- a/source3/utils/net_registry.c
+++ b/source3/utils/net_registry.c
@@ -30,6 +30,7 @@
#include "registry/reg_backend_db.h"
#include "registry/reg_import.h"
#include "registry/reg_format.h"
+#include "registry/reg_api_util.h"
#include <assert.h>
#include "../libcli/security/display_sec.h"
#include "../libcli/security/sddl.h"
@@ -1029,6 +1030,192 @@ static WERROR import_delete_val (struct import_ctx* ctx, struct registry_key* pa
return werr;
}
+struct precheck_ctx {
+ TALLOC_CTX *mem_ctx;
+ bool failed;
+};
+
+static WERROR precheck_create_key(struct precheck_ctx *ctx,
+ struct registry_key *parent,
+ const char *name, void **pkey, bool *existing)
+{
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct registry_key *key = NULL;
+
+ if (parent == NULL) {
+ char *subkeyname = NULL;
+ werr = open_hive(frame, name, REG_KEY_READ,
+ &parent, &subkeyname);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_printf("Precheck: open_hive of [%s] failed: %s\n",
+ name, win_errstr(werr));
+ goto done;
+ }
+ name = subkeyname;
+ }
+
+ werr = reg_openkey(frame, parent, name, 0, &key);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_printf("Precheck: openkey [%s] failed: %s\n",
+ name, win_errstr(werr));
+ goto done;
+ }
+
+ if (existing != NULL) {
+ *existing = true;
+ }
+
+ if (pkey != NULL) {
+ *pkey = talloc_steal(ctx->mem_ctx, key);
+ }
+
+done:
+ talloc_free(frame);
+ ctx->failed = !W_ERROR_IS_OK(werr);
+ return werr;
+}
+
+static WERROR precheck_close_key(struct precheck_ctx *ctx,
+ struct registry_key *key)
+{
+ talloc_free(key);
+ return WERR_OK;
+}
+
+static WERROR precheck_delete_key(struct precheck_ctx *ctx,
+ struct registry_key *parent, const char *name)
+{
+ WERROR werr;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct registry_key *key;
+
+ if (parent == NULL) {
+ char *subkeyname = NULL;
+ werr = open_hive(frame, name, REG_KEY_READ,
+ &parent, &subkeyname);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_printf("Precheck: open_hive of [%s] failed: %s\n",
+ name, win_errstr(werr));
+ goto done;
+ }
+ name = subkeyname;
+ }
+
+ werr = reg_openkey(ctx->mem_ctx, parent, name, 0, &key);
+ if (W_ERROR_IS_OK(werr)) {
+ d_printf("Precheck: key [%s\\%s] should not exist\n",
+ parent->key->name, name);
+ werr = WERR_FILE_EXISTS;
+ } else if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
+ werr = WERR_OK;
+ } else {
+ d_printf("Precheck: openkey [%s\\%s] failed: %s\n",
+ parent->key->name, name, win_errstr(werr));
+ }
+
+done:
+ talloc_free(frame);
+ ctx->failed = !W_ERROR_IS_OK(werr);
+ return werr;
+}
+
+static WERROR precheck_create_val(struct precheck_ctx *ctx,
+ struct registry_key *parent,
+ const char *name,
+ const struct registry_value *value)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct registry_value *old;
+ WERROR werr;
+
+ SMB_ASSERT(parent);
+
+ werr = reg_queryvalue(frame, parent, name, &old);
+ if (!W_ERROR_IS_OK(werr)) {
+ d_printf("Precheck: queryvalue \"%s\" of [%s] failed: %s\n",
+ name, parent->key->name, win_errstr(werr));
+ goto done;
+ }
+ if (registry_value_cmp(value, old) != 0) {
+ d_printf("Precheck: unexpected value \"%s\" of key [%s]\n",
+ name, parent->key->name);
+ ctx->failed = true;
+ }
+done:
+ talloc_free(frame);
+ return werr;
+}
+
+static WERROR precheck_delete_val(struct precheck_ctx *ctx,
+ struct registry_key *parent,
+ const char *name)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct registry_value *old;
+ WERROR werr;
+
+ SMB_ASSERT(parent);
+
+ werr = reg_queryvalue(frame, parent, name, &old);
+ if (W_ERROR_IS_OK(werr)) {
+ d_printf("Precheck: value \"%s\" of key [%s] should not exist\n",
+ name, parent->key->name);
+ werr = WERR_FILE_EXISTS;
+ } else if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
+ werr = WERR_OK;
+ } else {
+ printf("Precheck: queryvalue \"%s\" of key [%s] failed: %s\n",
+ name, parent->key->name, win_errstr(werr));
+ }
+
+ talloc_free(frame);
+ ctx->failed = !W_ERROR_IS_OK(werr);
+ return werr;
+}
+
+static bool import_precheck(const char *fname, const char *parse_options)
+{
+ TALLOC_CTX *mem_ctx = talloc_tos();
+ struct precheck_ctx precheck_ctx = {
+ .mem_ctx = mem_ctx,
+ .failed = false,
+ };
+ struct reg_import_callback precheck_callback = {
+ .openkey = NULL,
+ .closekey = (reg_import_callback_closekey_t)&precheck_close_key,
+ .createkey = (reg_import_callback_createkey_t)&precheck_create_key,
+ .deletekey = (reg_import_callback_deletekey_t)&precheck_delete_key,
+ .deleteval = (reg_import_callback_deleteval_t)&precheck_delete_val,
+ .setval = {
+ .registry_value = (reg_import_callback_setval_registry_value_t)
+ &precheck_create_val,
+ },
+ .setval_type = REGISTRY_VALUE,
+ .data = &precheck_ctx
+ };
+ struct reg_parse_callback *parse_callback;
+ int ret;
+
+ if (!fname) {
+ return true;
+ }
+
+ parse_callback = reg_import_adapter(mem_ctx, precheck_callback);
+ if (parse_callback == NULL) {
+ d_printf("talloc failed\n");
+ return false;
+ }
+
+ ret = reg_parse_file(fname, parse_callback, parse_options);
+
+ if (ret < 0 || precheck_ctx.failed) {
+ d_printf("Precheck failed\n");
+ return false;
+ }
+ return true;
+}
+
static int net_registry_import(struct net_context *c, int argc,
const char **argv)
@@ -1050,7 +1237,7 @@ static int net_registry_import(struct net_context *c, int argc,
.setval_type = REGISTRY_VALUE,
.data = &import_ctx
};
-
+ const char *parse_options = (argc > 1) ? argv[1] : NULL;
int ret = -1;
WERROR werr;
@@ -1076,12 +1263,14 @@ static int net_registry_import(struct net_context *c, int argc,
goto done;
}
- ret = reg_parse_file(argv[0],
- reg_import_adapter(frame, import_callback),
- (argc > 1) ? argv[1] : NULL);
+ if (import_precheck(c->opt_precheck, parse_options)) {
+ ret = reg_parse_file(argv[0],
+ reg_import_adapter(frame, import_callback),
+ parse_options);
+ }
if (ret < 0) {
- d_printf("reg_parse_file failed: transaction canceled\n");
+ d_printf("Transaction canceled!\n");
regdb_transaction_cancel();
} else {
werr = regdb_transaction_commit();