The branch, master has been updated via ac4899e s3:net registry import: implement dry-run with "--test" via 3705119 s3:net registry import: add an assert via 8bf0850 s3:net registry import: reduce indentation via d5ab328 s3:net registry import: fix the return code when transaction commit fails via a3ed47a s3:net registry import: improve regdb_open/close layering via c55a6da s3:net registry import: untangle nested function calls via 20e5e8e s3:net registry import: reduce indentation and untangle assignment from check via f9ff84b s3:net registry import: move precheck-and-import code to its own function via e28b4b1 s3:net registry: fix violation of coding conventions via 0fb847b s3:net registry import: add option --precheck via e78d647 s3:registry: add function registry_value_cmp() via 69add7e s3:net registry import: check return values + codecleanup via cc052d0 s3:net registry: fix output of dwords with sign bit set via 55ce9e1 s3:registry: fix possible double free in import via 619f0c0 s3:registry: improve debug output in reg_parse via e10ea2b s3:registry: add functions to conveniently create registry_values via 35eccd0 s3:registry: silence net_deletekey_recursive via fb706c7 s3:registry: make reg_delete_path() delete the path recursively. via 353f614 s3:registry: compile reg_create_path() & reg_delete_path() from a6c5376 Merge suggested fix from bug 7511 and enhance it
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit ac4899eaa1d1b998959aa694f6cac5c2c425ecfc Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 15:35:32 2012 +0200 s3:net registry import: implement dry-run with "--test" Pair-Programmed-With: Gregor Beck <gb...@sernet.de> Autobuild-User(master): Michael Adam <ob...@samba.org> Autobuild-Date(master): Tue Jun 26 21:43:49 CEST 2012 on sn-devel-104 commit 3705119bb06123068cb8f3780342fd4e6e501b08 Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 15:13:28 2012 +0200 s3:net registry import: add an assert Pair-Programmed-With: Gergor Beck <gb...@sernet.de> commit 8bf08505c1483d0d3a49f703edbed2d31eea6f1f Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 15:12:28 2012 +0200 s3:net registry import: reduce indentation Pair-Programmed-With: Gregor Beck <gb...@sernet.de> commit d5ab3282e454a4581f77250e54ba11761a9c2a63 Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 15:11:22 2012 +0200 s3:net registry import: fix the return code when transaction commit fails Pair-Programmed-With: Gregor Beck <gb...@sernet.de> commit a3ed47a09bfaf3bf100547a4d97e9d8573382a3d Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 15:02:41 2012 +0200 s3:net registry import: improve regdb_open/close layering Pair-Programmed-With: Gregor Beck <gb...@sernet.de> commit c55a6dae655716539edd3e4dd8b4d61e22f1858e Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 13:37:46 2012 +0200 s3:net registry import: untangle nested function calls commit 20e5e8ef266709378b239f0338a3ecb2d175e5a4 Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 13:32:40 2012 +0200 s3:net registry import: reduce indentation and untangle assignment from check in import_with_precheck_action(). commit f9ff84b0b45c66fd2c437228791e3bcf99255dad Author: Michael Adam <ob...@samba.org> Date: Tue Jun 26 13:29:50 2012 +0200 s3:net registry import: move precheck-and-import code to its own function This is the code that is executed in a registry transaction. The purpose of the refactoring is to be able to simplify and untangle the code structure in the sequel. commit e28b4b10a6d8cc13d7c8046a38d6c221915ff55b Author: Gregor Beck <gb...@sernet.de> Date: Wed Jun 13 14:32:55 2012 +0200 s3:net registry: fix violation of coding conventions Signed-off-by: Michael Adam <ob...@samba.org> commit 0fb847b7380cafffa75976de6cfe48b212eefc55 Author: Gregor Beck <gb...@sernet.de> Date: Fri May 4 13:51:01 2012 +0200 s3:net registry import: add option --precheck Signed-off-by: Michael Adam <ob...@samba.org> commit e78d647ebcdd353af3c270903b88d08ab5004a28 Author: Gregor Beck <gb...@sernet.de> Date: Mon May 7 15:43:27 2012 +0200 s3:registry: add function registry_value_cmp() Signed-off-by: Michael Adam <ob...@samba.org> commit 69add7e4fd64c0fc264414991e2d7b0edee09aed Author: Gregor Beck <gb...@sernet.de> Date: Fri May 4 09:35:37 2012 +0200 s3:net registry import: check return values + codecleanup Signed-off-by: Michael Adam <ob...@samba.org> commit cc052d0c7784a184b7d52ca08adc0bdf6d820420 Author: Gregor Beck <gb...@sernet.de> Date: Mon May 7 15:48:16 2012 +0200 s3:net registry: fix output of dwords with sign bit set Signed-off-by: Michael Adam <ob...@samba.org> commit 55ce9e1fa9fb9641200e9b86ad1142dd9cdf4262 Author: Gregor Beck <gb...@sernet.de> Date: Mon May 7 15:44:21 2012 +0200 s3:registry: fix possible double free in import Signed-off-by: Michael Adam <ob...@samba.org> commit 619f0c07ffdf53854701bfa1798bd0d4ce9cfbf2 Author: Gregor Beck <gb...@sernet.de> Date: Mon May 7 15:46:41 2012 +0200 s3:registry: improve debug output in reg_parse Signed-off-by: Michael Adam <ob...@samba.org> commit e10ea2b3cdfd32f810c6058446efb1392eb157ad Author: Gregor Beck <gb...@sernet.de> Date: Mon Apr 30 10:27:56 2012 +0200 s3:registry: add functions to conveniently create registry_values Pair-Programmed-With: Michael Adam <ob...@samba.org> commit 35eccd0f53deb59bfdd80589da38d8ae2467fb8d Author: Gregor Beck <gb...@sernet.de> Date: Wed May 2 11:22:54 2012 +0200 s3:registry: silence net_deletekey_recursive WERR_BADFILE may not be an error for the caller because the result is the same. Signed-off-by: Michael Adam <ob...@samba.org> commit fb706c7365a0db1ef54a928f4eb2c68718516bc8 Author: Michael Adam <ob...@samba.org> Date: Fri May 4 17:57:51 2012 +0200 s3:registry: make reg_delete_path() delete the path recursively. Pair-Programmed-With: Gregor Beck <gb...@sernet.de> (cherry picked from commit a56992ab71032b54d9879834c12f6b88e6174cb4) commit 353f614c96cab858f57100daee21a112bea93291 Author: Gregor Beck <gb...@sernet.de> Date: Mon Apr 30 10:26:32 2012 +0200 s3:registry: compile reg_create_path() & reg_delete_path() Signed-off-by: Michael Adam <ob...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/registry/reg_api.c | 8 +- source3/registry/reg_api_util.c | 79 ++++++++- source3/registry/reg_api_util.h | 9 +- source3/registry/reg_import.c | 1 + source3/registry/reg_parse.c | 3 +- source3/utils/net.c | 2 + source3/utils/net.h | 1 + source3/utils/net_registry.c | 337 +++++++++++++++++++++++++++++++------ source3/utils/net_registry_util.c | 2 +- 9 files changed, 376 insertions(+), 66 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c index 26a1481..b962920 100644 --- a/source3/registry/reg_api.c +++ b/source3/registry/reg_api.c @@ -1010,10 +1010,10 @@ static WERROR reg_deletekey_recursive_trans(struct registry_key *parent, if (!W_ERROR_IS_OK(werr)) { WERROR werr2; - - DEBUG(1, (__location__ " failed to delete key '%s' from key " - "'%s': %s\n", path, parent->key->name, - win_errstr(werr))); + DEBUG(W_ERROR_EQUAL(werr, WERR_BADFILE) ? 5 : 1, + (__location__ ": failed to delete key '%s' from key " + "'%s': %s\n", path, parent->key->name, + win_errstr(werr))); werr2 = regdb_transaction_cancel(); if (!W_ERROR_IS_OK(werr2)) { diff --git a/source3/registry/reg_api_util.c b/source3/registry/reg_api_util.c index 045ad21..e86e3e3 100644 --- a/source3/registry/reg_api_util.c +++ b/source3/registry/reg_api_util.c @@ -26,6 +26,7 @@ #include "registry.h" #include "reg_api.h" #include "reg_api_util.h" +#include "libcli/registry/util_reg.h" /** * Utility function to open a complete registry path including the hive prefix. @@ -82,9 +83,6 @@ WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path, return WERR_OK; } -#if 0 -/* these two functions are unused. */ - /** * Utility function to create a registry key without opening the hive * before. Assumes the hive already exists. @@ -141,8 +139,8 @@ WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path, } /* - * Utility function to create a registry key without opening the hive - * before. Will not delete a hive. + * Utility function to recursively delete a registry key without opening the + * hive before. Will not delete a hive. */ WERROR reg_delete_path(const struct security_token *token, @@ -174,9 +172,76 @@ WERROR reg_delete_path(const struct security_token *token, return err; } - err = reg_deletekey(hive, p+1); + err = reg_deletekey_recursive(hive, p+1); SAFE_FREE(path); TALLOC_FREE(hive); return err; } -#endif /* #if 0 */ + +struct registry_value *registry_value_dw(TALLOC_CTX *mem_ctx, uint32_t dw) +{ + struct registry_value *ret; + + ret = talloc_zero(mem_ctx, struct registry_value); + if (ret == NULL) { + return NULL; + } + + ret->data = data_blob_talloc(ret, NULL, sizeof(uint32_t)); + if (ret->data.data == NULL) { + talloc_free(ret); + return NULL; + } + + ret->type = REG_DWORD; + + SIVAL(ret->data.data, 0, dw); + + return ret; +} + +struct registry_value *registry_value_sz(TALLOC_CTX *mem_ctx, const char *str) +{ + struct registry_value *ret; + + ret = talloc_zero(mem_ctx, struct registry_value); + if (ret == NULL) { + return NULL; + } + + if (!push_reg_sz(ret, &ret->data, str)) { + talloc_free(ret); + return NULL; + } + + ret->type = REG_SZ; + + return ret; +} + +struct registry_value *registry_value_multi_sz(TALLOC_CTX *mem_ctx, const char **str) +{ + struct registry_value *ret; + + ret = talloc_zero(mem_ctx, struct registry_value); + if (ret == NULL) { + return NULL; + } + + if (!push_reg_multi_sz(ret, &ret->data, str)) { + talloc_free(ret); + return NULL; + } + + ret->type = REG_MULTI_SZ; + + return ret; +} + +int registry_value_cmp(const struct registry_value* v1, const struct registry_value* v2) +{ + if (v1->type == v2->type) { + return data_blob_cmp(&v1->data, &v2->data); + } + return v1->type - v2->type; +} diff --git a/source3/registry/reg_api_util.h b/source3/registry/reg_api_util.h index d2d7894..b5ce0fd 100644 --- a/source3/registry/reg_api_util.h +++ b/source3/registry/reg_api_util.h @@ -32,8 +32,6 @@ WERROR reg_open_path(TALLOC_CTX *mem_ctx, const char *orig_path, uint32 desired_access, const struct security_token *token, struct registry_key **pkey); -#if 0 -/* currently unused */ WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path, uint32 desired_access, const struct security_token *token, @@ -41,6 +39,11 @@ WERROR reg_create_path(TALLOC_CTX *mem_ctx, const char *orig_path, struct registry_key **pkey); WERROR reg_delete_path(const struct security_token *token, const char *orig_path); -#endif + +struct registry_value *registry_value_dw(TALLOC_CTX *mem_ctx, uint32_t dw); +struct registry_value *registry_value_sz(TALLOC_CTX *mem_ctx, const char *str); +struct registry_value *registry_value_multi_sz(TALLOC_CTX *mem_ctx, const char **str); + +int registry_value_cmp(const struct registry_value *v1, const struct registry_value *v2); #endif /* _REG_API_UTIL_H */ diff --git a/source3/registry/reg_import.c b/source3/registry/reg_import.c index ce3cd97..5f99b07 100644 --- a/source3/registry/reg_import.c +++ b/source3/registry/reg_import.c @@ -75,6 +75,7 @@ int reg_parse_callback_key(struct reg_import* p, if (p->open_key != NULL ) { werr = p->call.closekey(p->call.data, p->open_key); + p->open_key = NULL; if (!W_ERROR_IS_OK(werr)) { DEBUG(0, ("closekey failed: %s\n", win_errstr(werr))); } diff --git a/source3/registry/reg_parse.c b/source3/registry/reg_parse.c index 5a22fd7..babf5c0 100644 --- a/source3/registry/reg_parse.c +++ b/source3/registry/reg_parse.c @@ -934,7 +934,8 @@ int reg_parse_file(const char* fname, const struct reg_parse_callback* cb, fd = open(fname, O_RDONLY); if (fd < 0) { - DEBUG(0, ("reg_parse_file: open failed: %s\n", strerror(errno))); + DEBUG(0, ("reg_parse_file: open %s failed: %s\n", fname, + strerror(errno))); return -1; } diff --git a/source3/utils/net.c b/source3/utils/net.c index 1ce5ee6..eccb522 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 5b9db10..2056d89 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 eb7d19a..0993b95 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" @@ -123,16 +124,17 @@ done: return werr; } -static WERROR registry_enumkey(struct registry_key* parent, const char* keyname, bool recursive) +static WERROR registry_enumkey(struct registry_key *parent, const char *keyname, + bool recursive) { WERROR werr; TALLOC_CTX *ctx = talloc_stackframe(); - char* subkey_name; + char *subkey_name; NTTIME modtime; uint32_t count; - char* valname = NULL; + char *valname = NULL; struct registry_value *valvalue = NULL; - struct registry_key* key = NULL; + struct registry_key *key = NULL; werr = reg_openkey(ctx, parent, keyname, REG_KEY_READ, &key); if (!W_ERROR_IS_OK(werr)) { @@ -203,7 +205,7 @@ static int net_registry_enumerate(struct net_context *c, int argc, { WERROR werr; struct registry_key *key = NULL; - char* name = NULL; + char *name = NULL; TALLOC_CTX *ctx = talloc_stackframe(); int ret = -1; @@ -237,7 +239,7 @@ static int net_registry_enumerate_recursive(struct net_context *c, int argc, { WERROR werr; struct registry_key *key = NULL; - char* name = NULL; + char *name = NULL; TALLOC_CTX *ctx = talloc_stackframe(); int ret = -1; @@ -909,18 +911,18 @@ struct import_ctx { }; -static WERROR import_create_key(struct import_ctx* ctx, - struct registry_key* parent, - const char* name, void** pkey, bool* existing) +static WERROR import_create_key(struct import_ctx *ctx, + struct registry_key *parent, + const char *name, void **pkey, bool *existing) { WERROR werr; - void* mem_ctx = talloc_new(ctx->mem_ctx); + TALLOC_CTX *mem_ctx = talloc_new(ctx->mem_ctx); - struct registry_key* key = NULL; + struct registry_key *key = NULL; enum winreg_CreateAction action; if (parent == NULL) { - char* subkeyname = NULL; + char *subkeyname = NULL; werr = open_hive(mem_ctx, name, REG_KEY_WRITE, &parent, &subkeyname); if (!W_ERROR_IS_OK(werr)) { @@ -959,20 +961,20 @@ done: return werr; } -static WERROR import_close_key(struct import_ctx* ctx, - struct registry_key* key) +static WERROR import_close_key(struct import_ctx *ctx, + struct registry_key *key) { return WERR_OK; } -static WERROR import_delete_key(struct import_ctx* ctx, - struct registry_key* parent, const char* name) +static WERROR import_delete_key(struct import_ctx *ctx, + struct registry_key *parent, const char *name) { WERROR werr; - void* mem_ctx = talloc_new(talloc_tos()); + TALLOC_CTX *mem_ctx = talloc_new(talloc_tos()); if (parent == NULL) { - char* subkeyname = NULL; + char *subkeyname = NULL; werr = open_hive(mem_ctx, name, REG_KEY_WRITE, &parent, &subkeyname); if (!W_ERROR_IS_OK(werr)) { @@ -985,8 +987,8 @@ static WERROR import_delete_key(struct import_ctx* ctx, werr = reg_deletekey_recursive(parent, name); if (!W_ERROR_IS_OK(werr)) { - d_fprintf(stderr, "reg_deletekey_recursive %s: %s\n", _("failed"), - win_errstr(werr)); + d_fprintf(stderr, "reg_deletekey_recursive %s: %s\n", + _("failed"), win_errstr(werr)); goto done; } @@ -995,9 +997,9 @@ done: return werr; } -static WERROR import_create_val (struct import_ctx* ctx, - struct registry_key* parent, const char* name, - const struct registry_value* value) +static WERROR import_create_val (struct import_ctx *ctx, + struct registry_key *parent, const char *name, + const struct registry_value *value) { WERROR werr; @@ -1013,7 +1015,9 @@ static WERROR import_create_val (struct import_ctx* ctx, return werr; } -static WERROR import_delete_val (struct import_ctx* ctx, struct registry_key* parent, const char* name) { +static WERROR import_delete_val (struct import_ctx *ctx, + struct registry_key *parent, const char *name) +{ WERROR werr; if (parent == NULL) { @@ -1029,11 +1033,200 @@ 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 int net_registry_import(struct net_context *c, int argc, - const char **argv) +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) { - struct import_ctx import_ctx; + 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) +{ -- Samba Shared Repository