diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2004-12-10 20:07:04 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:06:29 -0500 |
commit | 444a86792471c0bef33dde15c7a4a33e16a951b4 (patch) | |
tree | 075b0cdd27acb80470a4e90e99598cbcea3b082c | |
parent | 60c69445f6fa86b27bd697cc8af52b582f620725 (diff) | |
download | samba-444a86792471c0bef33dde15c7a4a33e16a951b4.tar.gz samba-444a86792471c0bef33dde15c7a4a33e16a951b4.tar.bz2 samba-444a86792471c0bef33dde15c7a4a33e16a951b4.zip |
r4132: - Bunch of rather large fixes in the registry
- Added some README files
Not everything works yet, e.g. the EnumValue test appears to be broken.
(This used to be commit c169e86c1f52763b83e77e509f89cb91f9b69071)
-rw-r--r-- | source4/gtk/tools/gregedit.c | 98 | ||||
-rw-r--r-- | source4/include/credentials.h | 36 | ||||
-rw-r--r-- | source4/include/registry.h | 49 | ||||
-rw-r--r-- | source4/lib/registry/README | 30 | ||||
-rw-r--r-- | source4/lib/registry/common/reg_interface.c | 182 | ||||
-rw-r--r-- | source4/lib/registry/config.mk | 17 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_dir.c (renamed from source4/lib/registry/reg_backend_dir/reg_backend_dir.c) | 8 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_gconf.c (renamed from source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c) | 12 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_ldb.c (renamed from source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c) | 8 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_nt4.c (renamed from source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c) | 10 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_rpc.c (renamed from source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c) | 141 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_w95.c (renamed from source4/lib/registry/reg_backend_w95/reg_backend_w95.c) | 12 | ||||
-rw-r--r-- | source4/lib/registry/reg_backend_wine.c (renamed from source4/lib/registry/reg_backend_wine/reg_backend_wine.c) | 15 | ||||
-rw-r--r-- | source4/lib/registry/reg_samba.c | 62 | ||||
-rw-r--r-- | source4/lib/registry/tools/regdiff.c | 76 | ||||
-rw-r--r-- | source4/lib/registry/tools/regpatch.c | 25 | ||||
-rw-r--r-- | source4/lib/registry/tools/regshell.c | 87 | ||||
-rw-r--r-- | source4/lib/registry/tools/regtree.c | 38 | ||||
-rw-r--r-- | source4/rpc_server/winreg/README | 3 | ||||
-rw-r--r-- | source4/rpc_server/winreg/rpc_winreg.c | 58 | ||||
-rw-r--r-- | source4/torture/rpc/winreg.c | 1 |
21 files changed, 551 insertions, 417 deletions
diff --git a/source4/gtk/tools/gregedit.c b/source4/gtk/tools/gregedit.c index 31df3086f2..6301910a48 100644 --- a/source4/gtk/tools/gregedit.c +++ b/source4/gtk/tools/gregedit.c @@ -62,6 +62,7 @@ static GtkWidget* create_FindDialog (void) FindDialog = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (FindDialog), "Find Key or Value"); + gtk_window_set_resizable (GTK_WINDOW (FindDialog), FALSE); gtk_window_set_type_hint (GTK_WINDOW (FindDialog), GDK_WINDOW_TYPE_HINT_DIALOG); dialog_vbox2 = GTK_DIALOG (FindDialog)->vbox; @@ -135,7 +136,6 @@ static GtkWidget* create_SetValueDialog (void) SetValueDialog = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (SetValueDialog), "Set Registry Value"); - GTK_WINDOW (SetValueDialog)->type = GTK_WINDOW_POPUP; gtk_window_set_position (GTK_WINDOW (SetValueDialog), GTK_WIN_POS_CENTER); gtk_window_set_resizable (GTK_WINDOW (SetValueDialog), FALSE); gtk_window_set_type_hint (GTK_WINDOW (SetValueDialog), GDK_WINDOW_TYPE_HINT_DIALOG); @@ -207,7 +207,6 @@ static GtkWidget* create_NewKeyDialog (void) NewKeyDialog = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (NewKeyDialog), "New Registry Key"); - GTK_WINDOW (NewKeyDialog)->type = GTK_WINDOW_POPUP; gtk_window_set_position (GTK_WINDOW (NewKeyDialog), GTK_WIN_POS_CENTER); gtk_window_set_resizable (GTK_WINDOW (NewKeyDialog), FALSE); gtk_window_set_type_hint (GTK_WINDOW (NewKeyDialog), GDK_WINDOW_TYPE_HINT_DIALOG); @@ -287,45 +286,51 @@ static void expand_key(GtkTreeView *treeview, GtkTreeIter *parent, GtkTreePath * if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) gtk_show_werror(mainwin, error); } +static void registry_load_hive(struct registry_key *root) +{ + GtkTreeIter iter, tmpiter; + /* Add the root */ + gtk_tree_store_append(store_keys, &iter, NULL); + gtk_tree_store_set (store_keys, + &iter, + 0, + root->name?root->name:"", + 1, + root, + -1); + + gtk_tree_store_append(store_keys, &tmpiter, &iter); + + gtk_widget_set_sensitive( save, True ); + gtk_widget_set_sensitive( save_as, True ); +} + static void registry_load_root(void) { struct registry_key *root; - GtkTreeIter iter, tmpiter; - int i = 0; + uint32_t i = 0; if(!registry) return; gtk_tree_store_clear(store_keys); - for(i = 0; i < registry->num_hives; i++) + for(i = HKEY_CLASSES_ROOT; i <= HKEY_PN; i++) { - root = registry->hives[i]->root; + if (!W_ERROR_IS_OK(reg_get_hive(registry, i, &root))) { continue; } - /* Add the root */ - gtk_tree_store_append(store_keys, &iter, NULL); - gtk_tree_store_set (store_keys, - &iter, - 0, - root->hive->name?root->hive->name:"", - 1, - root, - -1); - - gtk_tree_store_append(store_keys, &tmpiter, &iter); + registry_load_hive(root); } - - gtk_widget_set_sensitive( save, True ); - gtk_widget_set_sensitive( save_as, True ); } static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) { gint result = gtk_dialog_run(GTK_DIALOG(create_openfilewin())); char *filename, *tmp; + struct registry_key *root; WERROR error; switch(result) { case GTK_RESPONSE_OK: filename = strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(openfilewin))); - error = reg_open(®istry, user_data, filename, NULL); + error = reg_open_hive(NULL, user_data, filename, NULL, &root); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(mainwin, error); break; @@ -334,7 +339,8 @@ static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) tmp = g_strdup_printf("Registry Editor - %s", filename); gtk_window_set_title (GTK_WINDOW (mainwin), tmp); g_free(tmp); - registry_load_root(); + gtk_tree_store_clear(store_keys); + registry_load_hive(root); break; default: break; @@ -346,7 +352,8 @@ static void on_open_file_activate (GtkMenuItem *menuitem, gpointer user_data) static void on_open_gconf_activate (GtkMenuItem *menuitem, gpointer user_data) { - WERROR error = reg_open(®istry, "gconf", NULL, NULL); + struct registry_key *root; + WERROR error = reg_open_hive(NULL, "gconf", NULL, NULL, &root); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(mainwin, error); return; @@ -354,13 +361,12 @@ static void on_open_gconf_activate (GtkMenuItem *menui gtk_window_set_title (GTK_WINDOW (mainwin), "Registry Editor - GConf"); - registry_load_root(); + gtk_tree_store_clear(store_keys); + registry_load_hive(root); } static void on_open_remote_activate(GtkMenuItem *menuitem, gpointer user_data) { - char *credentials; - const char *location; char *tmp; GtkWidget *rpcwin = GTK_WIDGET(gtk_rpc_binding_dialog_new(FALSE, NULL)); gint result = gtk_dialog_run(GTK_DIALOG(rpcwin)); @@ -372,16 +378,16 @@ static void on_open_remote_activate(GtkMenuItem *menuitem, gpointer user_data) return; } - location = gtk_rpc_binding_dialog_get_binding_string(GTK_RPC_BINDING_DIALOG(rpcwin), mem_ctx); - asprintf(&credentials, "%s%%%s", gtk_rpc_binding_dialog_get_username(GTK_RPC_BINDING_DIALOG(rpcwin)), gtk_rpc_binding_dialog_get_password(GTK_RPC_BINDING_DIALOG(rpcwin))); - error = reg_open(®istry, "rpc", location, credentials); + error = reg_open_remote(®istry, + gtk_rpc_binding_dialog_get_username(GTK_RPC_BINDING_DIALOG(rpcwin)), + gtk_rpc_binding_dialog_get_password(GTK_RPC_BINDING_DIALOG(rpcwin)), + gtk_rpc_binding_dialog_get_binding_string(GTK_RPC_BINDING_DIALOG(rpcwin), mem_ctx)); if(!W_ERROR_IS_OK(error)) { gtk_show_werror(mainwin, error); gtk_widget_destroy(rpcwin); return; } - free(credentials); tmp = g_strdup_printf("Registry Editor - Remote Registry at %s", gtk_rpc_binding_dialog_get_host(GTK_RPC_BINDING_DIALOG(rpcwin))); gtk_window_set_title (GTK_WINDOW (mainwin), tmp); @@ -805,14 +811,10 @@ static GtkWidget* create_savefilewin (void) int main(int argc, char *argv[]) { poptContext pc; - const char *backend = NULL; - const char *credentials = NULL; - const char *location; + WERROR error; int opt; struct poptOption long_options[] = { POPT_AUTOHELP - {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%%password)", NULL}, POPT_TABLEEND }; @@ -829,32 +831,18 @@ static GtkWidget* create_savefilewin (void) while((opt = poptGetNextOpt(pc)) != -1) { } - location = poptGetArg(pc); - - if(location) { - WERROR error; - - if(!backend) { - if(credentials)backend = "rpc"; - else backend = "nt4"; - } - - error = reg_open(®istry, backend, location, credentials); - if(!W_ERROR_IS_OK(error)) { - gtk_show_werror(mainwin, error); - return -1; - } - mainwin = create_mainwin (); - registry_load_root(); - } else { - mainwin = create_mainwin (); + error = reg_open_local(®istry); + if(!W_ERROR_IS_OK(error)) { + gtk_show_werror(mainwin, error); + return -1; } + mainwin = create_mainwin (); + registry_load_root(); gtk_widget_show_all (mainwin); gtk_main (); - if(registry)talloc_destroy(registry->mem_ctx); talloc_destroy(mem_ctx); return 0; } diff --git a/source4/include/credentials.h b/source4/include/credentials.h new file mode 100644 index 0000000000..99173ab421 --- /dev/null +++ b/source4/include/credentials.h @@ -0,0 +1,36 @@ +/* + samba -- Unix SMB/CIFS implementation. + + Client credentials structure + + Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org> + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct cli_credentials { + /* Preferred methods, NULL means default */ + const char **preferred_methods; + + const char *username; + const char *password; + const char *domain; + const char *realm; + + const char *(*username_cb) (void); + const char *(*password_cb) (void); + const char *(*domain_cb) (void); + const char *(*realm_cb) (void); +}; diff --git a/source4/include/registry.h b/source4/include/registry.h index a099ae1e0f..4ce9569376 100644 --- a/source4/include/registry.h +++ b/source4/include/registry.h @@ -22,26 +22,36 @@ #ifndef _REGISTRY_H /* _REGISTRY_H */ #define _REGISTRY_H -#define HKEY_CLASSES_ROOT 0x80000000 -#define HKEY_CURRENT_USER 0x80000001 -#define HKEY_LOCAL_MACHINE 0x80000002 -#define HKEY_USERS 0x80000003 + +enum hkeys { + HKEY_CLASSES_ROOT = 0x80000000, + HKEY_CURRENT_USER = 0x80000001, + HKEY_LOCAL_MACHINE = 0x80000002, + HKEY_USERS = 0x80000003, + HKEY_PERFORMANCE_DATA = 0x80000004, + HKEY_CURRENT_CONFIG = 0x80000005, + HKEY_DYN_DATA = 0x80000006, + HKEY_PT = 0x80000007, /* Don't know if this is correct! */ + HKEY_PN = 0x80000008 /* Don't know if this is correct! */ +}; /* Registry data types */ -#define REG_DELETE -1 +#define REG_DELETE -1 #define REG_NONE 0 #define REG_SZ 1 #define REG_EXPAND_SZ 2 #define REG_BINARY 3 -#define REG_DWORD 4 -#define REG_DWORD_LE 4 /* DWORD, little endian*/ -#define REG_DWORD_BE 5 /* DWORD, big endian */ +#define REG_DWORD_LE 4 +#define REG_DWORD REG_DWORD_LE +#define REG_DWORD_BE 5 #define REG_LINK 6 #define REG_MULTI_SZ 7 #define REG_RESOURCE_LIST 8 #define REG_FULL_RESOURCE_DESCRIPTOR 9 #define REG_RESOURCE_REQUIREMENTS_LIST 10 +#define REG_QWORD_LE 11 +#define REG_QWORD REQ_QWORD_LE #if 0 /* FIXME */ @@ -62,7 +72,7 @@ typedef struct ace_struct_s { /* structure to store the registry handles */ struct registry_key { char *name; /* Name of the key */ - char *path; /* Full path to the key */ + const char *path; /* Full path to the key */ char *class_name; /* Name of key class */ NTTIME last_mod; /* Time last modified */ SEC_DESC *security; @@ -92,18 +102,15 @@ typedef void (*value_notification_function) (void); * * Backends can provide : * - just one hive (example: nt4, w95) - * - several hives (example: rpc) + * - several hives (example: rpc). * */ -struct registry_operations { +struct hive_operations { const char *name; - /* If one file, connection, etc may have more then one hive */ - WERROR (*list_available_hives) (TALLOC_CTX *, const char *location, const char *credentials, char ***hives); - /* Implement this one */ - WERROR (*open_hive) (TALLOC_CTX *, struct registry_hive *, struct registry_key **); + WERROR (*open_hive) (struct registry_hive *, struct registry_key **); WERROR (*close_hive) (struct registry_hive *); /* Or this one */ @@ -140,11 +147,8 @@ struct registry_operations { }; struct registry_hive { - const struct registry_operations *functions; - char *name; /* usually something like HKEY_CURRENT_USER, etc */ + const struct hive_operations *functions; char *location; - char *credentials; - char *backend_hivename; void *backend_data; struct registry_key *root; struct registry_context *reg_ctx; @@ -153,14 +157,13 @@ struct registry_hive { /* Handle to a full registry * contains zero or more hives */ struct registry_context { - TALLOC_CTX *mem_ctx; - int num_hives; - struct registry_hive **hives; + void *backend_data; + WERROR (*get_hive) (struct registry_context *, uint32 hkey, struct registry_key **); }; struct reg_init_function_entry { /* Function to create a member of the pdb_methods list */ - const struct registry_operations *functions; + const struct hive_operations *hive_functions; struct reg_init_function_entry *prev, *next; }; diff --git a/source4/lib/registry/README b/source4/lib/registry/README new file mode 100644 index 0000000000..757029cdc2 --- /dev/null +++ b/source4/lib/registry/README @@ -0,0 +1,30 @@ +This is the registry library. The registry is basically a bunch of hives +(HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, etc) that can be loaded from +different places. + +The various registry backends provide support for loading/saving specific types +of hives: + - ldb + - w95 (USER.DAT-style files) + - nt4 (NTUSER.DAT-style files) + - gconf (GNOME configuration) + - rpc (Remote individual hives) + +Instead of opening individual hives, one can also open a 'complete' registry by +using one of these three functions: + + - reg_open_local() - load local registry, see below + - reg_open_remote() - connect to remote registry over RPC + - reg_open_wine() (not working yet) + +reg_open_local() loads a set of hives based on smb.conf settings. +Lines in smb.conf should have the following syntax: + +registry:<hivename> = <backend>:<location> + +So an example usage could be: + +registry:HKEY_CURRENT_USER = nt4:NTUSER.DAT +registry:HKEY_LOCAL_MACHINE = ldb:tdb://registry.tdb + +WERR_NOT_SUPPORTED will be returned for all hives that haven't been set. diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c index f7d3af0705..740d849db1 100644 --- a/source4/lib/registry/common/reg_interface.c +++ b/source4/lib/registry/common/reg_interface.c @@ -30,32 +30,25 @@ static struct reg_init_function_entry *backends = NULL; static struct reg_init_function_entry *reg_find_backend_entry(const char *name); -#define reg_make_path(mem_ctx, parent, name) (((parent)->hive->root == (parent))?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)) - /* Register new backend */ -NTSTATUS registry_register(const void *_function) +NTSTATUS registry_register(const void *_hive_ops) { - const struct registry_operations *functions = _function; + const struct hive_operations *hive_ops = _hive_ops; struct reg_init_function_entry *entry = backends; - if (!functions || !functions->name) { - DEBUG(0, ("Invalid arguments while registering registry backend\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - DEBUG(5,("Attempting to register registry backend %s\n", functions->name)); + DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name)); /* Check for duplicates */ - if (reg_find_backend_entry(functions->name)) { - DEBUG(0,("There already is a registry backend registered with the name %s!\n", functions->name)); + if (reg_find_backend_entry(hive_ops->name)) { + DEBUG(0,("There already is a registry backend registered with the name %s!\n", hive_ops->name)); return NT_STATUS_OBJECT_NAME_COLLISION; } - entry = malloc_p(struct reg_init_function_entry); - entry->functions = functions; + entry = talloc_p(NULL, struct reg_init_function_entry); + entry->hive_functions = hive_ops; DLIST_ADD(backends, entry); - DEBUG(5,("Successfully added registry backend '%s'\n", functions->name)); + DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name)); return NT_STATUS_OK; } @@ -67,7 +60,7 @@ static struct reg_init_function_entry *reg_find_backend_entry(const char *name) entry = backends; while(entry) { - if (strcmp(entry->functions->name, name) == 0) return entry; + if (strcmp(entry->hive_functions->name, name) == 0) return entry; entry = entry->next; } @@ -80,85 +73,83 @@ BOOL reg_has_backend(const char *backend) return reg_find_backend_entry(backend) != NULL?True:False; } -WERROR reg_create(struct registry_context **_ret) +static struct { + uint32 hkey; + const char *name; +} hkey_names[] = { - TALLOC_CTX *mem_ctx; - struct registry_context *ret; - mem_ctx = talloc_init("registry handle"); - ret = talloc_p(mem_ctx, struct registry_context); - ret->mem_ctx = mem_ctx; - ZERO_STRUCTP(ret); - *_ret = ret; - return WERR_OK; -} - -WERROR reg_list_available_hives(TALLOC_CTX *mem_ctx, const char *backend, const char *location, const char *credentials, char ***hives) + {HKEY_CLASSES_ROOT,"HKEY_CLASSES_ROOT" }, + {HKEY_CURRENT_USER,"HKEY_CURRENT_USER" }, + {HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE" }, + {HKEY_PERFORMANCE_DATA, "HKEY_PERFORMANCE_DATA" }, + {HKEY_USERS, "HKEY_USERS" }, + {HKEY_CURRENT_CONFIG, "HKEY_CURRENT_CONFIG" }, + {HKEY_DYN_DATA, "HKEY_DYN_DATA" }, + {HKEY_PT, "HKEY_PT" }, + {HKEY_PN, "HKEY_PN" }, + { 0, NULL } +}; + +int reg_list_hives(TALLOC_CTX *mem_ctx, char ***hives, uint32_t **hkeys) { - struct reg_init_function_entry *entry; - - entry = reg_find_backend_entry(backend); - - if (!entry) { - DEBUG(0, ("No such registry backend '%s' loaded!\n", backend)); - return WERR_GENERAL_FAILURE; - } + int i; + *hives = talloc_array_p(mem_ctx, char *, ARRAY_SIZE(hkey_names)); + *hkeys = talloc_array_p(mem_ctx, uint32_t, ARRAY_SIZE(hkey_names)); - if(!entry->functions->list_available_hives) { - return WERR_NOT_SUPPORTED; + for (i = 0; hkey_names[i].name; i++) { + (*hives)[i] = talloc_strdup(mem_ctx, hkey_names[i].name); + (*hkeys)[i] = hkey_names[i].hkey; } - return entry->functions->list_available_hives(mem_ctx, location, credentials, hives); + return i; } -WERROR reg_open(struct registry_context **ret, const char *backend, const char *location, const char *credentials) +const char *reg_get_hkey_name(uint32_t hkey) { - WERROR error = reg_create(ret), reterror = WERR_NO_MORE_ITEMS; - char **hives; - int i, j; - TALLOC_CTX *mem_ctx = talloc_init("reg_open"); - - if(!W_ERROR_IS_OK(error)) return error; - - error = reg_list_available_hives(mem_ctx, backend, location, credentials, &hives); - - if(W_ERROR_EQUAL(error, WERR_NOT_SUPPORTED)) { - return reg_import_hive(*ret, backend, location, credentials, NULL); + int i; + for (i = 0; hkey_names[i].name; i++) { + if (hkey_names[i].hkey == hkey) return hkey_names[i].name; } - - if(!W_ERROR_IS_OK(error)) return error; - j = 0; - for(i = 0; hives[i]; i++) - { - error = reg_import_hive(*ret, backend, location, credentials, hives[i]); - if (W_ERROR_IS_OK(error)) { - reterror = WERR_OK; - (*ret)->hives[j]->name = talloc_strdup((*ret)->mem_ctx, hives[i]); - j++; - } else if (!W_ERROR_IS_OK(reterror)) reterror = error; + return NULL; +} + +WERROR reg_get_hive_by_name(struct registry_context *ctx, const char *name, struct registry_key **key) +{ + int i; + + for (i = 0; hkey_names[i].name; i++) { + if (!strcmp(hkey_names[i].name, name)) return reg_get_hive(ctx, hkey_names[i].hkey, key); } - return reterror; + DEBUG(1, ("No hive with name '%s'\n", name)); + + return WERR_BADFILE; } WERROR reg_close (struct registry_context *ctx) { - int i; - for (i = 0; i < ctx->num_hives; i++) { - if (ctx->hives[i]->functions->close_hive) { - ctx->hives[i]->functions->close_hive(ctx->hives[i]); - } - } talloc_destroy(ctx); return WERR_OK; } +WERROR reg_get_hive(struct registry_context *ctx, uint32_t hkey, struct registry_key **key) +{ + WERROR ret = ctx->get_hive(ctx, hkey, key); + + if (W_ERROR_IS_OK(ret)) { + (*key)->name = talloc_strdup(*key, reg_get_hkey_name(hkey)); + (*key)->path = ""; + } + + return ret; +} + /* Open a registry file/host/etc */ -WERROR reg_import_hive(struct registry_context *h, const char *backend, const char *location, const char *credentials, const char *hivename) +WERROR reg_open_hive(struct registry_context *parent_ctx, const char *backend, const char *location, const char *credentials, struct registry_key **root) { struct registry_hive *ret; - TALLOC_CTX *mem_ctx; struct reg_init_function_entry *entry; WERROR werr; @@ -169,24 +160,21 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch return WERR_GENERAL_FAILURE; } - if(!entry->functions->open_hive) { + if(!entry->hive_functions || !entry->hive_functions->open_hive) { return WERR_NOT_SUPPORTED; } - - mem_ctx = h->mem_ctx; - ret = talloc_p(mem_ctx, struct registry_hive); - ret->location = location?talloc_strdup(mem_ctx, location):NULL; - ret->backend_hivename = hivename?talloc_strdup(mem_ctx, hivename):NULL; - ret->credentials = credentials?talloc_strdup(mem_ctx, credentials):NULL; - ret->functions = entry->functions; + ret = talloc_p(parent_ctx, struct registry_hive); + ret->location = location?talloc_strdup(ret, location):NULL; + ret->functions = entry->hive_functions; ret->backend_data = NULL; - ret->reg_ctx = h; - ret->name = NULL; + ret->reg_ctx = parent_ctx; - werr = entry->functions->open_hive(mem_ctx, ret, &ret->root); + werr = entry->hive_functions->open_hive(ret, &ret->root); - if(!W_ERROR_IS_OK(werr)) return werr; + if(!W_ERROR_IS_OK(werr)) { + return werr; + } if(!ret->root) { DEBUG(0, ("Backend %s didn't provide root key!\n", backend)); @@ -195,12 +183,9 @@ WERROR reg_import_hive(struct registry_context *h, const char *backend, const ch ret->root->hive = ret; ret->root->name = NULL; - ret->root->path = talloc_strdup(mem_ctx, ""); - - /* Add hive to context */ - h->num_hives++; - h->hives = talloc_realloc_p(h, h->hives, struct registry_hive *, h->num_hives); - h->hives[h->num_hives-1] = ret; + ret->root->path = talloc_strdup(ret, ""); + + *root = ret->root; return WERR_OK; } @@ -217,7 +202,7 @@ WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, co else hivelength = strlen(name); hivename = strndup(name, hivelength); - error = reg_get_hive(handle, hivename, &hive); + error = reg_get_hive_by_name(handle, hivename, &hive); SAFE_FREE(hivename); if(!W_ERROR_IS_OK(error)) { @@ -272,7 +257,8 @@ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char return WERR_NOT_SUPPORTED; } - fullname = reg_make_path(mem_ctx, parent, name); + + fullname = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name)); error = parent->hive->functions->open_key(mem_ctx, parent->hive, fullname, result); @@ -499,7 +485,7 @@ WERROR reg_key_add_name_recursive_abs(struct registry_context *handle, const cha else hivelength = strlen(name); hivename = strndup(name, hivelength); - error = reg_get_hive(handle, hivename, &hive); + error = reg_get_hive_by_name(handle, hivename, &hive); SAFE_FREE(hivename); if(!W_ERROR_IS_OK(error)) return error; @@ -578,19 +564,7 @@ WERROR reg_val_set(struct registry_key *key, const char *value, int type, void * return WERR_NOT_SUPPORTED; } -WERROR reg_get_hive(struct registry_context *h, const char *name, struct registry_key **key) -{ - int i; - for(i = 0; i < h->num_hives; i++) - { - if(!strcmp(h->hives[i]->name, name)) { - *key = h->hives[i]->root; - return WERR_OK; - } - } - return WERR_NO_MORE_ITEMS; -} WERROR reg_del_value(struct registry_value *val) { diff --git a/source4/lib/registry/config.mk b/source4/lib/registry/config.mk index b91ec647a0..af9fb83bab 100644 --- a/source4/lib/registry/config.mk +++ b/source4/lib/registry/config.mk @@ -6,7 +6,7 @@ INIT_FUNCTION = registry_nt4_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_nt4/reg_backend_nt4.o + lib/registry/reg_backend_nt4.o # End MODULE registry_nt4 ################################################ @@ -16,7 +16,7 @@ INIT_OBJ_FILES = \ INIT_FUNCTION = registry_w95_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_w95/reg_backend_w95.o + lib/registry/reg_backend_w95.o # End MODULE registry_w95 ################################################ @@ -26,7 +26,7 @@ INIT_OBJ_FILES = \ INIT_FUNCTION = registry_dir_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_dir/reg_backend_dir.o + lib/registry/reg_backend_dir.o # End MODULE registry_dir ################################################ @@ -36,18 +36,20 @@ INIT_OBJ_FILES = \ INIT_FUNCTION = registry_rpc_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_rpc/reg_backend_rpc.o + lib/registry/reg_backend_rpc.o REQUIRED_SUBSYSTEMS = RPC_NDR_WINREG # End MODULE registry_rpc ################################################ + + ################################################ # Start MODULE registry_gconf [MODULE::registry_gconf] INIT_FUNCTION = registry_gconf_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_gconf/reg_backend_gconf.o + lib/registry/reg_backend_gconf.o REQUIRED_SUBSYSTEMS = EXT_LIB_gconf # End MODULE registry_gconf ################################################ @@ -58,7 +60,7 @@ REQUIRED_SUBSYSTEMS = EXT_LIB_gconf INIT_FUNCTION = registry_ldb_init SUBSYSTEM = REGISTRY INIT_OBJ_FILES = \ - lib/registry/reg_backend_ldb/reg_backend_ldb.o + lib/registry/reg_backend_ldb.o REQUIRED_SUBSYSTEMS = \ LIBLDB # End MODULE registry_ldb @@ -70,7 +72,8 @@ REQUIRED_SUBSYSTEMS = \ INIT_OBJ_FILES = \ lib/registry/common/reg_interface.o ADD_OBJ_FILES = \ - lib/registry/common/reg_util.o + lib/registry/common/reg_util.o \ + lib/registry/reg_samba.o REQUIRED_SUBSYSTEMS = \ LIBBASIC # End MODULE registry_ldb diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir.c index 8712e7ce7c..5c3ed3c44c 100644 --- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c +++ b/source4/lib/registry/reg_backend_dir.c @@ -110,12 +110,12 @@ static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, return WERR_NO_MORE_ITEMS; } -static WERROR reg_dir_open(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) +static WERROR reg_dir_open(struct registry_hive *h, struct registry_key **key) { if(!h->location) return WERR_INVALID_PARAM; - *key = talloc_p(mem_ctx, struct registry_key); - (*key)->backend_data = talloc_strdup(mem_ctx, h->location); + *key = talloc_p(h, struct registry_key); + (*key)->backend_data = talloc_strdup(*key, h->location); return WERR_OK; } @@ -131,7 +131,7 @@ static WERROR reg_dir_del_value(struct registry_value *v) return WERR_NOT_SUPPORTED; } -static struct registry_operations reg_backend_dir = { +static struct hive_operations reg_backend_dir = { .name = "dir", .open_hive = reg_dir_open, .open_key = reg_dir_open_key, diff --git a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c b/source4/lib/registry/reg_backend_gconf.c index fd258ca285..2fed2417b7 100644 --- a/source4/lib/registry/reg_backend_gconf/reg_backend_gconf.c +++ b/source4/lib/registry/reg_backend_gconf.c @@ -29,16 +29,16 @@ static WERROR gerror_to_werror(GError *error) return WERR_FOOBAR; } -static WERROR reg_open_gconf_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) +static WERROR reg_open_gconf_hive(struct registry_hive *h, struct registry_key **k) { g_type_init(); h->backend_data = (void *)gconf_client_get_default(); if(!h->backend_data) return WERR_FOOBAR; - *k = talloc_p(mem_ctx, struct registry_key); - (*k)->name = talloc_strdup(mem_ctx, ""); - (*k)->path = talloc_strdup(mem_ctx, ""); - (*k)->backend_data = talloc_strdup(mem_ctx, "/"); + *k = talloc_p(h, struct registry_key); + (*k)->name = talloc_strdup(*k, ""); + (*k)->path = talloc_strdup(*k, ""); + (*k)->backend_data = talloc_strdup(*k, "/"); return WERR_OK; } @@ -173,7 +173,7 @@ static WERROR gconf_set_value(struct registry_key *key, const char *valname, int return WERR_NOT_SUPPORTED; } -static struct registry_operations reg_backend_gconf = { +static struct hive_operations reg_backend_gconf = { .name = "gconf", .open_hive = reg_open_gconf_hive, .open_key = gconf_open_key, diff --git a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c b/source4/lib/registry/reg_backend_ldb.c index 380a8010f2..7eaf6194a5 100644 --- a/source4/lib/registry/reg_backend_ldb/reg_backend_ldb.c +++ b/source4/lib/registry/reg_backend_ldb.c @@ -137,7 +137,7 @@ static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, struct registry_hive *h, const c return WERR_OK; } -static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, struct registry_key **k) +static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k) { struct ldb_context *c; @@ -151,8 +151,8 @@ static WERROR ldb_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *hive, str ldb_set_debug_stderr(c); hive->backend_data = c; - hive->root = talloc_zero_p(mem_ctx, struct registry_key); - hive->root->name = talloc_strdup(mem_ctx, ""); + hive->root = talloc_zero_p(hive, struct registry_key); + hive->root->name = talloc_strdup(hive->root, ""); return WERR_OK; } @@ -202,7 +202,7 @@ static WERROR ldb_close_hive (struct registry_hive *hive) return WERR_OK; } -static struct registry_operations reg_backend_ldb = { +static struct hive_operations reg_backend_ldb = { .name = "ldb", .add_key = ldb_add_key, .del_key = ldb_del_key, diff --git a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 381f0c3bcf..117d8d1b81 100644 --- a/source4/lib/registry/reg_backend_nt4/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -1573,16 +1573,16 @@ error: #endif -static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **key) +static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) { REGF *regf; REGF_HDR *regf_hdr; uint_t regf_id, hbin_id; HBIN_HDR *hbin_hdr; - regf = (REGF *)talloc_p(mem_ctx, REGF); + regf = (REGF *)talloc_p(h, REGF); memset(regf, 0, sizeof(REGF)); - regf->owner_sid_str = h->credentials; + regf->owner_sid_str = NULL; /* FIXME: Fill in */ h->backend_data = regf; DEBUG(5, ("Attempting to load registry file\n")); @@ -1655,7 +1655,7 @@ static WERROR nt_open_hive (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct h->backend_data = regf; - return nk_to_key(mem_ctx, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); + return nk_to_key(h, h, ((REGF *)h->backend_data)->first_key, BLK_SIZE(((REGF *)h->backend_data)->first_key), NULL, key); } @@ -1724,7 +1724,7 @@ static WERROR nt_key_by_index(TALLOC_CTX *mem_ctx, struct registry_key *k, int n return WERR_NO_MORE_ITEMS; } -static struct registry_operations reg_backend_nt4 = { +static struct hive_operations reg_backend_nt4 = { .name = "nt4", .open_hive = nt_open_hive, .num_subkeys = nt_num_subkeys, diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc.c index 3969a763e0..18563b2478 100644 --- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c +++ b/source4/lib/registry/reg_backend_rpc.c @@ -21,6 +21,8 @@ #include "registry.h" #include "librpc/gen_ndr/ndr_winreg.h" +static struct hive_operations reg_backend_rpc; + /** * This is the RPC backend for the registry library. */ @@ -76,93 +78,56 @@ struct rpc_key_data { }; struct { - const char *name; + uint32 hkey; WERROR (*open) (struct dcerpc_pipe *p, TALLOC_CTX *, struct policy_handle *h); } known_hives[] = { -{ "HKEY_LOCAL_MACHINE", open_HKLM }, -{ "HKEY_CURRENT_USER", open_HKCU }, -{ "HKEY_CLASSES_ROOT", open_HKCR }, -{ "HKEY_PERFORMANCE_DATA", open_HKPD }, -{ "HKEY_USERS", open_HKU }, -{ "HKEY_DYN_DATA", open_HKDD }, -{ "HKEY_CURRENT_CONFIG", open_HKCC }, -{ NULL, NULL } +{ HKEY_LOCAL_MACHINE, open_HKLM }, +{ HKEY_CURRENT_USER, open_HKCU }, +{ HKEY_CLASSES_ROOT, open_HKCR }, +{ HKEY_PERFORMANCE_DATA, open_HKPD }, +{ HKEY_USERS, open_HKU }, +{ HKEY_DYN_DATA, open_HKDD }, +{ HKEY_CURRENT_CONFIG, open_HKCC }, +{ 0, NULL } }; static WERROR rpc_query_key(struct registry_key *k); -static WERROR rpc_list_hives (TALLOC_CTX *mem_ctx, const char *location, const char *credentials, char ***hives) -{ - int i = 0; - *hives = talloc_p(mem_ctx, char *); - for(i = 0; known_hives[i].name; i++) { - *hives = talloc_realloc_p(mem_ctx, *hives, char *, i+2); - (*hives)[i] = talloc_strdup(mem_ctx, known_hives[i].name); - } - (*hives)[i] = NULL; - return WERR_OK; -} - -static WERROR rpc_close_hive (struct registry_hive *h) +static WERROR rpc_get_hive (struct registry_context *ctx, uint32 hkey_type, struct registry_key **k) { - dcerpc_pipe_close(h->backend_data); - return WERR_OK; -} - -static WERROR rpc_open_hive(TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **k) -{ - NTSTATUS status; - char *user; - char *pass; - struct rpc_key_data *mykeydata; - struct dcerpc_pipe *p; int n; + struct registry_hive *h; + struct rpc_key_data *mykeydata; - if (!h->credentials) return WERR_INVALID_PARAM; - - /* Default to local smbd if no connection is specified */ - if (!h->location) { - h->location = talloc_strdup(mem_ctx, "ncalrpc:"); - } - - user = talloc_strdup(mem_ctx, h->credentials); - pass = strchr(user, '%'); - if (pass) { - *pass = '\0'; - pass = strdup(pass+1); - } else { - pass = strdup(""); - } - - status = dcerpc_pipe_connect(&p, h->location, - DCERPC_WINREG_UUID, - DCERPC_WINREG_VERSION, - lp_workgroup(), - user, pass); - free(pass); - - h->backend_data = p; - - if(NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Unable to open '%s': %s\n", h->location, nt_errstr(status))); - return ntstatus_to_werror(status); - } - - for(n = 0; known_hives[n].name; n++) + for(n = 0; known_hives[n].hkey; n++) { - if(!strcmp(known_hives[n].name, h->backend_hivename)) break; + if(known_hives[n].hkey == hkey_type) break; } - if(!known_hives[n].name) { - DEBUG(1, ("No such hive %s\n", known_hives[n].name)); + if(!known_hives[n].open) { + DEBUG(1, ("No such hive %d\n", hkey_type)); return WERR_NO_MORE_ITEMS; } + + h = talloc_p(ctx, struct registry_hive); + h->functions = ®_backend_rpc; + h->location = NULL; + h->backend_data = ctx->backend_data; + h->reg_ctx = ctx; - *k = talloc_p(mem_ctx, struct registry_key); - (*k)->backend_data = mykeydata = talloc_p(mem_ctx, struct rpc_key_data); + (*k) = h->root = talloc_p(h, struct registry_key); + (*k)->hive = h; + (*k)->backend_data = mykeydata = talloc_p(*k, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; - return known_hives[n].open((struct dcerpc_pipe *)h->backend_data, *k, &(mykeydata->pol)); + return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol)); +} + +static int rpc_close (void *_h) +{ + struct registry_context *h = _h; + dcerpc_pipe_close(h->backend_data); + return 0; } #if 0 @@ -385,10 +350,8 @@ static WERROR rpc_num_subkeys(struct registry_key *key, int *count) { return WERR_OK; } -static struct registry_operations reg_backend_rpc = { +static struct hive_operations reg_backend_rpc = { .name = "rpc", - .open_hive = rpc_open_hive, - .close_hive = rpc_close_hive, .open_key = rpc_open_key, .get_subkey_by_index = rpc_get_subkey_by_index, .get_value_by_index = rpc_get_value_by_index, @@ -396,9 +359,39 @@ static struct registry_operations reg_backend_rpc = { .del_key = rpc_del_key, .num_subkeys = rpc_num_subkeys, .num_values = rpc_num_values, - .list_available_hives = rpc_list_hives, }; +WERROR reg_open_remote (struct registry_context **ctx, const char *user, const char *pass, const char *location) +{ + NTSTATUS status; + struct dcerpc_pipe *p; + + *ctx = talloc_p(NULL, struct registry_context); + + /* Default to local smbd if no connection is specified */ + if (!location) { + location = talloc_strdup(ctx, "ncalrpc:"); + } + + status = dcerpc_pipe_connect(&p, location, + DCERPC_WINREG_UUID, + DCERPC_WINREG_VERSION, + lp_workgroup(), + user, pass); + (*ctx)->backend_data = p; + + if(NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status))); + return ntstatus_to_werror(status); + } + + (*ctx)->get_hive = rpc_get_hive; + + talloc_set_destructor(*ctx, rpc_close); + + return WERR_OK; +} + NTSTATUS registry_rpc_init(void) { return registry_register(®_backend_rpc); diff --git a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c b/source4/lib/registry/reg_backend_w95.c index 445d13a99c..a94ad86c2c 100644 --- a/source4/lib/registry/reg_backend_w95/reg_backend_w95.c +++ b/source4/lib/registry/reg_backend_w95.c @@ -180,14 +180,14 @@ static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr) } } -static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct registry_key **root) +static WERROR w95_open_reg (struct registry_hive *h, struct registry_key **root) { CREG *creg; DWORD creg_id, rgkn_id; DWORD i; DWORD offset; - creg = talloc_p(mem_ctx, CREG); + creg = talloc_p(h, CREG); memset(creg, 0, sizeof(CREG)); h->backend_data = creg; @@ -234,7 +234,7 @@ static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct } #endif - creg->rgdb_keys = talloc_array_p(mem_ctx, RGDB_KEY **, creg->creg_hdr->num_rgdb); + creg->rgdb_keys = talloc_array_p(h, RGDB_KEY **, creg->creg_hdr->num_rgdb); offset = 0; DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb)); @@ -250,7 +250,7 @@ static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct } - creg->rgdb_keys[i] = talloc_array_p(mem_ctx, RGDB_KEY *, rgdb_hdr->max_id+1); + creg->rgdb_keys[i] = talloc_array_p(h, RGDB_KEY *, rgdb_hdr->max_id+1); memset(creg->rgdb_keys[i], 0, sizeof(RGDB_KEY *) * (rgdb_hdr->max_id+1)); parse_rgdb_block(creg, rgdb_hdr); @@ -259,7 +259,7 @@ static WERROR w95_open_reg (TALLOC_CTX *mem_ctx, struct registry_hive *h, struct } /* First element in rgkn should be root key */ - *root = talloc_p(mem_ctx, struct registry_key); + *root = talloc_p(h, struct registry_key); (*root)->name = NULL; (*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR)); @@ -342,7 +342,7 @@ static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *k, i return WERR_OK; } -static struct registry_operations reg_backend_w95 = { +static struct hive_operations reg_backend_w95 = { .name = "w95", .open_hive = w95_open_reg, .get_value_by_index = w95_get_value_by_id, diff --git a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c b/source4/lib/registry/reg_backend_wine.c index 249af27e13..8a3458b52c 100644 --- a/source4/lib/registry/reg_backend_wine/reg_backend_wine.c +++ b/source4/lib/registry/reg_backend_wine.c @@ -22,8 +22,17 @@ #include "lib/registry/common/registry.h" #include "windows/registry.h" +static WERROR wine_open_reg (struct registry_hive *h, struct registry_key **key) +{ + /* FIXME: Open h->location and mmap it */ +} + + + static REG_OPS reg_backend_wine = { .name = "wine", + .open_hive = wine_open_reg, + }; NTSTATUS registry_wine_init(void) @@ -31,3 +40,9 @@ NTSTATUS registry_wine_init(void) register_backend("registry", ®_backend_wine); return NT_STATUS_OK; } + +WERROR reg_open_wine(struct registry_key **ctx) +{ + /* FIXME: Open ~/.wine/system.reg, etc */ + return WERR_NOT_SUPPORTED; +} diff --git a/source4/lib/registry/reg_samba.c b/source4/lib/registry/reg_samba.c new file mode 100644 index 0000000000..a19029524d --- /dev/null +++ b/source4/lib/registry/reg_samba.c @@ -0,0 +1,62 @@ +/* + Unix SMB/CIFS implementation. + Copyright (C) Jelmer Vernooij 2004. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "registry.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_REGISTRY + +static WERROR reg_samba_get_hive (struct registry_context *ctx, uint32 hkey, struct registry_key **k) +{ + WERROR error; + const char *conf; + char *backend, *location; + const char *hivename = reg_get_hkey_name(hkey); + + *k = NULL; + + conf = lp_parm_string(-1, "registry", hivename); + + if (!conf) { + return WERR_NOT_SUPPORTED; + } + + backend = talloc_strdup(NULL, conf); + location = strchr(backend, ':'); + + if (location) { + *location = '\0'; + location++; + } + + error = reg_open_hive(ctx, backend, location, NULL, k); + + talloc_destroy(backend); + + return error; +} + +WERROR reg_open_local (struct registry_context **ctx) +{ + *ctx = talloc_p(NULL, struct registry_context); + (*ctx)->get_hive = reg_samba_get_hive; + + return WERR_OK; +} diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 55c8f1e72f..fc2954b6af 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -113,21 +113,19 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, { int opt; poptContext pc; - const char *backend1 = NULL, *backend2 = NULL; - const char *location2; - const char *credentials1= NULL, *credentials2 = NULL; char *outputfile = NULL; FILE *fd = stdout; - struct registry_context *h1 = NULL, *h2; + struct registry_context *h1 = NULL, *h2 = NULL; int from_null = 0; int i; WERROR error, error2; struct poptOption long_options[] = { POPT_AUTOHELP - {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, NULL, 'c', "credentials", NULL}, + POPT_COMMON_CREDENTIALS {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, - {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL" }, + {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL", NULL }, + {"remote", 'R', POPT_ARG_STRING, NULL, 0, "Connect to remote server" , NULL }, + {"local", 'L', POPT_ARG_NONE, NULL, 0, "Open local registry", NULL }, POPT_TABLEEND }; @@ -141,49 +139,24 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); while((opt = poptGetNextOpt(pc)) != -1) { + error = WERR_OK; switch(opt) { - case 'c': - if(!credentials1 && !from_null) credentials1 = poptGetOptArg(pc); - else if(!credentials2) credentials2 = poptGetOptArg(pc); + case 'L': + if (!h1 && !from_null) error = reg_open_local(&h1); + else if (!h2) error = reg_open_local(&h2); break; - case 'b': - if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); - else if(!backend2) backend2 = poptGetOptArg(pc); + case 'R': + if (!h1 && !from_null) error = reg_open_remote(&h1, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); + else if (!h2) error = reg_open_remote(&h2, cmdline_get_username(), cmdline_get_userpassword(), poptGetOptArg(pc)); break; } - } - setup_logging(argv[0], True); - if(!from_null) { - const char *location1; - location1 = poptGetArg(pc); - if(!location1) { - poptPrintUsage(pc, stderr, 0); + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "Error: %s\n", win_errstr(error)); return 1; } - - if(!backend1) backend1 = "rpc"; - - error = reg_open(&h1, backend1, location1, credentials1); - if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); - return 1; - } - } - - location2 = poptGetArg(pc); - if(!location2) { - poptPrintUsage(pc, stderr, 0); - return 2; - } - - if(!backend2) backend2 = "rpc"; - - error = reg_open(&h2, backend2, location2, credentials2); - if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); - return 1; } + setup_logging(argv[0], True); poptFreeContext(pc); @@ -196,12 +169,25 @@ static void writediff(struct registry_key *oldkey, struct registry_key *newkey, } fprintf(fd, "REGEDIT4\n\n"); - fprintf(fd, "; Generated using regdiff\n"); + fprintf(fd, "; Generated using regdiff, part of Samba\n"); error2 = error = WERR_OK; - for(i = 0; (!h1 || i < h1->num_hives) && i < h2->num_hives; i++) { - writediff(h1?h1->hives[i]->root:NULL, h2->hives[i]->root, fd); + for(i = HKEY_CLASSES_ROOT; i <= HKEY_PN; i++) { + struct registry_key *r1, *r2; + error = reg_get_hive(h1, i, &r1); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_hkey_name(i))); + continue; + } + + error = reg_get_hive(h2, i, &r2); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_hkey_name(i))); + continue; + } + + writediff(r1, r2, fd); } fclose(fd); diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c index be60b96019..a4a4649c96 100644 --- a/source4/lib/registry/tools/regpatch.c +++ b/source4/lib/registry/tools/regpatch.c @@ -758,16 +758,14 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd { int opt; poptContext pc; - const char *location; - const char *credentials = NULL; const char *patch; - const char *backend = "rpc"; struct registry_context *h; + const char *remote = NULL; WERROR error; struct poptOption long_options[] = { POPT_AUTOHELP - {"backend", 'b', POPT_ARG_STRING, &backend, 'b', "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 'c', "credentials (user%password", NULL}, + POPT_COMMON_CREDENTIALS + {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL}, POPT_TABLEEND }; @@ -785,25 +783,22 @@ static int nt_apply_reg_command_file(struct registry_context *r, const char *cmd setup_logging(argv[0], True); - location = poptGetArg(pc); - if(!location) { - poptPrintUsage(pc, stderr, 0); - return 1; + if (remote) { + error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + } else { + error = reg_open_local (&h); } - error = reg_open(&h, backend, location, credentials); - if(!h) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); + if (W_ERROR_IS_OK(error)) { + fprintf(stderr, "Error: %s\n", win_errstr(error)); return 1; } - + patch = poptGetArg(pc); if(!patch) patch = "/dev/stdin"; poptFreeContext(pc); nt_apply_reg_command_file(h, patch); - talloc_destroy(h->mem_ctx); - return 0; } diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index f18b012720..3fd9dab268 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -164,15 +164,23 @@ static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key * static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv) { - int i; - for(i = 0; i < cur->hive->reg_ctx->num_hives; i++) { + if (!cur->hive->reg_ctx) { + fprintf(stderr, "Only one hive loaded\n"); + return cur; + } - if(argc == 1) { - printf("%s\n", cur->hive->reg_ctx->hives[i]->name); - } else if(!strcmp(cur->hive->reg_ctx->hives[i]->name, argv[1])) { - return cur->hive->reg_ctx->hives[i]->root; - } + if (argc == 1) { + printf("%s\n", cur->hive->root->name); + } else { + struct registry_key *newroot; + WERROR error = reg_get_hive_by_name(cur->hive->reg_ctx, argv[1], &newroot); + if (W_ERROR_IS_OK(error)) { + return newroot; + } else { + fprintf(stderr, "Can't switch to hive %s: %s\n", cur->hive->root->name, win_errstr(error)); + } } + return NULL; } @@ -274,11 +282,7 @@ static char **reg_complete_command(const char *text, int end) matches[0] = strdup(matches[1]); break; default: - matches[0] = malloc(samelen+1); - if (!matches[0]) - goto cleanup; - strncpy(matches[0], matches[1], samelen); - matches[0][samelen] = 0; + matches[0] = strndup(matches[1], samelen); } matches[count] = NULL; return matches; @@ -295,11 +299,11 @@ cleanup: static char **reg_complete_key(const char *text, int end) { struct registry_key *subkey; - int i, j = 0; + int i, j = 1; + int samelen = 0; int len; char **matches; TALLOC_CTX *mem_ctx; - /* Complete argument */ matches = malloc_array_p(char *, MAX_COMPLETIONS); if (!matches) return NULL; @@ -313,6 +317,12 @@ static char **reg_complete_key(const char *text, int end) if(!strncmp(text, subkey->name, len)) { matches[j] = strdup(subkey->name); j++; + + if (j == 1) + samelen = strlen(matches[j]); + else + while (strncmp(matches[j], matches[j-1], samelen) != 0) + samelen--; } } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) { break; @@ -322,8 +332,20 @@ static char **reg_complete_key(const char *text, int end) return NULL; } } - matches[j] = NULL; talloc_destroy(mem_ctx); + + if (j == 1) { /* No matches at all */ + SAFE_FREE(matches); + return NULL; + } + + if (j == 2) { /* Exact match */ + matches[0] = strdup(matches[1]); + } else { + matches[0] = strndup(matches[1], samelen); + } + + matches[j] = NULL; return matches; } @@ -341,18 +363,18 @@ static char **reg_completion(const char *text, int start, int end) int main(int argc, char **argv) { int opt; - const char *backend = "rpc"; - const char *credentials = NULL; + const char *backend = NULL; struct registry_key *curkey = NULL; poptContext pc; WERROR error; TALLOC_CTX *mem_ctx = talloc_init("cmd"); - struct registry_context *h; + const char *remote = NULL; + struct registry_context *h = NULL; struct poptOption long_options[] = { POPT_AUTOHELP - POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL}, + {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL}, POPT_TABLEEND }; @@ -370,20 +392,31 @@ static char **reg_completion(const char *text, int start, int end) setup_logging("regtree", True); - error = reg_open(&h, backend, poptPeekArg(pc), credentials); + if (remote) { + error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + } else if (backend) { + error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey); + } else { + error = reg_open_local(&h); + } + if(!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + fprintf(stderr, "Unable to open registry\n"); return 1; } - poptFreeContext(pc); - - curkey = h->hives[0]->root; + if (h) { + /*FIXME: What if HKEY_CLASSES_ROOT is not present ? */ + reg_get_hive(h, HKEY_CLASSES_ROOT, &curkey); + } + + poptFreeContext(pc); + while(True) { char *line, *prompt; - if(curkey->hive->name) { - asprintf(&prompt, "%s:%s> ", curkey->hive->name, curkey->path); + if(curkey->hive->root->name) { + asprintf(&prompt, "%s:%s> ", curkey->hive->root->name, curkey->path); } else { asprintf(&prompt, "%s> ", curkey->path); } diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index ced7a00f94..8ff68229eb 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -36,7 +36,7 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) /* Hive name */ if(p->hive->root == p) { - if(p->hive->name) printf("%s\n", p->hive->name); else printf("<No Name>\n"); + if(p->hive->root->name) printf("%s\n", p->hive->root->name); else printf("<No Name>\n"); } else { if(!p->name) printf("<No Name>\n"); if(fullpath) printf("%s\n", p->path); @@ -73,17 +73,19 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) int main(int argc, char **argv) { int opt, i; - const char *backend = "rpc"; - const char *credentials = NULL; + const char *backend = NULL; + const char *remote = NULL; poptContext pc; - struct registry_context *h; + struct registry_context *h = NULL; + struct registry_key *root = NULL; WERROR error; int fullpath = 0, no_values = 0; struct poptOption long_options[] = { POPT_AUTOHELP + POPT_COMMON_CREDENTIALS {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, - {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials (user%password)", NULL}, + {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL }, {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, POPT_TABLEEND }; @@ -102,7 +104,14 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) setup_logging("regtree", True); - error = reg_open(&h, backend, poptPeekArg(pc), credentials); + if (remote) { + error = reg_open_remote(&h, cmdline_get_username(), cmdline_get_userpassword(), remote); + } else if (backend) { + error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &root); + } else { + error = reg_open_local (&h); + } + if(!W_ERROR_IS_OK(error)) { fprintf(stderr, "Unable to open '%s' with backend '%s':%s \n", poptGetArg(pc), backend, win_errstr(error)); return 1; @@ -110,10 +119,19 @@ static void print_tree(int l, struct registry_key *p, int fullpath, int novals) poptFreeContext(pc); error = WERR_OK; - - for(i = 0; i < h->num_hives; i++) { - print_tree(0, h->hives[i]->root, fullpath, no_values); - } + if (!h) { + print_tree(0, root, fullpath, no_values); + } else { + for(i = HKEY_CLASSES_ROOT; i < HKEY_PN; i++) { + error = reg_get_hive(h, i, &root); + if (!W_ERROR_IS_OK(error)) { + fprintf(stderr, "Skipping %s\n", reg_get_hkey_name(i)); + continue; + } + print_tree(0, root, fullpath, no_values); + } + } + return 0; } diff --git a/source4/rpc_server/winreg/README b/source4/rpc_server/winreg/README new file mode 100644 index 0000000000..7563843253 --- /dev/null +++ b/source4/rpc_server/winreg/README @@ -0,0 +1,3 @@ +This is the RPC server for the registry for Samba. It is basically +a front-end for the registry library in lib/registry. See lib/registry/README for +more details. diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c index 3e9341b122..dfe3be5d8a 100644 --- a/source4/rpc_server/winreg/rpc_winreg.c +++ b/source4/rpc_server/winreg/rpc_winreg.c @@ -28,40 +28,34 @@ enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY }; -static void winreg_destroy_hive(struct dcesrv_connection *c, struct dcesrv_handle *h) +static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) { - reg_close(((struct registry_key *)h->data)->hive->reg_ctx); + struct registry_context *ctx; + reg_open_local(&ctx); + + dce_call->conn->private = ctx; + + return NT_STATUS_OK; } -static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const char *hivename, struct policy_handle **outh) +#define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind + +static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, uint32_t hkey, struct policy_handle **outh) { - struct registry_context *ctx; + struct registry_context *ctx = dce_call->conn->private; struct dcesrv_handle *h; WERROR error; - const char *conf = lp_parm_string(-1, "registry", hivename); - char *backend, *location; - - if (!conf) { - return WERR_NOT_SUPPORTED; - } - backend = talloc_strdup(mem_ctx, conf); - location = strchr(backend, ':'); + h = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY); - if (location) { - *location = '\0'; - location++; + error = reg_get_hive(ctx, hkey, (struct registry_key **)&h->data); + if (!W_ERROR_IS_OK(error)) { + return error; } - - error = reg_open(&ctx, backend, location, NULL); - if(!W_ERROR_IS_OK(error)) return error; - h = dcesrv_handle_new(dce_call->conn, HTYPE_REGKEY); - h->data = ctx->hives[0]->root; - SMB_ASSERT(h->data); - h->destroy = winreg_destroy_hive; *outh = &h->wire_handle; - return WERR_OK; + + return error; } #define func_winreg_OpenHive(k,n) static WERROR winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \ @@ -69,15 +63,15 @@ static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *m return winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\ } -func_winreg_OpenHive(HKCR,"HKEY_CLASSES_ROOT") -func_winreg_OpenHive(HKCU,"HKEY_CURRENT_USER") -func_winreg_OpenHive(HKLM,"HKEY_LOCAL_MACHINE") -func_winreg_OpenHive(HKPD,"HKEY_PERFORMANCE_DATA") -func_winreg_OpenHive(HKU,"HKEY_USERS") -func_winreg_OpenHive(HKCC,"HKEY_CURRENT_CONFIG") -func_winreg_OpenHive(HKDD,"HKEY_DYN_DATA") -func_winreg_OpenHive(HKPT,"HKEY_PT") -func_winreg_OpenHive(HKPN,"HKEY_PN") +func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT) +func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER) +func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE) +func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA) +func_winreg_OpenHive(HKU,HKEY_USERS) +func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG) +func_winreg_OpenHive(HKDD,HKEY_DYN_DATA) +func_winreg_OpenHive(HKPT,HKEY_PT) +func_winreg_OpenHive(HKPN,HKEY_PN) /* winreg_CloseKey diff --git a/source4/torture/rpc/winreg.c b/source4/torture/rpc/winreg.c index 6f44034273..d500a89435 100644 --- a/source4/torture/rpc/winreg.c +++ b/source4/torture/rpc/winreg.c @@ -451,6 +451,7 @@ static BOOL test_InitiateSystemShutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_c struct winreg_InitiateSystemShutdown r; NTSTATUS status; + init_winreg_String(&r.in.hostname, NULL); init_winreg_String(&r.in.message, msg); r.in.flags = 0; r.in.timeout = timeout; |