diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /source3/registry/reg_import.c | |
parent | Initial commit. (diff) | |
download | samba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/registry/reg_import.c')
-rw-r--r-- | source3/registry/reg_import.c | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/source3/registry/reg_import.c b/source3/registry/reg_import.c new file mode 100644 index 0000000..aef8645 --- /dev/null +++ b/source3/registry/reg_import.c @@ -0,0 +1,314 @@ +/* + * Samba Unix/Linux SMB client library + * Adapter to use reg_parse with the registry api + * + * Copyright (C) Gregor Beck 2010 + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "reg_parse.h" +#include "reg_import.h" +#include "registry.h" +#include "registry/reg_objects.h" +#include <assert.h> + +/* Debuglevel for tracing */ +static const int TL = 2; + +struct reg_import { + struct reg_parse_callback reg_parse_callback; + struct reg_import_callback call; + void *open_key; +}; + +static int reg_parse_callback_key(struct reg_import *cb_private, + const char *key[], size_t n, bool del); + +static int reg_parse_callback_val(struct reg_import *cb_private, + const char *name, uint32_t type, + const uint8_t *data, size_t len); + +static int reg_parse_callback_val_registry_value(struct reg_import *cb_private, + const char *name, + uint32_t type, + const uint8_t *data, + size_t len); + +static int reg_parse_callback_val_regval_blob(struct reg_import *cb_private, + const char *name, uint32_t type, + const uint8_t *data, + size_t len); + +static int reg_parse_callback_val_del(struct reg_import *cb_private, + const char *name); + +static int reg_parse_callback_comment(struct reg_import *cb_private, + const char *txt); + + +/*******************************************************************************/ + +int reg_parse_callback_key(struct reg_import *p, + const char *key[], size_t n, bool del) +{ + WERROR werr = WERR_OK; + + DEBUG(TL, ("%s: %s\n", __FUNCTION__, key[0])); + + if (p->open_key != NULL) { + werr = p->call.closekey(p->call.data, p->open_key); + p->open_key = NULL; + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("closekey failed: %s\n", win_errstr(werr))); + } + } + + if (del) { + werr = p->call.deletekey(p->call.data, NULL, key[0]); + if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) { + /* the key didn't exist, treat as success */ + werr = WERR_OK; + } + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("deletekey %s failed: %s\n", + key[0], win_errstr(werr))); + } + } else { + bool existing; + werr = p->call.createkey(p->call.data, NULL, key[0], + &p->open_key, &existing); + if (W_ERROR_IS_OK(werr)) { + DEBUG(TL, ("createkey %s %s\n", + existing ? "opened" : "created", key[0])); + } else { + DEBUG(0, ("createkey %s failed: %s\n", + key[0], win_errstr(werr))); + } + } + + return W_ERROR_IS_OK(werr) ? 0 : -1; +} + +#define DEBUG_ADD_HEX(LEV, PTR, LEN) \ + do { \ + int i; \ + const unsigned char* ptr = (const unsigned char*)PTR; \ + for (i=0; i<LEN; i++) { \ + DEBUGADD(LEV, ("'%c'(%02x)%s", \ + isprint(ptr[i]) ? ptr[i] : '.', \ + (unsigned)ptr[i], \ + ((i+1 < LEN) && (i+1)%8) \ + ? ", " : "\n")); \ + } \ + } while(0) + +/*----------------------------------------------------------------------------*/ +int reg_parse_callback_val(struct reg_import *p, + const char *name, uint32_t type, + const uint8_t *data, size_t len) +{ + WERROR werr = WERR_OK; + + DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len)); + DEBUG_ADD_HEX(TL, data, len); + + werr = p->call.setval.blob(p->call.data, p->open_key, name, type, + data, len); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("setval %s failed: %s\n", + name, win_errstr(werr))); + } + + return W_ERROR_IS_OK(werr) ? 0 : -1; +} + +/*----------------------------------------------------------------------------*/ +int reg_parse_callback_val_registry_value(struct reg_import *p, + const char *name, uint32_t type, + const uint8_t *data, size_t len) +{ + WERROR werr = WERR_OK; + struct registry_value val = { + .type = type, + .data = data_blob_talloc(p, data, len), + }; + + DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len)); + DEBUG_ADD_HEX(TL, data, len); + + werr = p->call.setval.registry_value(p->call.data, p->open_key, + name, &val); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("setval %s failed: %s\n", + name, win_errstr(werr))); + } + + data_blob_free(&val.data); + return W_ERROR_IS_OK(werr) ? 0 : -1; +} + +/*----------------------------------------------------------------------------*/ +int reg_parse_callback_val_regval_blob(struct reg_import *p, + const char *name, uint32_t type, + const uint8_t *data, size_t len) +{ + WERROR werr = WERR_OK; + void* mem_ctx = talloc_new(p); + struct regval_blob *v = NULL; + + DEBUG(TL, ("%s(%x): >%s< = [%zx]\n", __FUNCTION__, type, name, len)); + DEBUG_ADD_HEX(TL, data, len); + + v = regval_compose(mem_ctx, name, type, data, len); + if (v == NULL) { + DEBUG(0, ("regval_compose %s failed\n", name)); + werr = WERR_NOT_ENOUGH_MEMORY; + goto done; + } + + werr = p->call.setval.regval_blob(p->call.data, p->open_key, v); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("setval %s failed: %s\n", + name, win_errstr(werr))); + } + +done: + talloc_free(mem_ctx); + + return W_ERROR_IS_OK(werr) ? 0 : -1; +} + + +/*----------------------------------------------------------------------------*/ + +int reg_parse_callback_val_del(struct reg_import *p, + const char *name) +{ + WERROR werr = WERR_OK; + + DEBUG(TL, ("%s: %s\n", __FUNCTION__, name)); + + werr = p->call.deleteval(p->call.data, p->open_key, name); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, ("deleteval %s failed: %s\n", + name, win_errstr(werr))); + } + + return W_ERROR_IS_OK(werr) ? 0 : -1; +} + + +int reg_parse_callback_comment(struct reg_import *cb_private, + const char *txt) +{ + DEBUG(TL, ("%s: %s\n", __FUNCTION__, txt)); + return 0; +} + +/******************************************************************************/ +static WERROR nop_callback_open(void* private_data, + void* parent, + const char* name, + void** key) +{ + return WERR_OK; +} + +static WERROR nop_callback_close(void* private_data, void* key) +{ + return WERR_OK; +} + +static WERROR nop_callback_create(void* private_data, + void* parent, + const char* name, + void** key, + bool* existing) +{ + return WERR_OK; +} + + +static WERROR nop_callback_del(void* private_data, + void* parent, + const char* name) +{ + return WERR_OK; +} + +struct reg_parse_callback *reg_import_adapter(TALLOC_CTX *talloc_ctx, + struct reg_import_callback cb) +{ + struct reg_parse_callback *ret; + struct reg_import *p = talloc_zero(talloc_ctx, struct reg_import); + if (p == NULL) { + goto fail; + } + if (cb.openkey == NULL) { + cb.openkey = (reg_import_callback_openkey_t)&nop_callback_open; + } + if (cb.closekey == NULL) { + cb.closekey = + (reg_import_callback_closekey_t)&nop_callback_close; + } + if (cb.createkey == NULL) { + cb.createkey = + (reg_import_callback_createkey_t)&nop_callback_create; + } + if (cb.deletekey == NULL) { + cb.deletekey = + (reg_import_callback_deletekey_t)&nop_callback_del; + + } + if (cb.deleteval == NULL) { + cb.deleteval = + (reg_import_callback_deleteval_t)&nop_callback_del; + } + + p->call = cb; + + ret = &p->reg_parse_callback; + ret->key = (reg_parse_callback_key_t) ®_parse_callback_key; + ret->val_del = (reg_parse_callback_val_del_t) ®_parse_callback_val_del; + ret->comment = (reg_parse_callback_comment_t) ®_parse_callback_comment; + ret->data = p; + + switch (cb.setval_type) { + case BLOB: + assert(cb.setval.blob != NULL); + ret->val = (reg_parse_callback_val_t) ®_parse_callback_val; + break; + case REGISTRY_VALUE: + assert(cb.setval.registry_value != NULL); + ret->val = (reg_parse_callback_val_t) ®_parse_callback_val_registry_value; + break; + case REGVAL_BLOB: + assert(cb.setval.regval_blob != NULL); + ret->val = (reg_parse_callback_val_t) ®_parse_callback_val_regval_blob; + break; + case NONE: + ret->val = NULL; + break; + default: + assert(false); + } + + assert((struct reg_parse_callback *)p == ret); + return ret; +fail: + talloc_free(p); + return NULL; +} |