wmi-1.3.16 from opsview.com

This commit is contained in:
Are Casilla
2019-02-16 00:16:52 +01:00
parent 163fdd3d1b
commit 17b3af2911
2146 changed files with 678824 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
PROJECT_NAME = REGISTRY
OUTPUT_DIRECTORY = apidocs
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
OPTIMIZE_OUTPUT_FOR_C = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
GENERATE_TODOLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
SHOW_USED_FILES = NO
SHOW_DIRECTORIES = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
INPUT = . common
FILE_PATTERNS = *.c *.h *.dox
GENERATE_HTML = YES
HTML_OUTPUT = html
GENERATE_MAN = YES
ALWAYS_DETAILED_SEC = YES
JAVADOC_AUTOBRIEF = YES
+41
View File
@@ -0,0 +1,41 @@
This is the registry library. The registry is basically a bunch of
hives 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.
On Windows the various registry hives are loaded from:
HKEY_CURRENT_CONFIG: %SystemRoot%\System32\Config\System
HKEY_CURRENT_USER: %Profile%\NTUser.dat
HKEY_LOCAL_MACHINE\SAM: %SystemRoot%\System32\Config\Sam
HKEY_LOCAL_MACHINE\Security: %SystemRoot%\System32\Config\Security
HKEY_LOCAL_MACHINE\Software: %SystemRoot%\System32\Config\Software
HKEY_LOCAL_MACHINE\System: %SystemRoot%\System32\Config\System
HKEY_USERS\.DEFAULT: %SystemRoot%\System32\Config\Default
HKEY_LOCAL_MACHINE\HARDWARE: is autogenerated
+34
View File
@@ -0,0 +1,34 @@
- ..\..\, \bla\blie support in regshell
- finish rpc_server
reg_backend_dir:
- value support
reg_backend_w95.c:
- write support
reg_backend_nt4:
- write support
reg_backend_rpc:
- value enum support
- write support
- rewrite
reg_backend_ldb:
- finish
reg_backend_wine.c:
- finish
regshell:
- support for security descriptors
gregedit.c:
- support for editing values / adding values / deleting values
- support for adding/deleting keys
- support for security descriptors
- pass parsed paths around rather than strings (i.e. just a list of strings)
- integrate various registry tools ?
- finish new patchfile code
@@ -0,0 +1,585 @@
/*
Unix SMB/CIFS implementation.
Transparent registry backend handling
Copyright (C) Jelmer Vernooij 2003-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 "lib/util/dlinklist.h"
#include "lib/registry/registry.h"
#include "build.h"
/**
* @file
* @brief Main registry functions
*/
/* List of available backends */
static struct reg_init_function_entry *backends = NULL;
static struct reg_init_function_entry *reg_find_backend_entry(const char *name);
/** Register a new backend. */
_PUBLIC_ NTSTATUS registry_register(const void *_hive_ops)
{
const struct hive_operations *hive_ops = _hive_ops;
struct reg_init_function_entry *entry = backends;
DEBUG(5,("Attempting to register registry backend %s\n", hive_ops->name));
/* Check for duplicates */
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 = talloc(talloc_autofree_context(), struct reg_init_function_entry);
entry->hive_functions = hive_ops;
DLIST_ADD(backends, entry);
DEBUG(5,("Successfully added registry backend '%s'\n", hive_ops->name));
return NT_STATUS_OK;
}
/** Find a backend in the list of available backends */
static struct reg_init_function_entry *reg_find_backend_entry(const char *name)
{
struct reg_init_function_entry *entry;
entry = backends;
while(entry) {
if (strcmp(entry->hive_functions->name, name) == 0) return entry;
entry = entry->next;
}
return NULL;
}
/** Initialize the registry subsystem */
_PUBLIC_ NTSTATUS registry_init(void)
{
init_module_fn static_init[] = STATIC_registry_MODULES;
init_module_fn *shared_init = load_samba_modules(NULL, "registry");
run_init_functions(static_init);
run_init_functions(shared_init);
talloc_free(shared_init);
return NT_STATUS_OK;
}
/** Check whether a certain backend is present. */
_PUBLIC_ BOOL reg_has_backend(const char *backend)
{
return reg_find_backend_entry(backend) != NULL?True:False;
}
const struct reg_predefined_key reg_predefined_keys[] = {
{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_PERFORMANCE_TEXT, "HKEY_PERFORMANCE_TEXT" },
{HKEY_PERFORMANCE_NLSTEXT, "HKEY_PERFORMANCE_NLSTEXT" },
{ 0, NULL }
};
/** Obtain a list of predefined keys. */
_PUBLIC_ int reg_list_predefs(TALLOC_CTX *mem_ctx, char ***predefs, uint32_t **hkeys)
{
int i;
*predefs = talloc_array(mem_ctx, char *, ARRAY_SIZE(reg_predefined_keys));
*hkeys = talloc_array(mem_ctx, uint32_t, ARRAY_SIZE(reg_predefined_keys));
for (i = 0; reg_predefined_keys[i].name; i++) {
(*predefs)[i] = talloc_strdup(mem_ctx, reg_predefined_keys[i].name);
(*hkeys)[i] = reg_predefined_keys[i].handle;
}
return i;
}
/** Obtain name of specific hkey. */
_PUBLIC_ const char *reg_get_predef_name(uint32_t hkey)
{
int i;
for (i = 0; reg_predefined_keys[i].name; i++) {
if (reg_predefined_keys[i].handle == hkey) return reg_predefined_keys[i].name;
}
return NULL;
}
/** Get predefined key by name. */
_PUBLIC_ WERROR reg_get_predefined_key_by_name(struct registry_context *ctx, const char *name, struct registry_key **key)
{
int i;
for (i = 0; reg_predefined_keys[i].name; i++) {
if (!strcasecmp(reg_predefined_keys[i].name, name)) return reg_get_predefined_key(ctx, reg_predefined_keys[i].handle, key);
}
DEBUG(1, ("No predefined key with name '%s'\n", name));
return WERR_BADFILE;
}
/** Get predefined key by id. */
_PUBLIC_ WERROR reg_get_predefined_key(struct registry_context *ctx, uint32_t hkey, struct registry_key **key)
{
WERROR ret = ctx->get_predefined_key(ctx, hkey, key);
if (W_ERROR_IS_OK(ret)) {
(*key)->name = talloc_strdup(*key, reg_get_predef_name(hkey));
(*key)->path = "";
}
return ret;
}
/** Open a registry file/host/etc */
_PUBLIC_ WERROR reg_open_hive(TALLOC_CTX *parent_ctx, const char *backend, const char *location, struct auth_session_info *session_info, struct cli_credentials *credentials, struct registry_key **root)
{
struct registry_hive *rethive;
struct registry_key *retkey = NULL;
struct reg_init_function_entry *entry;
WERROR werr;
entry = reg_find_backend_entry(backend);
if (!entry) {
DEBUG(0, ("No such registry backend '%s' loaded!\n", backend));
return WERR_GENERAL_FAILURE;
}
if(!entry->hive_functions || !entry->hive_functions->open_hive) {
return WERR_NOT_SUPPORTED;
}
rethive = talloc(parent_ctx, struct registry_hive);
rethive->location = location?talloc_strdup(rethive, location):NULL;
rethive->session_info = talloc_reference(rethive, session_info);
rethive->credentials = talloc_reference(rethive, credentials);
rethive->functions = entry->hive_functions;
rethive->backend_data = NULL;
werr = entry->hive_functions->open_hive(rethive, &retkey);
if(!W_ERROR_IS_OK(werr)) {
return werr;
}
if(!retkey) {
DEBUG(0, ("Backend %s didn't provide root key!\n", backend));
return WERR_GENERAL_FAILURE;
}
rethive->root = retkey;
retkey->hive = rethive;
retkey->name = NULL;
retkey->path = talloc_strdup(retkey, "");
*root = retkey;
return WERR_OK;
}
/**
* 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
*/
_PUBLIC_ WERROR reg_open_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, const char *name, struct registry_key **result)
{
WERROR error;
if(!parent) {
DEBUG(0, ("Invalid parent key specified for open of '%s'\n", name));
return WERR_INVALID_PARAM;
}
if(!parent->hive->functions->open_key &&
(parent->hive->functions->get_subkey_by_name ||
parent->hive->functions->get_subkey_by_index)) {
char *orig = strdup(name),
*curbegin = orig,
*curend = strchr(orig, '\\');
struct registry_key *curkey = parent;
while(curbegin && *curbegin) {
if(curend)*curend = '\0';
error = reg_key_get_subkey_by_name(mem_ctx, curkey, curbegin, &curkey);
if(!W_ERROR_IS_OK(error)) {
SAFE_FREE(orig);
return error;
}
if(!curend) break;
curbegin = curend + 1;
curend = strchr(curbegin, '\\');
}
SAFE_FREE(orig);
*result = curkey;
return WERR_OK;
}
if(!parent->hive->functions->open_key) {
DEBUG(0, ("Registry backend doesn't have get_subkey_by_name nor open_key!\n"));
return WERR_NOT_SUPPORTED;
}
error = parent->hive->functions->open_key(mem_ctx, parent, name, result);
if(!W_ERROR_IS_OK(error)) return error;
(*result)->hive = parent->hive;
(*result)->path = ((parent->hive->root == parent)?talloc_strdup(mem_ctx, name):talloc_asprintf(mem_ctx, "%s\\%s", parent->path, name));
(*result)->hive = parent->hive;
return WERR_OK;
}
/**
* Get value by index
*/
_PUBLIC_ WERROR reg_key_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_value **val)
{
if(!key) return WERR_INVALID_PARAM;
if(key->hive->functions->get_value_by_index) {
WERROR status = key->hive->functions->get_value_by_index(mem_ctx, key, idx, val);
if(!W_ERROR_IS_OK(status))
return status;
} else {
return WERR_NOT_SUPPORTED;
}
return WERR_OK;
}
/**
* Get the number of subkeys.
*/
_PUBLIC_ WERROR reg_key_num_subkeys(const struct registry_key *key, uint32_t *count)
{
if(!key) return WERR_INVALID_PARAM;
if(key->hive->functions->num_subkeys) {
return key->hive->functions->num_subkeys(key, count);
}
if(key->hive->functions->get_subkey_by_index) {
int i;
WERROR error;
struct registry_key *dest = NULL;
TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, key, i, &dest)); i++);
talloc_free(mem_ctx);
*count = i;
if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
return error;
}
return WERR_NOT_SUPPORTED;
}
/**
* Get the number of values of a key.
*/
_PUBLIC_ WERROR reg_key_num_values(const struct registry_key *key, uint32_t *count)
{
if(!key) return WERR_INVALID_PARAM;
if (key->hive->functions->num_values) {
return key->hive->functions->num_values(key, count);
}
if(key->hive->functions->get_value_by_index) {
int i;
WERROR error;
struct registry_value *dest;
TALLOC_CTX *mem_ctx = talloc_init("num_subkeys");
for(i = 0; W_ERROR_IS_OK(error = key->hive->functions->get_value_by_index(mem_ctx, key, i, &dest)); i++);
talloc_free(mem_ctx);
*count = i;
if(W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) error = WERR_OK;
return error;
}
return WERR_NOT_SUPPORTED;
}
/**
* Get subkey by index.
*/
_PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *key, int idx, struct registry_key **subkey)
{
if(!key) return WERR_INVALID_PARAM;
if(key->hive->functions->get_subkey_by_index) {
WERROR status = key->hive->functions->get_subkey_by_index(mem_ctx, key, idx, subkey);
if(!NT_STATUS_IS_OK(status)) return status;
} else {
return WERR_NOT_SUPPORTED;
}
if(key->hive->root == key)
(*subkey)->path = talloc_strdup(mem_ctx, (*subkey)->name);
else
(*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
(*subkey)->hive = key->hive;
return WERR_OK;;
}
/**
* Get subkey by name.
*/
WERROR reg_key_get_subkey_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_key **subkey)
{
int i;
WERROR error = WERR_OK;
if(!key) return WERR_INVALID_PARAM;
if(key->hive->functions->get_subkey_by_name) {
error = key->hive->functions->get_subkey_by_name(mem_ctx, key,name,subkey);
} else if(key->hive->functions->open_key) {
error = key->hive->functions->open_key(mem_ctx, key, name, subkey);
} else if(key->hive->functions->get_subkey_by_index) {
for(i = 0; W_ERROR_IS_OK(error); i++) {
error = reg_key_get_subkey_by_index(mem_ctx, key, i, subkey);
if(W_ERROR_IS_OK(error) && !strcasecmp((*subkey)->name, name)) {
break;
}
}
if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
error = WERR_DEST_NOT_FOUND;
} else {
return WERR_NOT_SUPPORTED;
}
if(!W_ERROR_IS_OK(error)) return error;
(*subkey)->path = talloc_asprintf(mem_ctx, "%s\\%s", key->path, (*subkey)->name);
(*subkey)->hive = key->hive;
return WERR_OK;
}
/**
* Get value by name.
*/
_PUBLIC_ WERROR reg_key_get_value_by_name(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char *name, struct registry_value **val)
{
int i;
WERROR error = WERR_OK;
if(!key) return WERR_INVALID_PARAM;
if(key->hive->functions->get_value_by_name) {
error = key->hive->functions->get_value_by_name(mem_ctx, key,name, val);
} else {
for(i = 0; W_ERROR_IS_OK(error); i++) {
error = reg_key_get_value_by_index(mem_ctx, key, i, val);
if(W_ERROR_IS_OK(error) && !strcasecmp((*val)->name, name)) {
break;
}
}
}
if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
return WERR_DEST_NOT_FOUND;
return error;
}
/**
* Delete a key.
*/
_PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name)
{
WERROR error;
if(!parent) return WERR_INVALID_PARAM;
if(!parent->hive->functions->del_key)
return WERR_NOT_SUPPORTED;
error = parent->hive->functions->del_key(parent, name);
if(!W_ERROR_IS_OK(error)) return error;
return WERR_OK;
}
/**
* Add a key.
*/
_PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **newkey)
{
WERROR error;
if (!parent) return WERR_INVALID_PARAM;
if (!parent->hive->functions->add_key) {
DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->hive->functions->name));
return WERR_NOT_SUPPORTED;
}
error = parent->hive->functions->add_key(mem_ctx, parent, name, access_mask, desc, newkey);
if(!W_ERROR_IS_OK(error)) return error;
if (!*newkey) {
DEBUG(0, ("Backend returned WERR_OK, but didn't specify key!\n"));
return WERR_GENERAL_FAILURE;
}
(*newkey)->hive = parent->hive;
return WERR_OK;
}
/**
* Set a value.
*/
_PUBLIC_ WERROR reg_val_set(struct registry_key *key, const char *value, uint32_t type, DATA_BLOB data)
{
/* A 'real' set function has preference */
if (key->hive->functions->set_value)
return key->hive->functions->set_value(key, value, type, data);
DEBUG(1, ("Backend '%s' doesn't support method set_value\n", key->hive->functions->name));
return WERR_NOT_SUPPORTED;
}
/**
* Get the security descriptor on a key.
*/
_PUBLIC_ WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, struct security_descriptor **secdesc)
{
/* A 'real' set function has preference */
if (key->hive->functions->key_get_sec_desc)
return key->hive->functions->key_get_sec_desc(ctx, key, secdesc);
DEBUG(1, ("Backend '%s' doesn't support method get_sec_desc\n", key->hive->functions->name));
return WERR_NOT_SUPPORTED;
}
/**
* Delete a value.
*/
_PUBLIC_ WERROR reg_del_value(const struct registry_key *key, const char *valname)
{
WERROR ret = WERR_OK;
if(!key->hive->functions->del_value)
return WERR_NOT_SUPPORTED;
ret = key->hive->functions->del_value(key, valname);
if(!W_ERROR_IS_OK(ret)) return ret;
return ret;
}
/**
* Flush a key to disk.
*/
_PUBLIC_ WERROR reg_key_flush(const struct registry_key *key)
{
if (!key) {
return WERR_INVALID_PARAM;
}
if (key->hive->functions->flush_key) {
return key->hive->functions->flush_key(key);
}
/* No need for flushing, apparently */
return WERR_OK;
}
/**
* Get the maximum name and data lengths of the subkeys.
*/
_PUBLIC_ WERROR reg_key_subkeysizes(const struct registry_key *key, uint32_t *max_subkeylen, uint32_t *max_subkeysize)
{
int i = 0;
struct registry_key *subkey;
WERROR error;
TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
*max_subkeylen = *max_subkeysize = 0;
do {
error = reg_key_get_subkey_by_index(mem_ctx, key, i, &subkey);
if (W_ERROR_IS_OK(error)) {
*max_subkeysize = MAX(*max_subkeysize, 0xFF);
*max_subkeylen = MAX(*max_subkeylen, strlen(subkey->name));
}
i++;
} while (W_ERROR_IS_OK(error));
talloc_free(mem_ctx);
return WERR_OK;
}
/**
* Get the maximum name and data lengths of the values.
*/
_PUBLIC_ WERROR reg_key_valuesizes(const struct registry_key *key, uint32_t *max_valnamelen, uint32_t *max_valbufsize)
{
int i = 0;
struct registry_value *value;
WERROR error;
TALLOC_CTX *mem_ctx = talloc_init("subkeysize");
*max_valnamelen = *max_valbufsize = 0;
do {
error = reg_key_get_value_by_index(mem_ctx, key, i, &value);
if (W_ERROR_IS_OK(error)) {
if (value->name) {
*max_valnamelen = MAX(*max_valnamelen, strlen(value->name));
}
*max_valbufsize = MAX(*max_valbufsize, value->data.length);
}
i++;
} while (W_ERROR_IS_OK(error));
talloc_free(mem_ctx);
return WERR_OK;
}
+248
View File
@@ -0,0 +1,248 @@
/*
Unix SMB/CIFS implementation.
Transparent registry backend handling
Copyright (C) Jelmer Vernooij 2003-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 "lib/registry/registry.h"
#include "librpc/gen_ndr/winreg.h"
/**
* @file
* @brief Registry utility functions
*/
static const struct {
uint32_t id;
const char *name;
} reg_value_types[] = {
{ REG_SZ, "REG_SZ" },
{ REG_DWORD, "REG_DWORD" },
{ REG_BINARY, "REG_BINARY" },
{ REG_EXPAND_SZ, "REG_EXPAND_SZ" },
{ REG_NONE, "REG_NONE" },
{ 0, NULL }
};
/** Return string description of registry value type */
_PUBLIC_ const char *str_regtype(int type)
{
int i;
for (i = 0; reg_value_types[i].name; i++) {
if (reg_value_types[i].id == type)
return reg_value_types[i].name;
}
return "Unknown";
}
_PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, DATA_BLOB *data)
{
char *ret = NULL;
if(data->length == 0) return talloc_strdup(mem_ctx, "");
switch (type) {
case REG_EXPAND_SZ:
case REG_SZ:
convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data->data, data->length, (void **)&ret);
return ret;
case REG_BINARY:
ret = data_blob_hex_string(mem_ctx, data);
return ret;
case REG_DWORD:
if (*(int *)data->data == 0)
return talloc_strdup(mem_ctx, "0");
return talloc_asprintf(mem_ctx, "0x%x", *(int *)data->data);
case REG_MULTI_SZ:
/* FIXME */
break;
default:
break;
}
return ret;
}
/** Generate a string that describes a registry value */
_PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, struct registry_value *val)
{
return talloc_asprintf(mem_ctx, "%s = %s : %s", val->name?val->name:"<No Name>", str_regtype(val->data_type), reg_val_data_string(mem_ctx, val->data_type, &val->data));
}
_PUBLIC_ BOOL reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, const char *data_str, uint32_t *type, DATA_BLOB *data)
{
int i;
*type = -1;
/* Find the correct type */
for (i = 0; reg_value_types[i].name; i++) {
if (!strcmp(reg_value_types[i].name, type_str)) {
*type = reg_value_types[i].id;
break;
}
}
if (*type == -1)
return False;
/* Convert data appropriately */
switch (*type)
{
case REG_SZ:
case REG_EXPAND_SZ:
data->length = convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, data_str, strlen(data_str), (void **)&data->data);
break;
case REG_DWORD: {
uint32_t tmp = strtol(data_str, NULL, 0);
*data = data_blob_talloc(mem_ctx, &tmp, 4);
}
break;
case REG_NONE:
ZERO_STRUCTP(data);
break;
case REG_BINARY:
*data = strhex_to_data_blob(data_str);
talloc_steal(mem_ctx, data->data);
break;
default:
/* FIXME */
return False;
}
return True;
}
/**
* Replace all \'s with /'s
*/
char *reg_path_win2unix(char *path)
{
int i;
for(i = 0; path[i]; i++) {
if(path[i] == '\\') path[i] = '/';
}
return path;
}
/**
* Replace all /'s with \'s
*/
char *reg_path_unix2win(char *path)
{
int i;
for(i = 0; path[i]; i++) {
if(path[i] == '/') path[i] = '\\';
}
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 = talloc_strndup(mem_ctx, name, predeflength);
error = reg_get_predefined_key_by_name(handle, predefname, &predef);
talloc_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_free(mem_ctx);
return error;
}
WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx, const char *path, uint32_t access_mask, struct security_descriptor *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;
}
+12
View File
@@ -0,0 +1,12 @@
# Registry backends
SMB_ENABLE(registry_gconf, NO)
SMB_EXT_LIB_FROM_PKGCONFIG(gconf, gconf-2.0)
AC_ARG_ENABLE(reg-gconf,
[ --enable-reg-gconf Enable support for GConf registry backend],
[
if test t$enable = tyes; then
SMB_ENABLE(registry_gconf, $SMB_ENABLE_gconf)
fi
])
+150
View File
@@ -0,0 +1,150 @@
# Registry backends
################################################
# Start MODULE registry_nt4
[MODULE::registry_nt4]
INIT_FUNCTION = registry_nt4_init
SUBSYSTEM = registry
OBJ_FILES = \
reg_backend_nt4.o
PUBLIC_DEPENDENCIES = TDR_REGF
# End MODULE registry_nt4
################################################
[SUBSYSTEM::TDR_REGF]
PUBLIC_DEPENDENCIES = TDR
OBJ_FILES = tdr_regf.o
# Special support for external builddirs
lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c
$(srcdir)/lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c
lib/registry/tdr_regf.h: lib/registry/tdr_regf.c
lib/registry/tdr_regf.c: $(srcdir)/lib/registry/regf.idl
@CPP="$(CPP)" $(PERL) $(srcdir)/pidl/pidl $(PIDL_ARGS) \
--header --outputdir=lib/registry \
--tdr-parser -- $(srcdir)/lib/registry/regf.idl
clean::
@-rm -f lib/registry/regf.h lib/registry/tdr_regf*
################################################
# Start MODULE registry_w95
[MODULE::registry_w95]
INIT_FUNCTION = registry_w95_init
SUBSYSTEM = registry
OBJ_FILES = \
reg_backend_w95.o
# End MODULE registry_w95
################################################
################################################
# Start MODULE registry_dir
[MODULE::registry_dir]
INIT_FUNCTION = registry_dir_init
SUBSYSTEM = registry
OBJ_FILES = \
reg_backend_dir.o
PUBLIC_DEPENDENCIES = LIBTALLOC
# End MODULE registry_dir
################################################
################################################
# Start MODULE registry_rpc
[MODULE::registry_rpc]
INIT_FUNCTION = registry_rpc_init
PRIVATE_PROTO_HEADER = reg_backend_rpc.h
OUTPUT_TYPE = INTEGRATED
SUBSYSTEM = registry
OBJ_FILES = \
reg_backend_rpc.o
PUBLIC_DEPENDENCIES = RPC_NDR_WINREG
# End MODULE registry_rpc
################################################
################################################
# Start MODULE registry_gconf
[MODULE::registry_gconf]
INIT_FUNCTION = registry_gconf_init
SUBSYSTEM = registry
OBJ_FILES = \
reg_backend_gconf.o
PUBLIC_DEPENDENCIES = gconf
# End MODULE registry_gconf
################################################
################################################
# Start MODULE registry_ldb
[MODULE::registry_ldb]
INIT_FUNCTION = registry_ldb_init
SUBSYSTEM = registry
OBJ_FILES = \
reg_backend_ldb.o
PUBLIC_DEPENDENCIES = \
ldb
# End MODULE registry_ldb
################################################
################################################
# Start SUBSYSTEM registry
[LIBRARY::registry]
VERSION = 0.0.1
SO_VERSION = 0
DESCRIPTION = Windows-style registry library
OBJ_FILES = \
common/reg_interface.o \
common/reg_util.o \
reg_samba.o \
patchfile.o
PUBLIC_DEPENDENCIES = \
LIBSAMBA-UTIL CHARSET
PRIVATE_PROTO_HEADER = registry_proto.h
PUBLIC_HEADERS = registry.h
# End MODULE registry_ldb
################################################
################################################
# Start BINARY regdiff
[BINARY::regdiff]
INSTALLDIR = BINDIR
OBJ_FILES = tools/regdiff.o
PRIVATE_DEPENDENCIES = \
LIBSAMBA-CONFIG registry LIBPOPT POPT_SAMBA POPT_CREDENTIALS
MANPAGE = man/regdiff.1
# End BINARY regdiff
################################################
################################################
# Start BINARY regpatch
[BINARY::regpatch]
INSTALLDIR = BINDIR
OBJ_FILES = tools/regpatch.o
PRIVATE_DEPENDENCIES = \
LIBSAMBA-CONFIG registry LIBPOPT POPT_SAMBA POPT_CREDENTIALS
MANPAGE = man/regpatch.1
# End BINARY regpatch
################################################
################################################
# Start BINARY regshell
[BINARY::regshell]
INSTALLDIR = BINDIR
OBJ_FILES = tools/regshell.o
PRIVATE_DEPENDENCIES = \
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS \
SMBREADLINE
MANPAGE = man/regshell.1
# End BINARY regshell
################################################
################################################
# Start BINARY regtree
[BINARY::regtree]
INSTALLDIR = BINDIR
OBJ_FILES = tools/regtree.o
PRIVATE_DEPENDENCIES = \
LIBSAMBA-CONFIG LIBPOPT registry POPT_SAMBA POPT_CREDENTIALS
MANPAGE = man/regtree.1
# End BINARY regtree
################################################
+100
View File
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
<refentry id="regdiff.1">
<refmeta>
<refentrytitle>regdiff</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>regdiff</refname>
<refpurpose>Diff program for Windows registry files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>regdiff</command>
<arg choice="opt">--help</arg>
<arg choice="opt">--backend=BACKEND</arg>
<arg choice="opt">--backend=BACKEND</arg>
<arg choice="opt">--credentials=CREDENTIALS</arg>
<arg choice="opt">--credentials=CREDENTIALS</arg>
<arg choice="opt">location</arg>
<arg choice="opt">location</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>regdiff compares two Windows registry files key by key
and value by value and generates a text file that contains the
differences between the two files.</para>
<para>A file generated by regdiff can later be applied to a
registry file by the regpatch utility. </para>
<para>regdiff and regpatch use the same file format as
the regedit32.exe utility from Windows.</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>--help</term>
<listitem><para>
Show list of available options.</para></listitem>
</varlistentry>
<varlistentry>
<term>--backend BACKEND</term>
<listitem><para>Name of backend to load. Possible values are:
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
</para>
<para>
This argument can be specified twice: once for the first
registry file and once for the second.
</para></listitem>
</varlistentry>
<varlistentry>
<term>--credentials=CREDENTIALS</term>
<listitem><para>
Credentials to use, if any. Password should be separated from user name by a percent sign.
</para>
<para>
This argument can be specified twice: once for the first
registry file and once for the second.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>VERSION</title>
<para>This man page is correct for version 4.0 of the Samba suite.</para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>gregedit, regshell, regpatch, regtree, samba, patch, diff</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>This utility is part of the <ulink url="http://www.samba.org/">Samba</ulink> suite, which is developed by the global <ulink url="http://www.samba.org/samba/team/">Samba Team</ulink>.</para>
<para>This manpage and regdiff were written by Jelmer Vernooij. </para>
</refsect1>
</refentry>
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
<refentry id="regpatch.1">
<refmeta>
<refentrytitle>regpatch</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>regpatch</refname>
<refpurpose>Applies registry patches to registry files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>regpatch</command>
<arg choice="opt">--help</arg>
<arg choice="opt">--backend=BACKEND</arg>
<arg choice="opt">--credentials=CREDENTIALS</arg>
<arg choice="opt">location</arg>
<arg choice="opt">patch-file</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>The regpatch utility applies registry patches to Windows registry
files. The patch files should have the same format as is being used
by the regdiff utility and regedit32.exe from Windows.</para>
<para>If no patch file is specified on the command line,
regpatch attempts to read it from standard input.</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>--help</term>
<listitem><para>
Show list of available options.</para></listitem>
</varlistentry>
<varlistentry>
<term>--backend BACKEND</term>
<listitem><para>Name of backend to load. Possible values are:
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
</para></listitem>
</varlistentry>
<varlistentry>
<term>--credentials=CREDENTIALS</term>
<listitem><para>
Credentials to use, if any. Password should be separated from user name by a percent sign.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>VERSION</title>
<para>This man page is correct for version 4.0 of the Samba suite.</para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>regdiff, regtree, regshell, gregedit, samba, diff, patch</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>This utility is part of the <ulink url="http://www.samba.org/">Samba</ulink> suite, which is developed by the global <ulink url="http://www.samba.org/samba/team/">Samba Team</ulink>.</para>
<para>This manpage and regpatch were written by Jelmer Vernooij. </para>
</refsect1>
</refentry>
@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
<refentry id="regshell.1">
<refmeta>
<refentrytitle>regshell</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>regshell</refname>
<refpurpose>Windows registry file browser using readline</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>regshell</command>
<arg choice="opt">--help</arg>
<arg choice="opt">--backend=BACKEND</arg>
<arg choice="opt">--credentials=CREDENTIALS</arg>
<arg choice="opt">location</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>
regshell is a utility that lets you browse thru a Windows registry
file as if you were using a regular unix shell to browse thru a
file system.
</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>--help</term>
<listitem><para>
Show list of available options.</para></listitem>
</varlistentry>
<varlistentry>
<term>--backend BACKEND</term>
<listitem><para>Name of backend to load. Possible values are:
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
</para></listitem>
</varlistentry>
<varlistentry>
<term>--credentials=CREDENTIALS</term>
<listitem><para>
Credentials to use, if any. Password should be separated from user name by a percent sign.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>COMMANDS</title>
<variablelist>
<varlistentry>
<term>ck|cd &lt;keyname&gt;</term>
<listitem><para>
Go to the specified subkey.
</para></listitem>
</varlistentry>
<varlistentry>
<term>ch|predef [predefined-key-name]</term>
<listitem><para>
Go to the specified predefined key.
</para></listitem>
</varlistentry>
<varlistentry>
<term>list|ls</term>
<listitem><para>
List subkeys and values of the current key.
</para></listitem>
</varlistentry>
<varlistentry>
<term>mkkey|mkdir &lt;keyname&gt;</term>
<listitem><para>
Create a key with the specified <replaceable>keyname</replaceable> as a subkey of the current key.
</para></listitem>
</varlistentry>
<varlistentry>
<term>rmval|rm &lt;valname&gt;</term>
<listitem><para>
Delete the specified value.
</para></listitem>
</varlistentry>
<varlistentry>
<term>rmkey|rmdir &lt;keyname&gt;</term>
<listitem><para>
Delete the specified subkey recursively.
</para></listitem>
</varlistentry>
<varlistentry>
<term>pwd|pwk</term>
<listitem><para>Print the full name of the current key.</para></listitem>
</varlistentry>
<varlistentry>
<term>set|update</term>
<listitem><para>Update the value of a key value. Not implemented at the moment.</para></listitem>
</varlistentry>
<varlistentry>
<term>help|?</term>
<listitem><para>Print a list of available commands.</para></listitem>
</varlistentry>
<varlistentry>
<term>exit|quit</term>
<listitem><para>Leave regshell.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>EXAMPLES</title>
<para>Browsing thru a nt4 registry file</para>
<screen>
<userinput>regshell -b nt4 NTUSER.DAT</userinput>
$$$PROTO.HIV> <userinput>ls</userinput>
K AppEvents
K Console
K Control Panel
K Environment
K Identities
K Keyboard Layout
K Network
K Printers
K Software
K UNICODE Program Groups
K Windows 3.1 Migration Status
$$$PROTO.HIV> <userinput>exit</userinput>
</screen>
<para>Listing the subkeys of HKEY_CURRENT_USER\AppEvents on a remote computer:</para>
<screen>
<userinput>regshell --remote=ncacn_np:aurelia -c "jelmer%secret"</userinput>
HKEY_CURRENT_MACHINE> <userinput>predef HKEY_CURRENT_USER</userinput>
HKEY_CURRENT_USER> <userinput>cd AppEvents</userinput>
Current path is: HKEY_CURRENT_USER\AppEvents
HKEY_CURRENT_USER\AppEvents> <userinput>ls</userinput>
K EventLabels
K Schemes
HKEY_CURRENT_USER\AppEvents> <userinput>exit</userinput>
</screen>
</refsect1>
<refsect1>
<title>VERSION</title>
<para>This man page is correct for version 4.0 of the Samba suite.</para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>regtree, regdiff, regpatch, gregedit, samba</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>This utility is part of the <ulink url="http://www.samba.org/">Samba</ulink> suite, which is developed by the global <ulink url="http://www.samba.org/samba/team/">Samba Team</ulink>.</para>
<para>This manpage and regshell were written by Jelmer Vernooij. </para>
</refsect1>
</refentry>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
<refentry id="regtree.1">
<refmeta>
<refentrytitle>regtree</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>regtree</refname>
<refpurpose>Text-mode registry viewer</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>regtree</command>
<arg choice="opt">--help</arg>
<arg choice="opt">--backend=BACKEND</arg>
<arg choice="opt">--fullpath</arg>
<arg choice="opt">--no-values</arg>
<arg choice="opt">--credentials=CREDENTIALS</arg>
<arg choice="opt">location</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>The regtree utility prints out all the contents of a
Windows registry file. Subkeys are printed with one level
more indentation than their parents. </para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>--help</term>
<listitem><para>
Show list of available options.</para></listitem>
</varlistentry>
<varlistentry>
<term>--backend BACKEND</term>
<listitem><para>Name of backend to load. Possible values are:
w95, nt4, gconf, dir and rpc. The default is <emphasis>dir</emphasis>.
</para></listitem>
</varlistentry>
<varlistentry>
<term>--credentials=CREDENTIALS</term>
<listitem><para>
Credentials to use, if any. Password should be separated from user name by a percent sign.</para></listitem>
</varlistentry>
<varlistentry>
<term>--fullpath</term>
<listitem><para>
Print the full path to each key instead of only its name.
</para>
</listitem>
</varlistentry>
<varlistentry><term>--no-values</term>
<listitem><para>Don't print values, just keys.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>VERSION</title>
<para>This man page is correct for version 4.0 of the Samba suite.</para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>gregedit, regshell, regdiff, regpatch, samba</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
<para>This utility is part of the <ulink url="http://www.samba.org/">Samba</ulink> suite, which is developed by the global <ulink url="http://www.samba.org/samba/team/">Samba Team</ulink>.</para>
<para>This manpage and regtree were written by Jelmer Vernooij. </para>
</refsect1>
</refentry>
+419
View File
@@ -0,0 +1,419 @@
/*
Unix SMB/CIFS implementation.
Reading .REG files
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 "lib/registry/registry.h"
#include "system/filesys.h"
/**
* @file
* @brief Registry patch files
*/
#define DEFAULT_IDENT_STRING "SAMBA4 REGISTRY"
static struct reg_diff_key *diff_find_add_key(struct reg_diff *diff, const char *path)
{
int i;
for (i = 0; diff->numkeys; i++) {
if (!strcasecmp(diff->keys[i].name, path))
return &diff->keys[i];
}
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, path);
diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY;
diff->keys[diff->numkeys].numvalues = 0;
diff->keys[diff->numkeys].values = NULL;
diff->numkeys++;
return NULL;
}
/*
* Generate difference between two keys
*/
static WERROR reg_generate_diff_key(struct reg_diff *diff, struct registry_key *oldkey, struct registry_key *newkey)
{
int i;
struct registry_key *t1, *t2;
struct registry_value *v1, *v2;
WERROR error1, error2;
TALLOC_CTX *mem_ctx = talloc_init("writediff");
/* Subkeys that were deleted */
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, &t1)); i++) {
error2 = reg_key_get_subkey_by_name(mem_ctx, newkey, t1->name, &t2);
if (W_ERROR_IS_OK(error2))
continue;
if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2)));
return error2;
}
/* newkey didn't have such a subkey, add del diff */
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, t1->path);
diff->keys[diff->numkeys].changetype = REG_DIFF_DEL_KEY;
diff->numkeys++;
}
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1)));
talloc_free(mem_ctx);
return error1;
}
/* Subkeys that were added */
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, &t1)); i++) {
error2 = reg_key_get_subkey_by_name(mem_ctx, oldkey, t1->name, &t2);
if (W_ERROR_IS_OK(error2))
continue;
if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
DEBUG(0, ("Error occured while getting subkey by name: %d\n", W_ERROR_V(error2)));
return error2;
}
/* oldkey didn't have such a subkey, add add diff */
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, t1->path);
diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY;
diff->keys[diff->numkeys].numvalues = 0;
diff->keys[diff->numkeys].values = NULL;
diff->numkeys++;
reg_generate_diff_key(diff, t1, t2);
}
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while getting subkey by index: %d\n", W_ERROR_V(error1)));
talloc_free(mem_ctx);
return error1;
}
/* Values that were changed */
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &v1)); i++) {
struct reg_diff_key *thiskey = NULL;
error2 = reg_key_get_value_by_name(mem_ctx, oldkey, v1->name, &v2);
if(!W_ERROR_IS_OK(error2) &&
!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2)));
return error2;
}
if (W_ERROR_IS_OK(error2) && data_blob_equal(&v1->data, &v2->data))
continue;
thiskey = diff_find_add_key(diff, oldkey->path);
thiskey->values = talloc_realloc(diff, thiskey->values, struct reg_diff_value, thiskey->numvalues+2);
thiskey->values[thiskey->numvalues].name = talloc_strdup(thiskey->values, v1->name);
thiskey->values[thiskey->numvalues].type = v2->data_type;
thiskey->values[thiskey->numvalues].changetype = REG_DIFF_SET_VAL;
thiskey->values[thiskey->numvalues].data = data_blob_dup_talloc(thiskey->values, &v2->data);
thiskey->numvalues++;
}
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1)));
talloc_free(mem_ctx);
return error1;
}
/* Values that were deleted */
for(i = 0; W_ERROR_IS_OK(error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &v1)); i++) {
struct reg_diff_key *thiskey = NULL;
error2 = reg_key_get_value_by_name(mem_ctx, newkey, v1->name, &v2);
if (W_ERROR_IS_OK(error2))
continue;
if (!W_ERROR_EQUAL(error2, WERR_DEST_NOT_FOUND)) {
DEBUG(0, ("Error occured while getting value by name: %d\n", W_ERROR_V(error2)));
return error2;
}
thiskey = diff_find_add_key(diff, oldkey->path);
thiskey->values = talloc_realloc(diff, thiskey->values, struct reg_diff_value, thiskey->numvalues+2);
thiskey->values[thiskey->numvalues].name = talloc_strdup(thiskey->values, v1->name);
thiskey->values[thiskey->numvalues].changetype = REG_DIFF_DEL_VAL;
thiskey->numvalues++;
}
if(!W_ERROR_EQUAL(error1, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while getting value by index: %d\n", W_ERROR_V(error1)));
talloc_free(mem_ctx);
return error1;
}
talloc_free(mem_ctx);
return WERR_OK;
}
/**
* Generate diff between two registry contexts
*/
_PUBLIC_ struct reg_diff *reg_generate_diff(TALLOC_CTX *mem_ctx, struct registry_context *ctx1, struct registry_context *ctx2)
{
struct reg_diff *diff = talloc_zero(mem_ctx, struct reg_diff);
int i;
WERROR error;
for(i = HKEY_CLASSES_ROOT; i <= HKEY_PERFORMANCE_NLSTEXT; i++) {
struct registry_key *r1, *r2;
error = reg_get_predefined_key(ctx1, i, &r1);
if (!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Unable to open hive %s for backend 1\n", reg_get_predef_name(i)));
continue;
}
error = reg_get_predefined_key(ctx2, i, &r2);
if (!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Unable to open hive %s for backend 2\n", reg_get_predef_name(i)));
continue;
}
reg_generate_diff_key(diff, r1, r2);
}
return diff;
}
/**
* Save registry diff
*/
_PUBLIC_ WERROR reg_diff_save(const struct reg_diff *diff, const char *filename)
{
int xf, i, j;
if (filename) {
xf = open(filename, O_CREAT, 0755);
if (xf == -1) {
DEBUG(0, ("Unable to open %s\n", filename));
return WERR_BADFILE;
}
} else
xf = STDIN_FILENO;
fdprintf(xf, "%s\n\n", diff->format?diff->format:DEFAULT_IDENT_STRING);
for (i = 0; i < diff->numkeys; i++) {
if (diff->keys[i].changetype == REG_DIFF_DEL_KEY) {
fdprintf(xf, "-%s\n\n", diff->keys[i].name);
continue;
}
fdprintf(xf, "[%s]\n", diff->keys[i].name);
for (j = 0; j < diff->keys[i].numvalues; j++) {
fdprintf(xf, "\"%s\"=", diff->keys[i].values[j].name);
switch (diff->keys[i].values[j].changetype) {
case REG_DIFF_DEL_VAL:
fdprintf(xf, "-\n");
break;
case REG_DIFF_SET_VAL:
fdprintf(xf, "%s:%s\n",
str_regtype(diff->keys[i].values[j].type),
reg_val_data_string(NULL,
diff->keys[i].values[j].type,
&diff->keys[i].values[j].data));
break;
}
}
fdprintf(xf, "\n");
}
close(xf);
return WERR_OK;
}
/**
* Load diff file
*/
_PUBLIC_ struct reg_diff *reg_diff_load(TALLOC_CTX *ctx, const char *fn)
{
struct reg_diff *diff;
int fd;
char *line, *p, *q;
struct reg_diff_key *curkey = NULL;
struct reg_diff_value *curval;
fd = open(fn, O_RDONLY, 0);
if (fd == -1) {
DEBUG(0, ("Error opening registry patch file `%s'\n", fn));
return NULL;
}
diff = talloc_zero(ctx, struct reg_diff);
if (diff == NULL) {
close(fd);
return NULL;
}
diff->format = afdgets(fd, diff, 0);
if (!diff->format) {
talloc_free(diff);
close(fd);
return NULL;
}
while ((line = afdgets(fd, diff, 0))) {
/* Ignore comments and empty lines */
if (strlen(line) == 0 || line[0] == ';') {
curkey = NULL;
talloc_free(line);
continue;
}
/* Start of key */
if (line[0] == '[') {
p = strchr_m(line, ']');
if (p[strlen(p)-2] != ']') {
DEBUG(0, ("Malformed line\n"));
return NULL;
}
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
diff->keys[diff->numkeys].name = talloc_strndup(diff->keys, line+1, strlen(line)-2);
diff->keys[diff->numkeys].changetype = REG_DIFF_CHANGE_KEY;
diff->keys[diff->numkeys].numvalues = 0;
diff->keys[diff->numkeys].values = NULL;
curkey = &diff->keys[diff->numkeys];
diff->numkeys++;
talloc_free(line);
continue;
}
/* Deleting key */
if (line[0] == '-') {
diff->keys = talloc_realloc(diff, diff->keys, struct reg_diff_key, diff->numkeys+2);
diff->keys[diff->numkeys].name = talloc_strdup(diff->keys, line+1);
diff->keys[diff->numkeys].changetype = REG_DIFF_DEL_KEY;
diff->numkeys++;
talloc_free(line);
continue;
}
/* Deleting/Changing value */
p = strchr_m(line, '=');
if (p == NULL) {
DEBUG(0, ("Malformed line\n"));
talloc_free(line);
continue;
}
*p = '\0'; p++;
if (curkey == NULL) {
DEBUG(0, ("Value change without key\n"));
talloc_free(line);
continue;
}
curkey->values = talloc_realloc(diff->keys, curkey->values, struct reg_diff_value, curkey->numvalues+2);
curval = &curkey->values[curkey->numvalues];
curkey->numvalues++;
curval->name = talloc_strdup(curkey->values, line);
/* Delete value */
if (strcmp(p, "-")) {
curval->changetype = REG_DIFF_DEL_VAL;
talloc_free(line);
continue;
}
q = strchr_m(p, ':');
if (q) {
*q = '\0';
q++;
}
curval->changetype = REG_DIFF_SET_VAL;
reg_string_to_val(curkey->values, q?p:"REG_SZ", q?q:p, &curval->type, &curval->data);
talloc_free(line);
}
close(fd);
return diff;
}
/**
* Apply diff to a registry context
*/
_PUBLIC_ BOOL reg_diff_apply (const struct reg_diff *diff, struct registry_context *ctx)
{
TALLOC_CTX *mem_ctx = talloc_init("apply_cmd_file");
struct registry_key *tmp = NULL;
WERROR error;
int i, j;
for (i = 0; i < diff->numkeys; i++) {
if (diff->keys[i].changetype == REG_DIFF_DEL_KEY) {
error = reg_key_del_abs(ctx, diff->keys[i].name);
if(!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Unable to delete key '%s'\n", diff->keys[i].name));
return False;
}
continue;
}
/* Add / change key */
error = reg_open_key_abs(mem_ctx, ctx, diff->keys[i].name, &tmp);
/* 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_abs(mem_ctx, ctx, diff->keys[i].name, 0, NULL, &tmp))) {
DEBUG(0, ("Error adding new key '%s'\n", diff->keys[i].name));
return False;
}
}
for (j = 0; j < diff->keys[i].numvalues; j++) {
if (diff->keys[i].values[j].changetype == REG_DIFF_DEL_VAL) {
error = reg_del_value(tmp, diff->keys[i].values[j].name);
if (!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Error deleting value '%s'\n", diff->keys[i].values[j].name));
return False;
}
error = reg_val_set(tmp, diff->keys[i].values[j].name,
diff->keys[i].values[j].type,
diff->keys[i].values[j].data);
if (!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Error setting value '%s'\n", diff->keys[i].values[j].name));
return False;
}
}
}
}
return True;
}
+142
View File
@@ -0,0 +1,142 @@
/*
Unix SMB/CIFS implementation.
Registry interface
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"
#include "system/dir.h"
#include "system/filesys.h"
static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *desc, struct registry_key **result)
{
char *path;
int ret;
asprintf(&path, "%s%s\\%s", parent->hive->location, parent->path, name);
path = reg_path_win2unix(path);
ret = mkdir(path, 0700);
SAFE_FREE(path);
if(ret == 0)return WERR_OK; /* FIXME */
return WERR_INVALID_PARAM;
}
static WERROR reg_dir_del_key(const struct registry_key *k, const char *name)
{
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_free(child);
return ret;
}
static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *p, const char *name, struct registry_key **subkey)
{
DIR *d;
char *fullpath, *unixpath;
struct registry_key *ret;
if(!name) {
DEBUG(0, ("NULL pointer passed as directory name!"));
return WERR_INVALID_PARAM;
}
fullpath = talloc_asprintf(mem_ctx, "%s/%s", (char *)p->backend_data, name);
unixpath = reg_path_win2unix(fullpath);
d = opendir(unixpath);
if(!d) {
DEBUG(3,("Unable to open '%s': %s\n", unixpath, strerror(errno)));
return WERR_BADFILE;
}
closedir(d);
ret = talloc(mem_ctx, struct registry_key);
ret->hive = p->hive;
ret->path = fullpath;
ret->backend_data = unixpath;
*subkey = ret;
return WERR_OK;
}
static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **key)
{
struct dirent *e;
char *fullpath = k->backend_data;
int i = 0;
DIR *d;
d = opendir(fullpath);
if(!d) return WERR_INVALID_PARAM;
while((e = readdir(d))) {
if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
struct stat stbuf;
char *thispath;
/* Check if file is a directory */
asprintf(&thispath, "%s/%s", fullpath, e->d_name);
stat(thispath, &stbuf);
if(S_ISDIR(stbuf.st_mode)) {
if(i == idx) {
(*key) = talloc(mem_ctx, struct registry_key);
(*key)->name = talloc_strdup(*key, e->d_name);
(*key)->path = NULL;
(*key)->backend_data = talloc_strdup(*key, thispath);
SAFE_FREE(thispath);
closedir(d);
return WERR_OK;
}
i++;
}
SAFE_FREE(thispath);
}
}
closedir(d);
return WERR_NO_MORE_ITEMS;
}
static WERROR reg_dir_open(struct registry_hive *h, struct registry_key **key)
{
if(!h->location) return WERR_INVALID_PARAM;
*key = talloc(h, struct registry_key);
(*key)->backend_data = talloc_strdup(*key, h->location);
return WERR_OK;
}
static struct hive_operations reg_backend_dir = {
.name = "dir",
.open_hive = reg_dir_open,
.open_key = reg_dir_open_key,
.add_key = reg_dir_add_key,
.del_key = reg_dir_del_key,
.get_subkey_by_index = reg_dir_key_by_index
};
NTSTATUS registry_dir_init(void)
{
return registry_register(&reg_backend_dir);
}
@@ -0,0 +1,197 @@
/*
Unix SMB/CIFS implementation.
Registry interface
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"
#include <gconf/gconf-client.h>
static WERROR gerror_to_werror(GError *error)
{
if(error == NULL) return WERR_OK;
/* FIXME */
return WERR_FOOBAR;
}
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(h, struct registry_key);
(*k)->name = talloc_strdup(*k, "");
(*k)->path = talloc_strdup(*k, "");
(*k)->backend_data = talloc_strdup(*k, "/");
return WERR_OK;
}
static WERROR gconf_open_key (TALLOC_CTX *mem_ctx, struct registry_key *h, const char *name, struct registry_key **key)
{
struct registry_key *ret;
char *fullpath;
fullpath = talloc_asprintf(mem_ctx, "%s%s%s",
(char *)h->backend_data,
strlen((char *)h->backend_data) == 1?"":"/",
reg_path_win2unix(talloc_strdup(mem_ctx, name)));
/* Check if key exists */
if(!gconf_client_dir_exists((GConfClient *)h->hive->backend_data, fullpath, NULL)) {
return WERR_DEST_NOT_FOUND;
}
ret = talloc(mem_ctx, struct registry_key);
ret->backend_data = fullpath;
*key = ret;
return WERR_OK;
}
static WERROR gconf_get_value_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_value **val)
{
GSList *entries;
GSList *cur;
GConfEntry *entry;
GConfValue *value;
struct registry_value *newval;
char *fullpath = p->backend_data;
const char *tmp;
int i;
cur = entries = gconf_client_all_entries((GConfClient*)p->hive->backend_data, fullpath, NULL);
for(i = 0; i < idx && cur; i++) cur = cur->next;
if(!cur) return WERR_NO_MORE_ITEMS;
entry = cur->data;
value = gconf_entry_get_value(entry);
newval = talloc(mem_ctx, struct registry_value);
newval->name = talloc_strdup(mem_ctx, strrchr(gconf_entry_get_key(entry), '/')+1);
if(value) {
switch(value->type) {
case GCONF_VALUE_INVALID:
newval->data_type = REG_NONE;
break;
case GCONF_VALUE_STRING:
newval->data_type = REG_SZ;
tmp = gconf_value_get_string(value);
newval->data_len = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, tmp, strlen(tmp), &(newval->data_blk));
break;
case GCONF_VALUE_INT:
newval->data_type = REG_DWORD;
newval->data_blk = talloc(mem_ctx, long);
*((long *)newval->data_blk) = gconf_value_get_int(value);
newval->data_len = sizeof(long);
break;
case GCONF_VALUE_FLOAT:
newval->data_blk = talloc(mem_ctx, double);
newval->data_type = REG_BINARY;
*((double *)newval->data_blk) = gconf_value_get_float(value);
newval->data_len = sizeof(double);
break;
case GCONF_VALUE_BOOL:
newval->data_blk = talloc(mem_ctx, BOOL);
newval->data_type = REG_BINARY;
*((BOOL *)newval->data_blk) = gconf_value_get_bool(value);
newval->data_len = sizeof(BOOL);
break;
default:
newval->data_type = REG_NONE;
DEBUG(0, ("Not implemented..\n"));
break;
}
} else newval->data_type = REG_NONE;
g_slist_free(entries);
*val = newval;
return WERR_OK;
}
static WERROR gconf_get_subkey_by_id(TALLOC_CTX *mem_ctx, struct registry_key *p, int idx, struct registry_key **sub)
{
GSList *dirs;
GSList *cur;
int i;
char *fullpath = p->backend_data;
cur = dirs = gconf_client_all_dirs((GConfClient*)p->hive->backend_data, fullpath,NULL);
for(i = 0; i < idx && cur; i++) cur = cur->next;
if(!cur) return WERR_NO_MORE_ITEMS;
*sub = talloc(mem_ctx, struct registry_key);
(*sub)->name = talloc_strdup(mem_ctx, strrchr((char *)cur->data, '/')+1);
(*sub)->backend_data = talloc_strdup(mem_ctx, cur->data);
g_slist_free(dirs);
return WERR_OK;
}
static WERROR gconf_set_value(struct registry_key *key, const char *valname, uint32_t type, void *data, int len)
{
GError *error = NULL;
char *valpath;
asprintf(&valpath, "%s/%s", key->path, valname);
switch(type) {
case REG_SZ:
case REG_EXPAND_SZ:
gconf_client_set_string((GConfClient *)key->hive->backend_data, valpath, data, &error);
SAFE_FREE(valpath);
return gerror_to_werror(error);
case REG_DWORD:
gconf_client_set_int((GConfClient *)key->hive->backend_data, valpath,
*((int *)data), &error);
SAFE_FREE(valpath);
return gerror_to_werror(error);
default:
DEBUG(0, ("Unsupported type: %d\n", type));
SAFE_FREE(valpath);
return WERR_NOT_SUPPORTED;
}
return WERR_NOT_SUPPORTED;
}
static struct hive_operations reg_backend_gconf = {
.name = "gconf",
.open_hive = reg_open_gconf_hive,
.open_key = gconf_open_key,
.get_subkey_by_index = gconf_get_subkey_by_id,
.get_value_by_index = gconf_get_value_by_id,
.set_value = gconf_set_value,
/* Note:
* since GConf uses schemas for what keys and values are allowed, there
* is no way of 'emulating' add_key and del_key here.
*/
};
NTSTATUS registry_gconf_init(void)
{
return registry_register(&reg_backend_gconf);
}
+406
View File
@@ -0,0 +1,406 @@
/*
Unix SMB/CIFS implementation.
Registry interface
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"
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
#include "db_wrap.h"
#include "librpc/gen_ndr/winreg.h"
struct ldb_key_data
{
struct ldb_dn *dn;
struct ldb_message **subkeys, **values;
int subkey_count, value_count;
};
static int ldb_free_hive (struct registry_hive *hive)
{
talloc_free(hive->backend_data);
hive->backend_data = NULL;
return 0;
}
static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char **name, uint32_t *type, DATA_BLOB *data)
{
const struct ldb_val *val;
*name = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(msg, "value", NULL));
*type = ldb_msg_find_attr_as_uint(msg, "type", 0);
val = ldb_msg_find_ldb_val(msg, "data");
switch (*type)
{
case REG_SZ:
case REG_EXPAND_SZ:
data->length = convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, val->data, val->length, (void **)&data->data);
break;
case REG_DWORD: {
uint32_t tmp = strtoul((char *)val->data, NULL, 0);
*data = data_blob_talloc(mem_ctx, &tmp, 4);
}
break;
default:
*data = data_blob_talloc(mem_ctx, val->data, val->length);
break;
}
}
static struct ldb_message *reg_ldb_pack_value(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, const char *name, uint32_t type, DATA_BLOB data)
{
struct ldb_val val;
struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message);
char *type_s;
ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name));
switch (type) {
case REG_SZ:
case REG_EXPAND_SZ:
val.length = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, (void *)data.data, data.length, (void **)&val.data);
ldb_msg_add_value(msg, "data", &val, NULL);
break;
case REG_DWORD:
ldb_msg_add_string(msg, "data", talloc_asprintf(mem_ctx, "0x%x", IVAL(data.data, 0)));
break;
default:
ldb_msg_add_value(msg, "data", &data, NULL);
}
type_s = talloc_asprintf(mem_ctx, "%u", type);
ldb_msg_add_string(msg, "type", type_s);
return msg;
}
static int reg_close_ldb_key(struct registry_key *key)
{
struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
/* struct ldb_context *c = key->hive->backend_data; */
if (kd->subkeys) {
talloc_free(kd->subkeys);
kd->subkeys = NULL;
}
if (kd->values) {
talloc_free(kd->values);
kd->values = NULL;
}
return 0;
}
static struct ldb_dn *reg_path_to_ldb(TALLOC_CTX *mem_ctx, const struct registry_key *from, const char *path, const char *add)
{
TALLOC_CTX *local_ctx;
struct ldb_dn *ret;
char *mypath = talloc_strdup(mem_ctx, path);
char *begin;
struct ldb_key_data *kd = talloc_get_type(from->backend_data, struct ldb_key_data);
struct ldb_context *ldb = talloc_get_type(from->hive->backend_data, struct ldb_context);
local_ctx = talloc_new(mem_ctx);
if (add) {
ret = ldb_dn_new(mem_ctx, ldb, add);
} else {
ret = ldb_dn_new(mem_ctx, ldb, NULL);
}
if ( ! ldb_dn_validate(ret)) {
talloc_free(ret);
talloc_free(local_ctx);
return NULL;
}
while(mypath) {
char *keyname;
begin = strrchr(mypath, '\\');
if (begin) keyname = begin + 1;
else keyname = mypath;
if(strlen(keyname)) {
ldb_dn_add_base_fmt(ret, "key=%s", keyname);
}
if(begin) {
*begin = '\0';
} else {
break;
}
}
ldb_dn_add_base(ret, kd->dn);
talloc_free(local_ctx);
return ret;
}
static WERROR ldb_get_subkey_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_key **subkey)
{
struct ldb_context *c = talloc_get_type(k->hive->backend_data, struct ldb_context);
struct ldb_message_element *el;
struct ldb_key_data *kd = talloc_get_type(k->backend_data, struct ldb_key_data);
struct ldb_key_data *newkd;
/* Do a search if necessary */
if (kd->subkeys == NULL) {
struct ldb_result *res;
int ret;
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(key=*)", NULL, &res);
if (ret != LDB_SUCCESS) {
DEBUG(0, ("Error getting subkeys for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
return WERR_FOOBAR;
}
kd->subkey_count = res->count;
kd->subkeys = talloc_steal(kd, res->msgs);
talloc_free(res);
}
if (idx >= kd->subkey_count) return WERR_NO_MORE_ITEMS;
el = ldb_msg_find_element(kd->subkeys[idx], "key");
*subkey = talloc(mem_ctx, struct registry_key);
talloc_set_destructor(*subkey, reg_close_ldb_key);
(*subkey)->name = talloc_strdup(mem_ctx, (char *)el->values[0].data);
(*subkey)->backend_data = newkd = talloc_zero(*subkey, struct ldb_key_data);
(*subkey)->last_mod = 0; /* TODO: we need to add this to the
ldb backend properly */
newkd->dn = ldb_dn_copy(mem_ctx, kd->subkeys[idx]->dn);
return WERR_OK;
}
static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value)
{
struct ldb_context *c = talloc_get_type(k->hive->backend_data, struct ldb_context);
struct ldb_key_data *kd = talloc_get_type(k->backend_data, struct ldb_key_data);
/* Do the search if necessary */
if (kd->values == NULL) {
struct ldb_result *res;
int ret;
ret = ldb_search(c, kd->dn, LDB_SCOPE_ONELEVEL, "(value=*)", NULL, &res);
if (ret != LDB_SUCCESS) {
DEBUG(0, ("Error getting values for '%s': %s\n", ldb_dn_get_linearized(kd->dn), ldb_errstring(c)));
return WERR_FOOBAR;
}
kd->value_count = res->count;
kd->values = talloc_steal(kd, res->msgs);
talloc_free(res);
}
if(idx >= kd->value_count) return WERR_NO_MORE_ITEMS;
*value = talloc(mem_ctx, struct registry_value);
reg_ldb_unpack_value(mem_ctx, kd->values[idx], &(*value)->name, &(*value)->data_type, &(*value)->data);
return WERR_OK;
}
static WERROR ldb_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
{
struct ldb_context *c = talloc_get_type(h->hive->backend_data, struct ldb_context);
struct ldb_result *res;
struct ldb_dn *ldap_path;
int ret;
struct ldb_key_data *newkd;
ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL);
ret = ldb_search(c, ldap_path, LDB_SCOPE_BASE, "(key=*)", NULL, &res);
if (ret != LDB_SUCCESS) {
DEBUG(0, ("Error opening key '%s': %s\n", ldb_dn_get_linearized(ldap_path), ldb_errstring(c)));
return WERR_FOOBAR;
} else if (res->count == 0) {
talloc_free(res);
return WERR_BADFILE;
}
*key = talloc(mem_ctx, struct registry_key);
talloc_set_destructor(*key, reg_close_ldb_key);
(*key)->name = talloc_strdup(mem_ctx, strrchr(name, '\\')?strchr(name, '\\'):name);
(*key)->backend_data = newkd = talloc_zero(*key, struct ldb_key_data);
newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn);
talloc_free(res);
return WERR_OK;
}
static WERROR ldb_open_hive(struct registry_hive *hive, struct registry_key **k)
{
struct ldb_key_data *kd;
struct ldb_context *wrap;
if (!hive->location) return WERR_INVALID_PARAM;
wrap = ldb_wrap_connect(hive, hive->location, hive->session_info, hive->credentials, 0, NULL);
if(!wrap) {
DEBUG(1, ("ldb_open_hive: unable to connect\n"));
return WERR_FOOBAR;
}
ldb_set_debug_stderr(wrap);
hive->backend_data = wrap;
*k = talloc_zero(hive, struct registry_key);
talloc_set_destructor (*k, reg_close_ldb_key);
talloc_set_destructor (hive, ldb_free_hive);
(*k)->name = talloc_strdup(*k, "");
(*k)->backend_data = kd = talloc_zero(*k, struct ldb_key_data);
kd->dn = ldb_dn_new(*k, wrap, "hive=NONE");
return WERR_OK;
}
static WERROR ldb_add_key (TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sd, struct registry_key **newkey)
{
struct ldb_context *ctx = talloc_get_type(parent->hive->backend_data, struct ldb_context);
struct ldb_message *msg;
struct ldb_key_data *newkd;
int ret;
msg = ldb_msg_new(mem_ctx);
msg->dn = reg_path_to_ldb(msg, parent, name, NULL);
ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name));
ret = ldb_add(ctx, msg);
if (ret < 0) {
DEBUG(1, ("ldb_msg_add: %s\n", ldb_errstring(ctx)));
return WERR_FOOBAR;
}
*newkey = talloc_zero(mem_ctx, struct registry_key);
(*newkey)->name = talloc_strdup(mem_ctx, name);
(*newkey)->backend_data = newkd = talloc_zero(*newkey, struct ldb_key_data);
newkd->dn = talloc_steal(newkd, msg->dn);
return WERR_OK;
}
static WERROR ldb_del_key (const struct registry_key *key, const char *child)
{
struct ldb_context *ctx = talloc_get_type(key->hive->backend_data, struct ldb_context);
int ret;
struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
struct ldb_dn *childdn;
childdn = ldb_dn_copy(ctx, kd->dn);
ldb_dn_add_child_fmt(childdn, "key=%s", child);
ret = ldb_delete(ctx, childdn);
talloc_free(childdn);
if (ret < 0) {
DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(ctx)));
return WERR_FOOBAR;
}
return WERR_OK;
}
static WERROR ldb_del_value (const struct registry_key *key, const char *child)
{
int ret;
struct ldb_context *ctx = talloc_get_type(key->hive->backend_data, struct ldb_context);
struct ldb_key_data *kd = talloc_get_type(key->backend_data, struct ldb_key_data);
struct ldb_dn *childdn;
childdn = ldb_dn_copy(ctx, kd->dn);
ldb_dn_add_child_fmt(childdn, "value=%s", child);
ret = ldb_delete(ctx, childdn);
talloc_free(childdn);
if (ret < 0) {
DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(ctx)));
return WERR_FOOBAR;
}
return WERR_OK;
}
static WERROR ldb_set_value (const struct registry_key *parent, const char *name, uint32_t type, DATA_BLOB data)
{
struct ldb_context *ctx = talloc_get_type(parent->hive->backend_data, struct ldb_context);
struct ldb_message *msg;
struct ldb_key_data *kd = talloc_get_type(parent->backend_data, struct ldb_key_data);
int ret;
TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value");
msg = reg_ldb_pack_value(ctx, mem_ctx, name, type, data);
msg->dn = ldb_dn_copy(msg, kd->dn);
ldb_dn_add_child_fmt(msg->dn, "value=%s", name);
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(ctx)));
talloc_free(mem_ctx);
return WERR_FOOBAR;
}
}
talloc_free(mem_ctx);
return WERR_OK;
}
static struct hive_operations reg_backend_ldb = {
.name = "ldb",
.add_key = ldb_add_key,
.del_key = ldb_del_key,
.open_hive = ldb_open_hive,
.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)
{
return registry_register(&reg_backend_ldb);
}
File diff suppressed because it is too large Load Diff
+395
View File
@@ -0,0 +1,395 @@
/*
Samba Unix/Linux SMB implementation
RPC backend for the registry library
Copyright (C) 2003-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. */
#include "includes.h"
#include "registry.h"
#include "librpc/gen_ndr/ndr_winreg_c.h"
static struct hive_operations reg_backend_rpc;
/**
* This is the RPC backend for the registry library.
*/
static void init_winreg_String(struct winreg_String *name, const char *s)
{
name->name = s;
}
#define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \
{ \
struct winreg_Open ## u r; \
NTSTATUS status; \
\
r.in.system_name = NULL; \
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \
r.out.handle = hnd;\
\
status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \
if (NT_STATUS_IS_ERR(status)) {\
DEBUG(0,("Error executing open\n"));\
return ntstatus_to_werror(status);\
}\
\
return r.out.result;\
}
openhive(HKLM)
openhive(HKCU)
openhive(HKPD)
openhive(HKU)
openhive(HKCR)
openhive(HKDD)
openhive(HKCC)
struct rpc_key_data {
struct policy_handle pol;
int num_subkeys;
int num_values;
int max_valnamelen;
int max_valdatalen;
};
static struct {
uint32_t 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 },
{ 0, NULL }
};
static WERROR rpc_query_key(const struct registry_key *k);
static WERROR rpc_get_predefined_key (struct registry_context *ctx, uint32_t hkey_type, struct registry_key **k)
{
int n;
struct registry_hive *h;
struct rpc_key_data *mykeydata;
for(n = 0; known_hives[n].hkey; n++)
{
if(known_hives[n].hkey == hkey_type) break;
}
if(!known_hives[n].open) {
DEBUG(1, ("No such hive %d\n", hkey_type));
return WERR_NO_MORE_ITEMS;
}
h = talloc(ctx, struct registry_hive);
h->functions = &reg_backend_rpc;
h->location = NULL;
h->backend_data = ctx->backend_data;
(*k) = h->root = talloc(h, struct registry_key);
(*k)->hive = h;
(*k)->backend_data = mykeydata = talloc(*k, struct rpc_key_data);
mykeydata->num_values = -1;
mykeydata->num_subkeys = -1;
return known_hives[n].open((struct dcerpc_pipe *)ctx->backend_data, *k, &(mykeydata->pol));
}
#if 0
static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k)
{
struct winreg_OpenKey r;
struct rpc_key_data *mykeydata;
k->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data);
mykeydata->num_values = -1;
mykeydata->num_subkeys = -1;
/* Then, open the handle using the hive */
memset(&r, 0, sizeof(struct winreg_OpenKey));
r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol);
init_winreg_String(&r.in.keyname, k->path);
r.in.unknown = 0x00000000;
r.in.access_mask = 0x02000000;
r.out.handle = &mykeydata->pol;
dcerpc_winreg_OpenKey((struct dcerpc_pipe *)k->hive->backend_data, mem_ctx, &r);
return r.out.result;
}
#endif
static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, const struct registry_key *h, const char *name, struct registry_key **key)
{
struct rpc_key_data *mykeydata;
struct winreg_OpenKey r;
*key = talloc(mem_ctx, struct registry_key);
(*key)->name = talloc_strdup(mem_ctx, name);
(*key)->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data);
mykeydata->num_values = -1;
mykeydata->num_subkeys = -1;
/* Then, open the handle using the hive */
memset(&r, 0, sizeof(struct winreg_OpenKey));
r.in.parent_handle = &(((struct rpc_key_data *)h->backend_data)->pol);
init_winreg_String(&r.in.keyname, name);
r.in.unknown = 0x00000000;
r.in.access_mask = 0x02000000;
r.out.handle = &mykeydata->pol;
dcerpc_winreg_OpenKey((struct dcerpc_pipe *)(h->hive->backend_data), mem_ctx, &r);
return r.out.result;
}
static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_value **value)
{
struct rpc_key_data *mykeydata = parent->backend_data;
WERROR error;
struct winreg_EnumValue r;
uint32_t len1, zero = 0;
enum winreg_Type type;
NTSTATUS status;
struct winreg_StringBuf name;
uint8_t u8;
if(mykeydata->num_values == -1) {
error = rpc_query_key(parent);
if(!W_ERROR_IS_OK(error)) return error;
}
len1 = mykeydata->max_valdatalen;
name.length = 0;
name.size = mykeydata->max_valnamelen * 2;
name.name = "";
r.in.handle = &mykeydata->pol;
r.in.enum_index = n;
r.in.name = &name;
r.in.type = &type;
r.in.value = &u8;
r.in.length = &zero;
r.in.size = &len1;
r.out.name = &name;
status = dcerpc_winreg_EnumValue((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
if(NT_STATUS_IS_ERR(status)) {
DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status)));
return WERR_GENERAL_FAILURE;
}
if(NT_STATUS_IS_OK(status) &&
W_ERROR_IS_OK(r.out.result) && r.out.length) {
*value = talloc(mem_ctx, struct registry_value);
(*value)->name = talloc_strdup(mem_ctx, r.out.name->name);
(*value)->data_type = type;
(*value)->data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length);
return WERR_OK;
}
return r.out.result;
}
static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **subkey)
{
struct winreg_EnumKey r;
struct rpc_key_data *mykeydata = parent->backend_data;
NTSTATUS status;
struct winreg_StringBuf namebuf, classbuf;
NTTIME change_time = 0;
namebuf.length = 0;
namebuf.size = 1024;
namebuf.name = NULL;
classbuf.length = 0;
classbuf.size = 0;
classbuf.name = NULL;
r.in.handle = &mykeydata->pol;
r.in.enum_index = n;
r.in.name = &namebuf;
r.in.keyclass = &classbuf;
r.in.last_changed_time = &change_time;
r.out.name = &namebuf;
status = dcerpc_winreg_EnumKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
char *name = talloc_strdup(mem_ctx, r.out.name->name);
return rpc_open_key(mem_ctx, parent, name, subkey);
}
return r.out.result;
}
static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, const struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec, struct registry_key **key)
{
NTSTATUS status;
struct winreg_CreateKey r;
init_winreg_String(&r.in.name, name);
init_winreg_String(&r.in.keyclass, NULL);
r.in.handle = parent->backend_data;
r.out.new_handle = talloc(mem_ctx, struct policy_handle);
r.in.options = 0;
r.in.access_mask = access_mask;
r.in.secdesc = NULL;
status = dcerpc_winreg_CreateKey((struct dcerpc_pipe *)(parent->hive->backend_data), mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("CreateKey failed - %s\n", nt_errstr(status)));
return ntstatus_to_werror(status);
}
if (W_ERROR_IS_OK(r.out.result)) {
*key = talloc(mem_ctx, struct registry_key);
(*key)->name = talloc_strdup(*key, name);
(*key)->backend_data = r.out.new_handle;
}
return r.out.result;
}
static WERROR rpc_query_key(const struct registry_key *k)
{
NTSTATUS status;
struct winreg_QueryInfoKey r;
struct rpc_key_data *mykeydata = k->backend_data;
TALLOC_CTX *mem_ctx = talloc_init("query_key");
init_winreg_String(&r.in.class_in, NULL);
r.in.handle = &mykeydata->pol;
status = dcerpc_winreg_QueryInfoKey((struct dcerpc_pipe *)(k->hive->backend_data), mem_ctx, &r);
talloc_free(mem_ctx);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status)));
return ntstatus_to_werror(status);
}
if (W_ERROR_IS_OK(r.out.result)) {
mykeydata->num_subkeys = *r.out.num_subkeys;
mykeydata->num_values = *r.out.num_values;
mykeydata->max_valnamelen = *r.out.max_valnamelen;
mykeydata->max_valdatalen = *r.out.max_valbufsize;
}
return r.out.result;
}
static WERROR rpc_del_key(const struct registry_key *parent, const char *name)
{
NTSTATUS status;
struct rpc_key_data *mykeydata = parent->backend_data;
struct winreg_DeleteKey r;
TALLOC_CTX *mem_ctx = talloc_init("del_key");
r.in.handle = &mykeydata->pol;
init_winreg_String(&r.in.key, name);
status = dcerpc_winreg_DeleteKey((struct dcerpc_pipe *)parent->hive->backend_data, mem_ctx, &r);
talloc_free(mem_ctx);
return r.out.result;
}
static WERROR rpc_num_values(const struct registry_key *key, uint32_t *count)
{
struct rpc_key_data *mykeydata = key->backend_data;
WERROR error;
if(mykeydata->num_values == -1) {
error = rpc_query_key(key);
if(!W_ERROR_IS_OK(error)) return error;
}
*count = mykeydata->num_values;
return WERR_OK;
}
static WERROR rpc_num_subkeys(const struct registry_key *key, uint32_t *count)
{
struct rpc_key_data *mykeydata = key->backend_data;
WERROR error;
if(mykeydata->num_subkeys == -1) {
error = rpc_query_key(key);
if(!W_ERROR_IS_OK(error)) return error;
}
*count = mykeydata->num_subkeys;
return WERR_OK;
}
static struct hive_operations reg_backend_rpc = {
.name = "rpc",
.open_key = rpc_open_key,
.get_subkey_by_index = rpc_get_subkey_by_index,
.get_value_by_index = rpc_get_value_by_index,
.add_key = rpc_add_key,
.del_key = rpc_del_key,
.num_subkeys = rpc_num_subkeys,
.num_values = rpc_num_values,
};
_PUBLIC_ WERROR reg_open_remote(struct registry_context **ctx, struct auth_session_info *session_info, struct cli_credentials *credentials,
const char *location, struct event_context *ev)
{
NTSTATUS status;
struct dcerpc_pipe *p;
*ctx = talloc(NULL, struct registry_context);
/* Default to local smbd if no connection is specified */
if (!location) {
location = talloc_strdup(ctx, "ncalrpc:");
}
status = dcerpc_pipe_connect(*ctx /* TALLOC_CTX */,
&p, location,
&dcerpc_table_winreg,
credentials, ev);
(*ctx)->backend_data = p;
if(NT_STATUS_IS_ERR(status)) {
DEBUG(1, ("Unable to open '%s': %s\n", location, nt_errstr(status)));
talloc_free(*ctx);
*ctx = NULL;
return ntstatus_to_werror(status);
}
(*ctx)->get_predefined_key = rpc_get_predefined_key;
return WERR_OK;
}
NTSTATUS registry_rpc_init(void)
{
dcerpc_init();
return registry_register(&reg_backend_rpc);
}
+357
View File
@@ -0,0 +1,357 @@
/*
Samba Unix/Linux SMB client utility libeditreg.c
Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
Backend for Windows '95 registry files. Explanation of file format
comes from http://www.cs.mun.ca/~michael/regutils/.
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"
#include "system/filesys.h"
#include "system/shmem.h"
/**
* The registry starts with a header that contains pointers to
* the rgdb.
*
* After the main header follows the RGKN header (key index table).
* The RGKN keys are listed after each other. They are put into
* blocks, the first having a length of 0x2000 bytes, the others
* being 0x1000 bytes long.
*
* After the RGKN header follow one or more RGDB blocks. These blocks
* contain keys. A key is followed by its name and its values.
*
* Values are followed by their name and then their data.
*
* Basically the idea is that the RGKN contains the associations between
* the keys and the RGDB contains the actual data.
*/
typedef uint32_t DWORD;
typedef unsigned short WORD;
typedef struct creg_block {
DWORD CREG_ID; /* CREG */
DWORD uk1;
DWORD rgdb_offset;
DWORD chksum;
WORD num_rgdb;
WORD flags;
DWORD uk2;
DWORD uk3;
DWORD uk4;
} CREG_HDR;
typedef struct rgkn_block {
DWORD RGKN_ID; /* RGKN */
DWORD size;
DWORD root_offset;
DWORD free_offset;
DWORD flags;
DWORD chksum;
DWORD uk1;
DWORD uk2;
} RGKN_HDR;
typedef struct reg_id {
WORD id;
WORD rgdb;
} REG_ID;
typedef struct rgkn_key {
DWORD type; /* 0x00000000 = normal key, 0x80000000 = free block */
DWORD hash; /* Contains either hash or size of free blocks that follows */
DWORD next_free;
DWORD parent_offset;
DWORD first_child_offset;
DWORD next_offset;
REG_ID id;
} RGKN_KEY;
typedef struct rgdb_block {
DWORD RGDB_ID; /* RGDB */
DWORD size;
DWORD unused_size;
WORD flags;
WORD section;
DWORD free_offset; /* -1 if there is no free space */
WORD max_id;
WORD first_free_id;
DWORD uk1;
DWORD chksum;
} RGDB_HDR;
typedef struct rgdb_key {
DWORD size;
REG_ID id;
DWORD used_size;
WORD name_len;
WORD num_values;
DWORD uk1;
} RGDB_KEY;
typedef struct rgdb_value {
DWORD type;
DWORD uk1;
WORD name_len;
WORD data_len;
} RGDB_VALUE;
typedef struct creg_struct_s {
int fd;
BOOL modified;
char *base;
struct stat sbuf;
CREG_HDR *creg_hdr;
RGKN_HDR *rgkn_hdr;
RGDB_KEY ***rgdb_keys;
} CREG;
#if 0 /* unused */
#define RGKN_START_SIZE 0x2000
#define RGKN_INC_SIZE 0x1000
#endif
#define LOCN_RGKN(creg, o) ((RGKN_KEY *)((creg)->base + sizeof(CREG_HDR) + o))
#define LOCN_RGDB_BLOCK(creg, o) (((creg)->base + (creg)->creg_hdr->rgdb_offset + o))
#define LOCN_RGDB_KEY(creg, rgdb, id) ((RGDB_KEY *)((creg)->rgdb_keys[(rgdb)][(id)]))
static DWORD str_to_dword(const char *a) {
int i;
unsigned long ret = 0;
for(i = strlen(a)-1; i >= 0; i--) {
ret = ret * 0x100 + a[i];
}
return ret;
}
#if 0 /* unused */
static DWORD calc_hash(const char *str) {
DWORD ret = 0;
int i;
for(i = 0; str[i] && str[i] != '\\'; i++) {
ret+=toupper(str[i]);
}
return ret;
}
static void parse_rgkn_block(CREG *creg, off_t start_off, off_t end_off)
{
off_t i;
for(i = start_off; end_off - i > sizeof(RGKN_KEY); i+= sizeof(RGKN_KEY)) {
RGKN_KEY *key = (RGKN_KEY *)LOCN_RGKN(creg, i);
if(key->type == 0) {
DEBUG(4,("Regular, id: %d, %d, parent: %x, firstchild: %x, next: %x hash: %lX\n", key->id.id, key->id.rgdb, key->parent_offset, key->first_child_offset, key->next_offset, (long)key->hash));
} else if(key->type == 0x80000000) {
DEBUG(3,("free\n"));
i += key->hash;
} else {
DEBUG(0,("Invalid key type in RGKN: %0X\n", key->type));
}
}
}
#endif
static void parse_rgdb_block(CREG *creg, RGDB_HDR *rgdb_hdr)
{
DWORD used_size = rgdb_hdr->size - rgdb_hdr->unused_size;
DWORD offset = 0;
while(offset < used_size) {
RGDB_KEY *key = (RGDB_KEY *)(((char *)rgdb_hdr) + sizeof(RGDB_HDR) + offset);
if(!(key->id.id == 0xFFFF && key->id.rgdb == 0xFFFF))creg->rgdb_keys[key->id.rgdb][key->id.id] = key;
offset += key->size;
}
}
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(h, CREG);
memset(creg, 0, sizeof(CREG));
h->backend_data = creg;
if((creg->fd = open(h->location, O_RDONLY, 0000)) < 0) {
return WERR_FOOBAR;
}
if (fstat(creg->fd, &creg->sbuf) < 0) {
return WERR_FOOBAR;
}
creg->base = mmap(0, creg->sbuf.st_size, PROT_READ, MAP_SHARED, creg->fd, 0);
if (creg->base == (void *)-1) {
DEBUG(0,("Could not mmap file: %s, %s\n", h->location, strerror(errno)));
return WERR_FOOBAR;
}
creg->creg_hdr = (CREG_HDR *)creg->base;
if ((creg_id = IVAL(&creg->creg_hdr->CREG_ID,0)) != str_to_dword("CREG")) {
DEBUG(0, ("Unrecognized Windows 95 registry header id: 0x%0X, %s\n",
creg_id, h->location));
return WERR_FOOBAR;
}
creg->rgkn_hdr = (RGKN_HDR *)LOCN_RGKN(creg, 0);
if ((rgkn_id = IVAL(&creg->rgkn_hdr->RGKN_ID,0)) != str_to_dword("RGKN")) {
DEBUG(0, ("Unrecognized Windows 95 registry key index id: 0x%0X, %s\n",
rgkn_id, h->location));
return WERR_FOOBAR;
}
#if 0
/* If'ed out because we only need to parse this stuff when allocating new
* entries (which we don't do at the moment */
/* First parse the 0x2000 long block */
parse_rgkn_block(creg, sizeof(RGKN_HDR), 0x2000);
/* Then parse the other 0x1000 length blocks */
for(offset = 0x2000; offset < creg->rgkn_hdr->size; offset+=0x1000) {
parse_rgkn_block(creg, offset, offset+0x1000);
}
#endif
creg->rgdb_keys = talloc_array(h, RGDB_KEY **, creg->creg_hdr->num_rgdb);
offset = 0;
DEBUG(3, ("Reading %d rgdb entries\n", creg->creg_hdr->num_rgdb));
for(i = 0; i < creg->creg_hdr->num_rgdb; i++) {
RGDB_HDR *rgdb_hdr = (RGDB_HDR *)LOCN_RGDB_BLOCK(creg, offset);
if(strncmp((char *)&(rgdb_hdr->RGDB_ID), "RGDB", 4)) {
DEBUG(0, ("unrecognized rgdb entry: %4d, %s\n",
rgdb_hdr->RGDB_ID, h->location));
return WERR_FOOBAR;
} else {
DEBUG(3, ("Valid rgdb entry, first free id: %d, max id: %d\n", rgdb_hdr->first_free_id, rgdb_hdr->max_id));
}
creg->rgdb_keys[i] = talloc_array(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);
offset+=rgdb_hdr->size;
}
/* First element in rgkn should be root key */
*root = talloc(h, struct registry_key);
(*root)->name = NULL;
(*root)->backend_data = LOCN_RGKN(creg, sizeof(RGKN_HDR));
return WERR_OK;
}
static WERROR w95_get_subkey_by_index (TALLOC_CTX *mem_ctx, const struct registry_key *parent, int n, struct registry_key **key)
{
CREG *creg = parent->hive->backend_data;
RGKN_KEY *rgkn_key = parent->backend_data;
RGKN_KEY *child;
DWORD child_offset;
DWORD cur = 0;
/* Get id of first child */
child_offset = rgkn_key->first_child_offset;
while(child_offset != 0xFFFFFFFF) {
child = LOCN_RGKN(creg, child_offset);
/* n == cur ? return! */
if(cur == n) {
RGDB_KEY *rgdb_key;
rgdb_key = LOCN_RGDB_KEY(creg, child->id.rgdb, child->id.id);
if(!rgdb_key) {
DEBUG(0, ("Can't find %d,%d in RGDB table!\n", child->id.rgdb, child->id.id));
return WERR_FOOBAR;
}
*key = talloc(mem_ctx, struct registry_key);
(*key)->backend_data = child;
(*key)->name = talloc_strndup(mem_ctx, (char *)rgdb_key + sizeof(RGDB_KEY), rgdb_key->name_len);
return WERR_OK;
}
cur++;
child_offset = child->next_offset;
}
return WERR_NO_MORE_ITEMS;
}
static WERROR w95_num_values(const struct registry_key *k, uint32_t *count)
{
RGKN_KEY *rgkn_key = k->backend_data;
RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id);
if(!rgdb_key) return WERR_FOOBAR;
*count = rgdb_key->num_values;
return WERR_OK;
}
static WERROR w95_get_value_by_id(TALLOC_CTX *mem_ctx, const struct registry_key *k, int idx, struct registry_value **value)
{
RGKN_KEY *rgkn_key = k->backend_data;
DWORD i;
DWORD offset = 0;
RGDB_KEY *rgdb_key = LOCN_RGDB_KEY((CREG *)k->hive->backend_data, rgkn_key->id.rgdb, rgkn_key->id.id);
RGDB_VALUE *curval = NULL;
if(!rgdb_key) return WERR_FOOBAR;
if(idx >= rgdb_key->num_values) return WERR_NO_MORE_ITEMS;
for(i = 0; i < idx; i++) {
curval = (RGDB_VALUE *)(((char *)rgdb_key) + sizeof(RGDB_KEY) + rgdb_key->name_len + offset);
offset+=sizeof(RGDB_VALUE) + curval->name_len + curval->data_len;
}
*value = talloc(mem_ctx, struct registry_value);
(*value)->name = talloc_strndup(mem_ctx, (char *)curval+sizeof(RGDB_VALUE), curval->name_len);
(*value)->data = data_blob_talloc(mem_ctx, curval+sizeof(RGDB_VALUE)+curval->name_len, curval->data_len);
(*value)->data_type = curval->type;
return WERR_OK;
}
static struct hive_operations reg_backend_w95 = {
.name = "w95",
.open_hive = w95_open_reg,
.get_value_by_index = w95_get_value_by_id,
.num_values = w95_num_values,
.get_subkey_by_index = w95_get_subkey_by_index,
};
NTSTATUS registry_w95_init(void)
{
return registry_register(&reg_backend_w95);
}
@@ -0,0 +1,48 @@
/*
Unix SMB/CIFS implementation.
Registry interface
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 "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)
{
register_backend("registry", &reg_backend_wine);
return NT_STATUS_OK;
}
WERROR reg_open_wine(struct registry_key **ctx)
{
/* FIXME: Open ~/.wine/system.reg, etc */
return WERR_NOT_SUPPORTED;
}
+82
View File
@@ -0,0 +1,82 @@
/*
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"
/**
* @file
* @brief Samba-specific registry functions
*/
static WERROR reg_samba_get_predef (struct registry_context *ctx, uint32_t hkey, struct registry_key **k)
{
WERROR error;
const char *conf;
char *backend;
const char *location;
const char *hivename = reg_get_predef_name(hkey);
*k = NULL;
conf = lp_parm_string(-1, "registry", hivename);
if (!conf) {
return WERR_NOT_SUPPORTED;
}
location = strchr(conf, ':');
if (location) {
backend = talloc_strndup(ctx, conf, (int)(location - conf));
location++;
} else {
backend = talloc_strdup(ctx, "ldb");
location = conf;
}
/* FIXME: Different hive backend for HKEY_CLASSES_ROOT: merged view of HKEY_LOCAL_MACHINE\Software\Classes
* and HKEY_CURRENT_USER\Software\Classes */
/* FIXME: HKEY_CURRENT_CONFIG is an alias for HKEY_LOCAL_MACHINE\System\CurrentControlSet\Hardware Profiles\Current */
/* FIXME: HKEY_PERFORMANCE_DATA is dynamically generated */
/* FIXME: HKEY_LOCAL_MACHINE\Hardware is autogenerated */
/* FIXME: HKEY_LOCAL_MACHINE\Security\SAM is an alias for HKEY_LOCAL_MACHINE\SAM */
error = reg_open_hive(ctx, backend, location, ctx->session_info, ctx->credentials, k);
talloc_free(backend);
return error;
}
_PUBLIC_ WERROR reg_open_local (TALLOC_CTX *mem_ctx,
struct registry_context **ctx,
struct auth_session_info *session_info,
struct cli_credentials *credentials)
{
*ctx = talloc(mem_ctx, struct registry_context);
(*ctx)->credentials = talloc_reference(*ctx, credentials);
(*ctx)->session_info = talloc_reference(*ctx, session_info);
(*ctx)->get_predefined_key = reg_samba_get_predef;
return WERR_OK;
}
+167
View File
@@ -0,0 +1,167 @@
/*
Definitions for the REGF registry file format as used by
Windows NT4 and above.
Copyright (C) 2005 Jelmer Vernooij, jelmer@samba.org
Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl
Based on two files from Samba 3:
regedit.c by Richard Sharpe
regfio.c by Jerry Carter
*/
interface regf
{
const int REGF_OFFSET_NONE = 0xffffffff;
/*
* Registry version number
* 1.2.0.1 for WinNT 3.51
* 1.3.0.1 for WinNT 4
* 1.5.0.1 for WinXP
*/
typedef [noprint] struct {
[value(1)] uint32 major;
[value(3)] uint32 minor;
[value(0)] uint32 release;
[value(1)] uint32 build;
} regf_version;
/*
"regf" is obviously the abbreviation for "Registry file". "regf" is the
signature of the header-block which is always 4kb in size, although only
the first 64 bytes seem to be used and a checksum is calculated over
the first 0x200 bytes only!
*/
typedef [public,noprint] struct {
[charset(DOS)] uint8 REGF_ID[4]; /* 'regf' */
uint32 update_counter1;
uint32 update_counter2;
NTTIME modtime;
regf_version version;
uint32 data_offset;
uint32 last_block;
[value(1)] uint32 uk7; /* 1 */
[charset(UTF16)] uint16 description[0x40];
uint32 padding[83]; /* Padding */
/* Checksum of first 0x200 bytes XOR-ed */
uint32 chksum;
} regf_hdr;
/*
hbin probably means hive-bin (i.e. hive-container)
This block is always a multiple
of 4kb in size.
*/
typedef [public,noprint] struct {
[charset(DOS)] uint8 HBIN_ID[4]; /* hbin */
uint32 offset_from_first; /* Offset from 1st hbin-Block */
uint32 offset_to_next; /* Offset to the next hbin-Block */
uint32 unknown[2];
NTTIME last_change;
uint32 block_size; /* Block size (including the header!) */
uint8 data[offset_to_next-0x20];
/* data is filled with:
uint32 length;
Negative if in used, positive otherwise
Always a multiple of 8
uint8_t data[length];
Free space marker if 0xffffffff
*/
} hbin_block;
typedef [base_type(uint16),noprint] enum {
REG_ROOT_KEY = 0x20,
REG_SUB_KEY = 0x2C,
REG_SYM_LINK = 0x10
} reg_key_type;
/*
The nk-record can be treated as a combination of tree-record and
key-record of the win 95 registry.
*/
typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
reg_key_type type;
NTTIME last_change;
uint32 uk1;
uint32 parent_offset;
uint32 num_subkeys;
uint32 uk2;
uint32 subkeys_offset;
uint32 unknown_offset;
uint32 num_values;
uint32 values_offset; /* Points to a list of offsets of vk-records */
uint32 sk_offset;
uint32 clsname_offset;
uint32 unk3[5];
[value(strlen(key_name))] uint16 name_length;
uint16 clsname_length;
[charset(DOS)] uint8 key_name[name_length];
} nk_block;
/* sk (? Security Key ?) is the ACL of the registry. */
typedef [noprint,public] struct {
[charset(DOS)] uint8 header[2];
uint16 tag;
uint32 prev_offset;
uint32 next_offset;
uint32 ref_cnt;
uint32 rec_size;
uint8 sec_desc[rec_size];
} sk_block;
typedef [noprint] struct {
uint32 nk_offset;
uint32 base37; /* base37 of key name */
} lh_hash;
/* Subkey listing with hash of first 4 characters */
typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
lh_hash hr[key_count];
} lh_block;
typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
uint32 nk_offset[key_count];
} li_block;
typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
uint32 offset[key_count]; /* li/lh offset */
} ri_block;
/* The vk-record consists information to a single value (value key). */
typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
[value(strlen(data_name))] uint16 name_length;
uint32 data_length; /* If top-bit set, offset contains the data */
uint32 data_offset;
uint32 data_type;
uint16 flag; /* =1, has name, else no name (=Default). */
uint16 unk1;
[charset(DOS)] uint8 data_name[name_length];
} vk_block;
typedef [noprint] struct {
uint32 nk_offset;
[charset(DOS)] uint8 hash[4];
} hash_record;
/*
The lf-record is the counterpart to the RGKN-record (the
hash-function)
*/
typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
hash_record hr[key_count]; /* Array of hash records, depending on key_count */
} lf_block;
}
+186
View File
@@ -0,0 +1,186 @@
/*
Unix SMB/CIFS implementation.
Registry interface
Copyright (C) Gerald Carter 2002.
Copyright (C) Jelmer Vernooij 2003-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.
*/
#ifndef _REGISTRY_H /* _REGISTRY_H */
#define _REGISTRY_H
#include "librpc/gen_ndr/security.h"
/* Handles for the predefined keys */
#define HKEY_CLASSES_ROOT 0x80000000
#define HKEY_CURRENT_USER 0x80000001
#define HKEY_LOCAL_MACHINE 0x80000002
#define HKEY_USERS 0x80000003
#define HKEY_PERFORMANCE_DATA 0x80000004
#define HKEY_CURRENT_CONFIG 0x80000005
#define HKEY_DYN_DATA 0x80000006
#define HKEY_PERFORMANCE_TEXT 0x80000050
#define HKEY_PERFORMANCE_NLSTEXT 0x80000060
struct reg_predefined_key {
uint32_t handle;
const char *name;
};
extern const struct reg_predefined_key reg_predefined_keys[];
#define REG_DELETE -1
/*
* The general idea here is that every backend provides a 'hive'. Combining
* various hives gives you a complete registry like windows has
*/
#define REGISTRY_INTERFACE_VERSION 1
/* structure to store the registry handles */
struct registry_key
{
const char *name;
const char *path;
const char *class_name;
NTTIME last_mod;
struct registry_hive *hive;
void *backend_data;
};
struct registry_value
{
const char *name;
unsigned int data_type;
DATA_BLOB data;
};
/* FIXME */
typedef void (*reg_key_notification_function) (void);
typedef void (*reg_value_notification_function) (void);
/*
* Container for function pointers to enumeration routines
* for virtual registry view
*
* Backends can provide :
* - just one hive (example: nt4, w95)
* - several hives (example: rpc).
*
* Backends should always do case-insensitive compares
* (everything is case-insensitive but case-preserving,
* just like the FS)
*
* There is no save function as all operations are expected to
* be atomic.
*/
struct hive_operations {
const char *name;
/* Implement this one */
WERROR (*open_hive) (struct registry_hive *, struct registry_key **);
/* Or this one */
WERROR (*open_key) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_key **);
WERROR (*num_subkeys) (const struct registry_key *, uint32_t *count);
WERROR (*num_values) (const struct registry_key *, uint32_t *count);
WERROR (*get_subkey_by_index) (TALLOC_CTX *, const struct registry_key *, int idx, struct registry_key **);
/* Can not contain more than one level */
WERROR (*get_subkey_by_name) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_key **);
WERROR (*get_value_by_index) (TALLOC_CTX *, const struct registry_key *, int idx, struct registry_value **);
/* Can not contain more than one level */
WERROR (*get_value_by_name) (TALLOC_CTX *, const struct registry_key *, const char *name, struct registry_value **);
/* Security control */
WERROR (*key_get_sec_desc) (TALLOC_CTX *, const struct registry_key *, struct security_descriptor **);
WERROR (*key_set_sec_desc) (const struct registry_key *, const struct security_descriptor *);
/* Notification */
WERROR (*request_key_change_notify) (const struct registry_key *, reg_key_notification_function);
WERROR (*request_value_change_notify) (const struct registry_value *, reg_value_notification_function);
/* Key management */
WERROR (*add_key)(TALLOC_CTX *, const struct registry_key *, const char *name, uint32_t access_mask, struct security_descriptor *, struct registry_key **);
WERROR (*del_key)(const struct registry_key *, const char *name);
WERROR (*flush_key) (const struct registry_key *);
/* Value management */
WERROR (*set_value)(const struct registry_key *, const char *name, uint32_t type, const DATA_BLOB data);
WERROR (*del_value)(const struct registry_key *, const char *valname);
};
struct cli_credentials;
struct registry_hive
{
const struct hive_operations *functions;
struct registry_key *root;
struct auth_session_info *session_info;
struct cli_credentials *credentials;
void *backend_data;
const char *location;
};
/* Handle to a full registry
* contains zero or more hives */
struct registry_context {
void *backend_data;
struct cli_credentials *credentials;
struct auth_session_info *session_info;
WERROR (*get_predefined_key) (struct registry_context *, uint32_t hkey, struct registry_key **);
};
struct reg_init_function_entry {
const struct hive_operations *hive_functions;
struct reg_init_function_entry *prev, *next;
};
/* Representing differences between registry files */
struct reg_diff_value
{
const char *name;
enum { REG_DIFF_DEL_VAL, REG_DIFF_SET_VAL } changetype;
uint32_t type;
DATA_BLOB data;
};
struct reg_diff_key
{
const char *name;
enum { REG_DIFF_CHANGE_KEY, REG_DIFF_DEL_KEY } changetype;
uint32_t numvalues;
struct reg_diff_value *values;
};
struct reg_diff
{
const char *format;
uint32_t numkeys;
struct reg_diff_key *keys;
};
struct auth_session_info;
struct event_context;
#include "lib/registry/registry_proto.h"
#endif /* _REGISTRY_H */
+86
View File
@@ -0,0 +1,86 @@
/*
Unix SMB/CIFS implementation.
simple registry frontend
Copyright (C) Jelmer Vernooij 2004-2005
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 "lib/registry/registry.h"
#include "lib/events/events.h"
#include "lib/registry/reg_backend_rpc.h"
#include "lib/cmdline/popt_common.h"
int main(int argc, char **argv)
{
int opt;
poptContext pc;
char *outputfile = NULL;
struct registry_context *h1 = NULL, *h2 = NULL;
int from_null = 0;
WERROR error;
struct reg_diff *diff;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", 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_COMMON_SAMBA
POPT_COMMON_CREDENTIALS
POPT_COMMON_VERSION
{ NULL }
};
registry_init();
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
while((opt = poptGetNextOpt(pc)) != -1) {
error = WERR_OK;
switch(opt) {
case 'L':
if (!h1 && !from_null) error = reg_open_local(NULL, &h1, NULL, cmdline_credentials);
else if (!h2) error = reg_open_local(NULL, &h2, NULL, cmdline_credentials);
break;
case 'R':
if (!h1 && !from_null)
error = reg_open_remote(&h1, NULL, cmdline_credentials,
poptGetOptArg(pc), NULL);
else if (!h2) error = reg_open_remote(&h2, NULL, cmdline_credentials,
poptGetOptArg(pc), NULL);
break;
}
if (!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Error: %s\n", win_errstr(error));
return 1;
}
}
poptFreeContext(pc);
diff = reg_generate_diff(NULL, h1, h2);
if (!diff) {
fprintf(stderr, "Unable to generate diff between keys\n");
return -1;
}
reg_diff_save(diff, outputfile);
return 0;
}
@@ -0,0 +1,75 @@
/*
Unix SMB/CIFS implementation.
simple registry frontend
Copyright (C) 2004-2005 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.
*/
#include "includes.h"
#include "lib/events/events.h"
#include "lib/registry/registry.h"
#include "lib/cmdline/popt_common.h"
#include "lib/registry/reg_backend_rpc.h"
int main(int argc, char **argv)
{
int opt;
poptContext pc;
const char *patch;
struct registry_context *h;
const char *remote = NULL;
struct reg_diff *diff;
WERROR error;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
POPT_COMMON_SAMBA
POPT_COMMON_CREDENTIALS
{ NULL }
};
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
while((opt = poptGetNextOpt(pc)) != -1) {
}
registry_init();
if (remote) {
error = reg_open_remote (&h, NULL, cmdline_credentials, remote, NULL);
} else {
error = reg_open_local (NULL, &h, NULL, cmdline_credentials);
}
if (W_ERROR_IS_OK(error)) {
fprintf(stderr, "Error: %s\n", win_errstr(error));
return 1;
}
patch = poptGetArg(pc);
poptFreeContext(pc);
diff = reg_diff_load(NULL, patch);
if (!diff) {
fprintf(stderr, "Unable to load registry patch from `%s'\n", patch);
return 1;
}
reg_diff_apply(diff, h);
return 0;
}
+490
View File
@@ -0,0 +1,490 @@
/*
Unix SMB/CIFS implementation.
simple registry frontend
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 "lib/registry/registry.h"
#include "lib/cmdline/popt_common.h"
#include "lib/events/events.h"
#include "lib/registry/reg_backend_rpc.h"
#include "system/time.h"
#include "lib/smbreadline/smbreadline.h"
#include "librpc/gen_ndr/ndr_security.h"
/*
* ck/cd - change key
* ls - list values/keys
* rmval/rm - remove value
* rmkey/rmdir - remove key
* mkkey/mkdir - make key
* ch - change hive
* info - show key info
* save - save hive
* print - print value
* help
* exit
*/
static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
struct security_descriptor *sec_desc = NULL;
time_t last_mod;
WERROR error;
printf("Name: %s\n", cur->name);
printf("Full path: %s\n", cur->path);
printf("Key Class: %s\n", cur->class_name);
last_mod = nt_time_to_unix(cur->last_mod);
printf("Time Last Modified: %s\n", ctime(&last_mod));
error = reg_get_sec_desc(mem_ctx, cur, &sec_desc);
if (!W_ERROR_IS_OK(error)) {
printf("Error getting security descriptor\n");
} else {
ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "Security", sec_desc);
}
talloc_free(sec_desc);
return cur;
}
static struct registry_key *cmd_predef(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv)
{
struct registry_key *ret = NULL;
if (argc < 2) {
fprintf(stderr, "Usage: predef predefined-key-name\n");
} else if (!ctx) {
fprintf(stderr, "No full registry loaded, no predefined keys defined\n");
} else {
WERROR error = reg_get_predefined_key_by_name(ctx, argv[1], &ret);
if (!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Error opening predefined key %s: %s\n", argv[1], win_errstr(error));
ret = NULL;
}
}
return ret;
}
static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
printf("%s\n", cur->path);
return cur;
}
static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
struct registry_value val;
WERROR error;
if (argc < 4) {
fprintf(stderr, "Usage: set value-name type value\n");
return cur;
}
if (!reg_string_to_val(mem_ctx, argv[2], argv[3], &val.data_type, &val.data)) {
fprintf(stderr, "Unable to interpret data\n");
return cur;
}
error = reg_val_set(cur, argv[1], val.data_type, val.data);
if (!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Error setting value: %s\n", win_errstr(error));
return NULL;
}
return cur;
}
static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
struct registry_key *new = NULL;
WERROR error;
if(argc < 2) {
new = cur;
} else {
error = reg_open_key(mem_ctx, cur, argv[1], &new);
if(!W_ERROR_IS_OK(error)) {
DEBUG(0, ("Error opening specified key: %s\n", win_errstr(error)));
return NULL;
}
}
printf("Current path is: %s\n", new->path);
return new;
}
static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
struct registry_value *value;
WERROR error;
if (argc != 2) {
fprintf(stderr, "Usage: print <valuename>");
return NULL;
}
error = reg_key_get_value_by_name(mem_ctx, cur, argv[1], &value);
if (!W_ERROR_IS_OK(error)) {
fprintf(stderr, "No such value '%s'\n", argv[1]);
return NULL;
}
printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
return NULL;
}
static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
int i;
WERROR error;
struct registry_value *value;
struct registry_key *sub;
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, cur, i, &sub)); i++) {
printf("K %s\n", sub->name);
}
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while browsing thru keys: %s\n", win_errstr(error)));
}
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) {
printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
}
return NULL;
}
static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
struct registry_key *tmp;
if(argc < 2) {
fprintf(stderr, "Usage: mkkey <keyname>\n");
return NULL;
}
if(!W_ERROR_IS_OK(reg_key_add_name(mem_ctx, cur, argv[1], 0, NULL, &tmp))) {
fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]);
return NULL;
}
return NULL;
}
static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
if(argc < 2) {
fprintf(stderr, "Usage: rmkey <name>\n");
return NULL;
}
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]);
}
return NULL;
}
static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
if(argc < 2) {
fprintf(stderr, "Usage: rmval <valuename>\n");
return NULL;
}
if(!W_ERROR_IS_OK(reg_del_value(cur, argv[1]))) {
fprintf(stderr, "Error deleting value '%s'\n", argv[1]);
} else {
fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]);
}
return NULL;
}
static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
{
exit(0);
return NULL;
}
static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int, char **);
static struct {
const char *name;
const char *alias;
const char *help;
struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int argc, char **argv);
} regshell_cmds[] = {
{"ck", "cd", "Change current key", cmd_ck },
{"info", "i", "Show detailed information of a key", cmd_info },
{"list", "ls", "List values/keys in current key", cmd_ls },
{"print", "p", "Print value", cmd_print },
{"mkkey", "mkdir", "Make new key", cmd_mkkey },
{"rmval", "rm", "Remove value", cmd_rmval },
{"rmkey", "rmdir", "Remove key", cmd_rmkey },
{"pwd", "pwk", "Printing current key", cmd_pwd },
{"set", "update", "Update value", cmd_set },
{"help", "?", "Help", cmd_help },
{"exit", "quit", "Exit", cmd_exit },
{"predef", "predefined", "Go to predefined key", cmd_predef },
{NULL }
};
static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv)
{
int i;
printf("Available commands:\n");
for(i = 0; regshell_cmds[i].name; i++) {
printf("%s - %s\n", regshell_cmds[i].name, regshell_cmds[i].help);
}
return NULL;
}
static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *k, char *line)
{
int argc;
char **argv = NULL;
int ret, i;
if ((ret = poptParseArgvString(line, &argc, (const char ***) &argv)) != 0) {
fprintf(stderr, "regshell: %s\n", poptStrerror(ret));
return k;
}
for(i = 0; regshell_cmds[i].name; i++) {
if(!strcmp(regshell_cmds[i].name, argv[0]) ||
(regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) {
return regshell_cmds[i].handle(mem_ctx, ctx, k, argc, argv);
}
}
fprintf(stderr, "No such command '%s'\n", argv[0]);
return k;
}
#define MAX_COMPLETIONS 100
static struct registry_key *current_key = NULL;
static char **reg_complete_command(const char *text, int start, int end)
{
/* Complete command */
char **matches;
int i, len, samelen=0, count=1;
matches = malloc_array_p(char *, MAX_COMPLETIONS);
if (!matches) return NULL;
matches[0] = NULL;
len = strlen(text);
for (i=0;regshell_cmds[i].handle && count < MAX_COMPLETIONS-1;i++) {
if (strncmp(text, regshell_cmds[i].name, len) == 0) {
matches[count] = strdup(regshell_cmds[i].name);
if (!matches[count])
goto cleanup;
if (count == 1)
samelen = strlen(matches[count]);
else
while (strncmp(matches[count], matches[count-1], samelen) != 0)
samelen--;
count++;
}
}
switch (count) {
case 0: /* should never happen */
case 1:
goto cleanup;
case 2:
matches[0] = strdup(matches[1]);
break;
default:
matches[0] = strndup(matches[1], samelen);
}
matches[count] = NULL;
return matches;
cleanup:
count--;
while (count >= 0) {
free(matches[count]);
count--;
}
free(matches);
return NULL;
}
static char **reg_complete_key(const char *text, int start, int end)
{
struct registry_key *base;
struct registry_key *subkey;
int i, j = 1;
int samelen = 0;
int len;
char **matches;
const char *base_n = "";
TALLOC_CTX *mem_ctx;
WERROR status;
matches = malloc_array_p(char *, MAX_COMPLETIONS);
if (!matches) return NULL;
matches[0] = NULL;
mem_ctx = talloc_init("completion");
base = current_key;
len = strlen(text);
for(i = 0; j < MAX_COMPLETIONS-1; i++) {
status = reg_key_get_subkey_by_index(mem_ctx, base, i, &subkey);
if(W_ERROR_IS_OK(status)) {
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;
} else {
printf("Error creating completion list: %s\n", win_errstr(status));
talloc_free(mem_ctx);
return NULL;
}
}
if (j == 1) { /* No matches at all */
SAFE_FREE(matches);
talloc_free(mem_ctx);
return NULL;
}
if (j == 2) { /* Exact match */
asprintf(&matches[0], "%s%s", base_n, matches[1]);
} else {
asprintf(&matches[0], "%s%s", base_n, talloc_strndup(mem_ctx, matches[1], samelen));
}
talloc_free(mem_ctx);
matches[j] = NULL;
return matches;
}
static char **reg_completion(const char *text, int start, int end)
{
smb_readline_ca_char(' ');
if (start == 0) {
return reg_complete_command(text, start, end);
} else {
return reg_complete_key(text, start, end);
}
}
int main(int argc, char **argv)
{
int opt;
const char *backend = NULL;
struct registry_key *curkey = NULL;
poptContext pc;
WERROR error;
TALLOC_CTX *mem_ctx = talloc_init("cmd");
const char *remote = NULL;
struct registry_context *h = NULL;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
{"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
POPT_COMMON_SAMBA
POPT_COMMON_CREDENTIALS
POPT_COMMON_VERSION
{ NULL }
};
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
while((opt = poptGetNextOpt(pc)) != -1) {
}
registry_init();
if (remote) {
error = reg_open_remote (&h, NULL, cmdline_credentials, remote, NULL);
} else if (backend) {
error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, cmdline_credentials, &curkey);
} else {
error = reg_open_local(NULL, &h, NULL, cmdline_credentials);
}
if(!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Unable to open registry\n");
return 1;
}
if (h) {
int i;
for (i = 0; reg_predefined_keys[i].handle; i++) {
WERROR err;
err = reg_get_predefined_key(h, reg_predefined_keys[i].handle, &curkey);
if (W_ERROR_IS_OK(err)) {
break;
} else {
curkey = NULL;
}
}
}
if (!curkey) {
fprintf(stderr, "Unable to access any of the predefined keys\n");
return -1;
}
poptFreeContext(pc);
while(True) {
char *line, *prompt;
if(curkey->hive->root->name) {
asprintf(&prompt, "%s:%s> ", curkey->hive->root->name, curkey->path);
} else {
asprintf(&prompt, "%s> ", curkey->path);
}
current_key = curkey; /* No way to pass a void * pointer
via readline :-( */
line = smb_readline(prompt, NULL, reg_completion);
if(!line)
break;
if(line[0] != '\n') {
struct registry_key *new = process_cmd(mem_ctx, h, curkey, line);
if(new)curkey = new;
}
}
talloc_free(mem_ctx);
return 0;
}
+153
View File
@@ -0,0 +1,153 @@
/*
Unix SMB/CIFS implementation.
simple registry frontend
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 "lib/registry/registry.h"
#include "lib/events/events.h"
#include "lib/registry/reg_backend_rpc.h"
#include "lib/cmdline/popt_common.h"
static void print_tree(int l, struct registry_key *p, int fullpath, int novals)
{
struct registry_key *subkey;
struct registry_value *value;
struct security_descriptor *sec_desc;
WERROR error;
int i;
TALLOC_CTX *mem_ctx;
for(i = 0; i < l; i++) putchar(' ');
/* Hive name */
if(p->hive->root == p) {
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);
else printf("%s\n", p->name?p->name:"(NULL)");
}
mem_ctx = talloc_init("print_tree");
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, p, i, &subkey)); i++) {
print_tree(l+1, subkey, fullpath, novals);
}
talloc_free(mem_ctx);
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while fetching subkeys for '%s': %s\n", p->path, win_errstr(error)));
}
if(!novals) {
mem_ctx = talloc_init("print_tree");
for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, p, i, &value)); i++) {
int j;
char *desc;
for(j = 0; j < l+1; j++) putchar(' ');
desc = reg_val_description(mem_ctx, value);
printf("%s\n", desc);
}
talloc_free(mem_ctx);
if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
DEBUG(0, ("Error occured while fetching values for '%s': %s\n", p->path, win_errstr(error)));
}
}
mem_ctx = talloc_init("sec_desc");
if (NT_STATUS_IS_ERR(reg_get_sec_desc(mem_ctx, p, &sec_desc))) {
DEBUG(0, ("Error getting security descriptor\n"));
}
talloc_free(mem_ctx);
}
int main(int argc, char **argv)
{
int opt, i;
const char *backend = NULL;
const char *remote = NULL;
poptContext pc;
struct registry_context *h = NULL;
struct registry_key *root = NULL;
WERROR error;
int fullpath = 0, no_values = 0;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
{"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", 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_COMMON_SAMBA
POPT_COMMON_CREDENTIALS
{ NULL }
};
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
while((opt = poptGetNextOpt(pc)) != -1) {
}
registry_init();
if (remote) {
error = reg_open_remote(&h, NULL, cmdline_credentials, remote, NULL);
if(!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Unable to open remote registry at %s:%s \n", remote, win_errstr(error));
return 1;
}
} else if (backend) {
error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, cmdline_credentials, &root);
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;
}
} else {
error = reg_open_local (NULL, &h, NULL, cmdline_credentials);
if(!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Unable to open local registry:%s \n", win_errstr(error));
return 1;
}
}
poptFreeContext(pc);
error = WERR_OK;
if (root != NULL) {
print_tree(0, root, fullpath, no_values);
} else {
for(i = 0; reg_predefined_keys[i].handle; i++) {
error = reg_get_predefined_key(h, reg_predefined_keys[i].handle, &root);
if (!W_ERROR_IS_OK(error)) {
fprintf(stderr, "Skipping %s\n", reg_predefined_keys[i].name);
continue;
}
SMB_ASSERT(root);
print_tree(0, root, fullpath, no_values);
}
}
return 0;
}