diff --git a/source/include/registry.h b/source/include/registry.h index 5865636836d..e2f8bc087a3 100644 --- a/source/include/registry.h +++ b/source/include/registry.h @@ -131,11 +131,11 @@ struct hive_operations { /* Key management */ WERROR (*add_key)(TALLOC_CTX *, struct registry_key *, const char *name, uint32_t access_mask, SEC_DESC *, struct registry_key **); - WERROR (*del_key)(struct registry_key *); + WERROR (*del_key)(struct registry_key *, const char *name); WERROR (*flush_key) (struct registry_key *); /* Value management */ - WERROR (*set_value)(struct registry_key *, const char *name, int type, void *data, int len); + WERROR (*set_value)(struct registry_key *, const char *name, uint32 type, void *data, int len); WERROR (*del_value)(struct registry_key *, const char *valname); }; diff --git a/source/lib/registry/common/reg_interface.c b/source/lib/registry/common/reg_interface.c index 79bb0b765cb..c729945a262 100644 --- a/source/lib/registry/common/reg_interface.c +++ b/source/lib/registry/common/reg_interface.c @@ -192,28 +192,6 @@ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *lo return WERR_OK; } -/* Open a key by name (including the predefined key name!) */ -WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) -{ - struct registry_key *predef; - WERROR error; - int predeflength; - char *predefname; - - if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name; - else predeflength = strlen(name); - - predefname = strndup(name, predeflength); - error = reg_get_predefined_key_by_name(handle, predefname, &predef); - SAFE_FREE(predefname); - - if(!W_ERROR_IS_OK(error)) { - return error; - } - - return reg_open_key(mem_ctx, predef, name, result); -} - /* Open a key * First tries to use the open_key function from the backend * then falls back to get_subkey_by_name and later get_subkey_by_index @@ -409,123 +387,21 @@ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, struct registry_key *key, return WERR_OK; } -WERROR reg_key_del(struct registry_key *key) +WERROR reg_key_del(struct registry_key *parent, const char *name) { WERROR error; - if(!key) return WERR_INVALID_PARAM; + if(!parent) return WERR_INVALID_PARAM; - if(!key->hive->functions->del_key) + if(!parent->hive->functions->del_key) return WERR_NOT_SUPPORTED; - error = key->hive->functions->del_key(key); + error = parent->hive->functions->del_key(parent, name); if(!W_ERROR_IS_OK(error)) return error; return WERR_OK; } -WERROR reg_key_del_recursive(struct registry_key *key) -{ - WERROR error = WERR_OK; - int i; - - TALLOC_CTX *mem_ctx = talloc_init("del_recursive"); - - /* Delete all values for specified key */ - for(i = 0; W_ERROR_IS_OK(error); i++) { - struct registry_value *val; - error = reg_key_get_value_by_index(mem_ctx, key, i, &val); - if(!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) - { - talloc_destroy(mem_ctx); - return error; - } - - if(W_ERROR_IS_OK(error)) { - error = reg_del_value(key, val->name); - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } - } - } - - error = WERR_OK; - - /* Delete all keys below this one */ - for(i = 0; W_ERROR_IS_OK(error); i++) { - struct registry_key *subkey; - - error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey); - if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } - - error = reg_key_del_recursive(subkey); - if(!W_ERROR_IS_OK(error)) { talloc_destroy(mem_ctx); return error; } - } - - talloc_destroy(mem_ctx); - return reg_key_del(key); -} - -WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const char *name) -{ - struct registry_key *hive; - WERROR error; - int hivelength; - char *hivename; - - if(strchr(name, '\\')) hivelength = strchr(name, '\\')-name; - else hivelength = strlen(name); - - hivename = strndup(name, hivelength); - error = reg_get_predefined_key_by_name(handle, hivename, &hive); - SAFE_FREE(hivename); - - if(!W_ERROR_IS_OK(error)) return error; - - return reg_key_add_name_recursive(hive, name); -} - -WERROR reg_key_add_name_recursive(struct registry_key *parent, const char *path) -{ - struct registry_key *cur, *prevcur = parent; - WERROR error = WERR_OK; - char *dups, *begin, *end; - TALLOC_CTX *mem_ctx = talloc_init("add_recursive"); - - begin = dups = strdup(path); - - while(1) { - end = strchr(begin, '\\'); - if(end) *end = '\0'; - - error = reg_key_get_subkey_by_name(mem_ctx, prevcur, begin, &cur); - - /* Key is not there, add it */ - if(W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - error = reg_key_add_name(mem_ctx, prevcur, begin, 0, NULL, &cur); - if(!W_ERROR_IS_OK(error)) break; - } - - if(!W_ERROR_IS_OK(error)) { - if(end) *end = '\\'; - break; - } - - if(!end) { - error = WERR_OK; - break; - } - - *end = '\\'; - begin = end+1; - prevcur = cur; - } - SAFE_FREE(dups); - talloc_destroy(mem_ctx); - return error; -} - WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, uint32_t access_mask, SEC_DESC *desc, struct registry_key **newkey) { WERROR error; @@ -547,7 +423,7 @@ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, struct registry_key *parent, const return WERR_OK; } -WERROR reg_val_set(struct registry_key *key, const char *value, int type, void *data, int len) +WERROR reg_val_set(struct registry_key *key, const char *value, uint32 type, void *data, int len) { /* A 'real' set function has preference */ if (key->hive->functions->set_value) @@ -577,27 +453,6 @@ WERROR reg_save (struct registry_context *ctx, const char *location) return WERR_NOT_SUPPORTED; } -WERROR reg_key_get_parent(TALLOC_CTX *mem_ctx, struct registry_key *key, struct registry_key **parent) -{ - char *parent_name; - char *last; - struct registry_key *root = NULL; - WERROR error; - - parent_name = strdup(key->path); - last = strrchr(parent_name, '\\'); - - if(!last) { - SAFE_FREE(parent_name); - return WERR_FOOBAR; - } - *last = '\0'; - - error = reg_open_key(mem_ctx, root, parent_name, parent); - SAFE_FREE(parent_name); - return error; -} - WERROR reg_key_flush(struct registry_key *key) { if (!key) { diff --git a/source/lib/registry/common/reg_util.c b/source/lib/registry/common/reg_util.c index 052ccc347be..1d1f7703245 100644 --- a/source/lib/registry/common/reg_util.c +++ b/source/lib/registry/common/reg_util.c @@ -150,3 +150,90 @@ char *reg_path_unix2win(char *path) } return path; } + +/* Open a key by name (including the predefined key name!) */ +WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, const char *name, struct registry_key **result) +{ + struct registry_key *predef; + WERROR error; + int predeflength; + char *predefname; + + if(strchr(name, '\\')) predeflength = strchr(name, '\\')-name; + else predeflength = strlen(name); + + predefname = strndup(name, predeflength); + error = reg_get_predefined_key_by_name(handle, predefname, &predef); + SAFE_FREE(predefname); + + if(!W_ERROR_IS_OK(error)) { + return error; + } + + if (strchr(name, '\\')) { + return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1, result); + } else { + *result = predef; + return WERR_OK; + } +} + +static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, struct registry_key **parent, const char **name) +{ + char *parent_name; + WERROR error; + + if (strchr(path, '\\') == NULL) { + return WERR_FOOBAR; + } + + parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-1-path); + + error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent); + if (!W_ERROR_IS_OK(error)) { + return error; + } + + *name = talloc_strdup(mem_ctx, strchr(path, '\\')+1); + + return WERR_OK; +} + +WERROR reg_key_del_abs(struct registry_context *ctx, const char *path) +{ + struct registry_key *parent; + const char *n; + TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs"); + WERROR error; + + if (!strchr(path, '\\')) { + return WERR_FOOBAR; + } + + error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); + if (W_ERROR_IS_OK(error)) { + error = reg_key_del(parent, n); + } + + talloc_destroy(mem_ctx); + + return error; +} + +WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32 access_mask, SEC_DESC *sec_desc, struct registry_key **result) +{ + struct registry_key *parent; + const char *n; + WERROR error; + + if (!strchr(path, '\\')) { + return WERR_FOOBAR; + } + + error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); + if (W_ERROR_IS_OK(error)) { + error = reg_key_add_name(mem_ctx, parent, n, access_mask, sec_desc, result); + } + + return error; +} diff --git a/source/lib/registry/reg_backend_dir.c b/source/lib/registry/reg_backend_dir.c index 89f92805854..41a0da58c01 100644 --- a/source/lib/registry/reg_backend_dir.c +++ b/source/lib/registry/reg_backend_dir.c @@ -34,9 +34,16 @@ static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, return WERR_INVALID_PARAM; } -static WERROR reg_dir_del_key(struct registry_key *k) +static WERROR reg_dir_del_key(struct registry_key *k, const char *name) { - return (rmdir((char *)k->backend_data) == 0)?WERR_OK:WERR_GENERAL_FAILURE; + char *child = talloc_asprintf(NULL, "%s/%s", (char *)k->backend_data, name); + WERROR ret; + + if (rmdir(child) == 0) ret = WERR_OK; else ret = WERR_GENERAL_FAILURE; + + talloc_destroy(child); + + return ret; } static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, struct registry_key *p, const char *name, struct registry_key **subkey) diff --git a/source/lib/registry/reg_backend_ldb.c b/source/lib/registry/reg_backend_ldb.c index ec8a6d9de3a..7a63f4a5304 100644 --- a/source/lib/registry/reg_backend_ldb.c +++ b/source/lib/registry/reg_backend_ldb.c @@ -235,12 +235,15 @@ static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, struct registry_key *parent, con return WERR_OK; } -static WERROR ldb_del_key (struct registry_key *key) +static WERROR ldb_del_key (struct registry_key *key, const char *child) { int ret; struct ldb_key_data *kd = key->backend_data; + char *childdn = talloc_asprintf(NULL, "key=%s,%s", child, kd->dn); - ret = ldb_delete(key->hive->backend_data, kd->dn); + ret = ldb_delete(key->hive->backend_data, childdn); + + talloc_destroy(childdn); if (ret < 0) { DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(key->hive->backend_data))); @@ -250,6 +253,59 @@ static WERROR ldb_del_key (struct registry_key *key) return WERR_OK; } +static WERROR ldb_del_value (struct registry_key *key, const char *child) +{ + int ret; + struct ldb_key_data *kd = key->backend_data; + char *childdn = talloc_asprintf(NULL, "value=%s,%s", child, kd->dn); + + ret = ldb_delete(key->hive->backend_data, childdn); + + talloc_destroy(childdn); + + if (ret < 0) { + DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(key->hive->backend_data))); + return WERR_FOOBAR; + } + + return WERR_OK; +} + +static WERROR ldb_set_value (struct registry_key *parent, const char *name, uint32 type, void *data, int len) +{ + struct ldb_context *ctx = parent->hive->backend_data; + struct ldb_message msg; + struct ldb_val val; + int ret; + char *type_s; + TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value"); + + ZERO_STRUCT(msg); + + msg.dn = reg_path_to_ldb(mem_ctx, parent->path, talloc_asprintf(mem_ctx, "value=%s,", name)); + + ldb_msg_add_string(ctx, &msg, "value", talloc_strdup(mem_ctx, name)); + val.length = len; + val.data = data; + ldb_msg_add_value(ctx, &msg, "data", &val); + + type_s = talloc_asprintf(mem_ctx, "%u", type); + ldb_msg_add_string(ctx, &msg, "type", type_s); + + ret = ldb_add(ctx, &msg); + if (ret < 0) { + ret = ldb_modify(ctx, &msg); + if (ret < 0) { + DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(parent->hive->backend_data))); + talloc_destroy(mem_ctx); + return WERR_FOOBAR; + } + } + + talloc_destroy(mem_ctx); + return WERR_OK; +} + static struct hive_operations reg_backend_ldb = { .name = "ldb", .add_key = ldb_add_key, @@ -258,6 +314,8 @@ static struct hive_operations reg_backend_ldb = { .open_key = ldb_open_key, .get_value_by_index = ldb_get_value_by_id, .get_subkey_by_index = ldb_get_subkey_by_id, + .set_value = ldb_set_value, + .del_value = ldb_del_value, }; NTSTATUS registry_ldb_init(void) diff --git a/source/lib/registry/reg_backend_rpc.c b/source/lib/registry/reg_backend_rpc.c index b14b67d609c..224a061762d 100644 --- a/source/lib/registry/reg_backend_rpc.c +++ b/source/lib/registry/reg_backend_rpc.c @@ -315,27 +315,17 @@ static WERROR rpc_query_key(struct registry_key *k) return r.out.result; } -static WERROR rpc_del_key(struct registry_key *k) +static WERROR rpc_del_key(struct registry_key *parent, const char *name) { NTSTATUS status; - struct rpc_key_data *mykeydata = k->backend_data; + struct rpc_key_data *mykeydata = parent->backend_data; struct winreg_DeleteKey r; - struct registry_key *parent; - WERROR error; TALLOC_CTX *mem_ctx = talloc_init("del_key"); - error = reg_key_get_parent(mem_ctx, k, &parent); - if(!W_ERROR_IS_OK(error)) { - talloc_destroy(mem_ctx); - return error; - } - - mykeydata = parent->backend_data; - r.in.handle = &mykeydata->pol; - init_winreg_String(&r.in.key, k->name); + init_winreg_String(&r.in.key, name); - status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r); + status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r); talloc_destroy(mem_ctx); diff --git a/source/lib/registry/tools/regpatch.c b/source/lib/registry/tools/regpatch.c index 18589a9285e..600c1f60e7c 100644 --- a/source/lib/registry/tools/regpatch.c +++ b/source/lib/registry/tools/regpatch.c @@ -686,13 +686,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd /* If we found it, apply the other bits, else create such a key */ if (W_ERROR_EQUAL(error, WERR_DEST_NOT_FOUND)) { - if(W_ERROR_IS_OK(reg_key_add_name_recursive_abs(r, cmd->key))) { - error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error finding new key '%s' after it has been added\n", cmd->key)); - continue; - } - } else { + if(!W_ERROR_IS_OK(reg_key_add_abs(mem_ctx, r, cmd->key, 0, NULL, &tmp))) { DEBUG(0, ("Error adding new key '%s'\n", cmd->key)); continue; } @@ -730,13 +724,7 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd * Find the key if it exists, and delete it ... */ - error = reg_open_key_abs(mem_ctx, r, cmd->key, &tmp); - if(!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Unable to open key '%s'\n", cmd->key)); - continue; - } - - error = reg_key_del_recursive(tmp); + error = reg_key_del_abs(r, cmd->key); if(!W_ERROR_IS_OK(error)) { DEBUG(0, ("Unable to delete key '%s'\n", cmd->key)); continue; diff --git a/source/lib/registry/tools/regshell.c b/source/lib/registry/tools/regshell.c index 0a097088699..6de8b25c9cf 100644 --- a/source/lib/registry/tools/regshell.c +++ b/source/lib/registry/tools/regshell.c @@ -120,18 +120,12 @@ static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key * static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - struct registry_key *key; if(argc < 2) { fprintf(stderr, "Usage: rmkey \n"); return NULL; } - if(!W_ERROR_IS_OK(reg_open_key(mem_ctx, cur, argv[1], &key))) { - fprintf(stderr, "No such subkey '%s'\n", argv[1]); - return NULL; - } - - if(!W_ERROR_IS_OK(reg_key_del(key))) { + if(!W_ERROR_IS_OK(reg_key_del(cur, argv[1]))) { fprintf(stderr, "Error deleting '%s'\n", argv[1]); } else { fprintf(stderr, "Successfully deleted '%s'\n", argv[1]); @@ -259,9 +253,10 @@ static char **reg_complete_command(const char *text, int end) return matches; cleanup: - while (i >= 0) { - free(matches[i]); - i--; + count--; + while (count >= 0) { + free(matches[count]); + count--; } free(matches); return NULL; diff --git a/source/rpc_server/winreg/rpc_winreg.c b/source/rpc_server/winreg/rpc_winreg.c index e8d4056b2a2..b34ccfa4b9e 100644 --- a/source/rpc_server/winreg/rpc_winreg.c +++ b/source/rpc_server/winreg/rpc_winreg.c @@ -126,16 +126,13 @@ static WERROR winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *m struct winreg_DeleteKey *r) { struct dcesrv_handle *h; - struct registry_key *key; WERROR result; h = dcesrv_handle_fetch(dce_call->conn, r->in.handle, HTYPE_REGKEY); DCESRV_CHECK_HANDLE(h); - result = reg_open_key(mem_ctx, (struct registry_key *)h->data, r->in.key.name, &key); - if (W_ERROR_IS_OK(result)) { - return reg_key_del(key); + return reg_key_del((struct registry_key *)h->data, r->in.key.name); } return result;