From b409d4120f9ae451f93a2322267c0f346531d9f3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 26 Aug 2007 15:16:40 +0000 Subject: r24667: Finally merge the registry improvements that Wilco Baan Hofman and I have been working on for at least half a year now. Contains the following improvements: * proper layering (finally!) for the registry library. Distinction is now made between 'real' backends (local, remote, wine, etc) and the low-level hive backends (regf, creg, ldb, ...) that are only used by the local registry backend * tests for all important hive and registry operations * re-enable RPC-WINREG tests (still needs more work though, as some return values aren't checked yet) * write support for REGF files * dir backend now supports setting/reading values, creating keys * support for storing security descriptors * remove CREG backend as it was incomplete, didn't match the data model and wasn't used at all anyway * support for parsing ADM files as used by the policy editor (see lib/policy) * support for parsing PREG files (format used by .POL files) * new streaming interface for registry diffs (improves speed and memory usage for regdiff/regpatch significantly) ... and fixes a large number of bugs in the registry code (This used to be commit 7a1eec6358bc863dfc671c542b7185d3e39d7b5a) --- source4/lib/registry/regf.c | 1923 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1923 insertions(+) create mode 100644 source4/lib/registry/regf.c (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c new file mode 100644 index 0000000000..7fa71033d9 --- /dev/null +++ b/source4/lib/registry/regf.c @@ -0,0 +1,1923 @@ +/* + Samba CIFS implementation + Registry backend for REGF files + Copyright (C) 2005-2007 Jelmer Vernooij, jelmer@samba.org + Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl + + 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 . */ + +#include "includes.h" +#include "lib/registry/hive.h" +#include "system/filesys.h" +#include "system/time.h" +#include "lib/registry/tdr_regf.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "librpc/gen_ndr/winreg.h" + +static struct hive_operations reg_backend_regf; + +/** + * There are several places on the web where the REGF format is explained; + * + * TODO: Links + */ + +/* TODO: + * - Return error codes that make more sense + * - Locking + * - do more things in-memory + */ + +/* + * Read HBIN blocks into memory + */ + +struct regf_data { + int fd; + struct hbin_block **hbins; + struct regf_hdr *header; +}; + +static WERROR regf_save_hbin(struct regf_data *data); + +struct regf_key_data { + struct hive_key key; + struct regf_data *hive; + uint32_t offset; + struct nk_block *nk; +}; + +static struct hbin_block *hbin_by_offset(const struct regf_data *data, + uint32_t offset, uint32_t *rel_offset) +{ + int i; + + for (i = 0; data->hbins[i]; i++) { + if (offset >= data->hbins[i]->offset_from_first && + offset < data->hbins[i]->offset_from_first+ + data->hbins[i]->offset_to_next) { + if (rel_offset != NULL) + *rel_offset = offset - data->hbins[i]->offset_from_first - 0x20; + return data->hbins[i]; + } + } + + return NULL; +} + +/** + * Validate a regf header + * For now, do nothing, but we should check the checksum + */ +static uint32_t regf_hdr_checksum(const uint8_t *buffer) +{ + uint32_t checksum = 0, x; + int i; + + for (i = 0; i < 0x01FB; i+= 4) { + x = IVAL(buffer, i); + checksum ^= x; + } + + return checksum; +} + +/** + * Obtain the contents of a HBIN block + */ +static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) +{ + DATA_BLOB ret; + struct hbin_block *hbin; + uint32_t rel_offset; + + ret.data = NULL; + ret.length = 0; + + hbin = hbin_by_offset(data, offset, &rel_offset); + + if (hbin == NULL) { + DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset)); + return ret; + } + + ret.length = IVAL(hbin->data, rel_offset); + if (!(ret.length & 0x80000000)) { + DEBUG(0, ("Trying to use dirty block at 0x%04x\n", offset)); + return ret; + } + + /* remove high bit */ + ret.length = (ret.length ^ 0xffffffff) + 1; + + ret.length -= 4; /* 4 bytes for the length... */ + ret.data = hbin->data + + (offset - hbin->offset_from_first - 0x20) + 4; + + return ret; +} + +static bool hbin_get_tdr (struct regf_data *regf, uint32_t offset, + TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p) +{ + struct tdr_pull pull; + + ZERO_STRUCT(pull); + + pull.data = hbin_get(regf, offset); + if (!pull.data.data) { + DEBUG(1, ("Unable to get data at 0x%04x\n", offset)); + return false; + } + + if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) { + DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset)); + return false; + } + + return true; +} + +/* Allocate some new data */ +static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size, + uint32_t *offset) +{ + DATA_BLOB ret; + uint32_t rel_offset = -1; /* Relative offset ! */ + struct hbin_block *hbin = NULL; + int i; + + *offset = 0; + + if (size == 0) + return data_blob(NULL, 0); + + size += 4; /* Need to include int32 for the length */ + + /* Allocate as a multiple of 8 */ + size = (size + 7) & ~7; + + ret.data = NULL; + ret.length = 0; + + for (i = 0; (hbin = data->hbins[i]); i++) { + int j; + int32_t my_size; + for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) { + my_size = IVALS(hbin->data, j); + + if (my_size == 0x0) { + DEBUG(0, ("Invalid zero-length block! File is corrupt.\n")); + return ret; + } + + if (my_size % 8 != 0) { + DEBUG(0, ("Encountered non-aligned block!\n")); + } + + if (my_size < 0) { /* Used... */ + my_size = -my_size; + } else if (my_size == size) { /* exact match */ + rel_offset = j; + DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n", size)); + break; + } else if (my_size > size) { /* data will remain */ + rel_offset = j; + /* Split this block and mark the next block as free */ + SIVAL(hbin->data, rel_offset+size, my_size-size); + DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n", my_size, size)); + break; + } + } + + if (rel_offset != -1) + break; + } + + /* No space available in previous hbins, + * allocate new one */ + if (data->hbins[i] == NULL) { + DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n", size)); + data->hbins = talloc_realloc(data, data->hbins, struct hbin_block *, i+2); + hbin = talloc(data->hbins, struct hbin_block); + SMB_ASSERT(hbin != NULL); + + data->hbins[i] = hbin; + data->hbins[i+1] = NULL; + + hbin->HBIN_ID = talloc_strdup(hbin, "hbin"); + hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next); + hbin->offset_to_next = 0x1000; + hbin->unknown[0] = 0; + hbin->unknown[0] = 0; + unix_to_nt_time(&hbin->last_change, time(NULL)); + hbin->block_size = hbin->offset_to_next; + hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20); + + rel_offset = 0x0; + SIVAL(hbin->data, size, hbin->block_size - size - 0x20); + } + + /* Set size and mark as used */ + SIVAL(hbin->data, rel_offset, -size); + + ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */ + ret.length = size - 0x4; + if (offset) { + uint32_t new_rel_offset; + *offset = hbin->offset_from_first + rel_offset + 0x20; + SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin); + SMB_ASSERT(new_rel_offset == rel_offset); + } + + return ret; +} + +/* Store a data blob. Return the offset at which it was stored */ +static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob) +{ + uint32_t ret; + DATA_BLOB dest = hbin_alloc(data, blob.length, &ret); + + memcpy(dest.data, blob.data, blob.length); + + return ret; +} + +static uint32_t hbin_store_tdr (struct regf_data *data, tdr_push_fn_t push_fn, void *p) +{ + struct tdr_push *push = talloc_zero(data, struct tdr_push); + uint32_t ret; + + if (NT_STATUS_IS_ERR(push_fn(push, p))) { + DEBUG(0, ("Error during push\n")); + return -1; + } + + ret = hbin_store(data, push->data); + + talloc_free(push); + + return ret; +} + + +/* Free existing data */ +static void hbin_free (struct regf_data *data, uint32_t offset) +{ + int32_t size; + uint32_t rel_offset; + int32_t next_size; + struct hbin_block *hbin; + + SMB_ASSERT (offset > 0); + + hbin = hbin_by_offset(data, offset, &rel_offset); + + if (hbin == NULL) + return; + + /* Get original size */ + size = IVALS(hbin->data, rel_offset); + + if (size > 0) { + DEBUG(1, ("Trying to free already freed block at 0x%04x\n", offset)); + return; + } + /* Mark as unused */ + size = -size; + + /* If the next block is free, merge into big free block */ + if (rel_offset + size < hbin->offset_to_next) { + next_size = IVALS(hbin->data, rel_offset+size); + if (next_size > 0) { + size += next_size; + } + } + + /* Write block size */ + SIVALS(hbin->data, rel_offset, size); +} + +/** + * Store a data blob data was already stored, but has changed in size + * Will try to save it at the current location if possible, otherwise + * does a free + store */ +static uint32_t hbin_store_resize(struct regf_data *data, + uint32_t orig_offset, DATA_BLOB blob) +{ + uint32_t rel_offset; + struct hbin_block *hbin = hbin_by_offset(data, orig_offset, &rel_offset); + int32_t my_size; + int32_t orig_size; + int32_t needed_size; + int32_t possible_size; + int i; + + SMB_ASSERT(orig_offset > 0); + + if (!hbin) + return hbin_store(data, blob); + + /* Get original size */ + orig_size = -IVALS(hbin->data, rel_offset); + + needed_size = blob.length + 4; /* Add int32 containing length */ + needed_size = (needed_size + 7) & ~7; /* Align */ + + /* Fits into current allocated block */ + if (orig_size >= needed_size) { + memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length); + /* If the difference in size is greater than 0x4, split the block + * and free/merge it */ + if (orig_size - needed_size > 0x4) { + SIVALS(hbin->data, rel_offset, -needed_size); + SIVALS(hbin->data, rel_offset + needed_size, needed_size-orig_size); + hbin_free(data, orig_offset + needed_size); + } + return orig_offset; + } + + possible_size = orig_size; + + /* Check if it can be combined with the next few free records */ + for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) { + if (IVALS(hbin->data, i) < 0) /* Used */ + break; + + my_size = IVALS(hbin->data, i); + + if (my_size == 0x0) { + DEBUG(0, ("Invalid zero-length block! File is corrupt.\n")); + break; + } else { + possible_size += my_size; + } + + if (possible_size >= blob.length) { + SIVAL(hbin->data, rel_offset, -possible_size); + memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length); + return orig_offset; + } + } + + hbin_free(data, orig_offset); + return hbin_store(data, blob); +} + +static uint32_t hbin_store_tdr_resize (struct regf_data *regf, tdr_push_fn_t push_fn, + uint32_t orig_offset, void *p) +{ + struct tdr_push *push = talloc_zero(regf, struct tdr_push); + uint32_t ret; + + if (NT_STATUS_IS_ERR(push_fn(push, p))) { + DEBUG(0, ("Error during push\n")); + return -1; + } + + ret = hbin_store_resize(regf, orig_offset, push->data); + + talloc_free(push); + + return ret; +} + +static uint32_t regf_create_lh_hash(const char *name) +{ + char *hash_name; + uint32_t ret = 0; + uint16_t i; + + hash_name = strupper_talloc(NULL, name); + for (i = 0; *(hash_name + i) != 0; i++) { + ret *= 37; + ret += *(hash_name + i); + } + talloc_free(hash_name); + return ret; +} + +static WERROR regf_get_info (TALLOC_CTX *mem_ctx, + const struct hive_key *key, + const char **classname, + uint32_t *num_subkeys, + uint32_t *num_values, + NTTIME *last_mod_time) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + + if (num_subkeys != NULL) + *num_subkeys = private_data->nk->num_subkeys; + + if (num_values != NULL) + *num_values = private_data->nk->num_values; + + if (classname != NULL) { + if (private_data->nk->clsname_offset != -1) { + DATA_BLOB data = hbin_get(private_data->hive, + private_data->nk->clsname_offset); + *classname = talloc_strndup(mem_ctx, + (char*)data.data, private_data->nk->clsname_length); + } else + *classname = NULL; + } + + /* TODO: Last mod time */ + + return WERR_OK; +} + +static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, + struct regf_data *regf, + uint32_t offset) +{ + struct nk_block *nk; + struct regf_key_data *ret; + + ret = talloc_zero(ctx, struct regf_key_data); + ret->key.ops = ®_backend_regf; + ret->hive = talloc_reference(ret, regf); + ret->offset = offset; + nk = talloc(ret, struct nk_block); + if (nk == NULL) + return NULL; + + ret->nk = nk; + + if (!hbin_get_tdr(regf, offset, nk, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { + DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); + return NULL; + } + + if (strcmp(nk->header, "nk") != 0) { + DEBUG(0, ("Expected nk record, got %s\n", nk->header)); + talloc_free(ret); + return NULL; + } + + return ret; +} + + +static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, + int idx, const char **name, + uint32_t *data_type, DATA_BLOB *data) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + struct vk_block *vk; + struct regf_data *regf = private_data->hive; + uint32_t vk_offset; + DATA_BLOB tmp; + + if (idx >= private_data->nk->num_values) + return WERR_NO_MORE_ITEMS; + + tmp = hbin_get(regf, private_data->nk->values_offset); + if (!tmp.data) { + DEBUG(0, ("Unable to find value list\n")); + return WERR_GENERAL_FAILURE; + } + + if (tmp.length < private_data->nk->num_values * 4) { + DEBUG(1, ("Value counts mismatch\n")); + } + + vk_offset = IVAL(tmp.data, idx * 4); + + vk = talloc(NULL, struct vk_block); + W_ERROR_HAVE_NO_MEMORY(vk); + + if (!hbin_get_tdr(regf, vk_offset, vk, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); + talloc_free(vk); + return WERR_GENERAL_FAILURE; + } + + /* FIXME: name character set ?*/ + if (name != NULL) + *name = talloc_strndup(ctx, vk->data_name, vk->name_length); + + if (data_type != NULL) + *data_type = vk->data_type; + + if (vk->data_length & 0x80000000) { + vk->data_length &=~0x80000000; + data->data = (uint8_t *)&vk->data_offset; + data->length = vk->data_length; + } else { + *data = hbin_get(regf, vk->data_offset); + } + + if (data->length < vk->data_length) { + DEBUG(1, ("Read data less than indicated data length!\n")); + } + + talloc_free(vk); + + return WERR_OK; +} + +static WERROR regf_get_value_by_name (TALLOC_CTX *mem_ctx, + struct hive_key *key, const char *name, + uint32_t *type, DATA_BLOB *data) +{ + int i; + const char *vname; + WERROR error; + + /* FIXME: Do binary search? Is this list sorted at all? */ + + for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i, + &vname, type, data)); i++) { + if (!strcmp(vname, name)) + return WERR_OK; + } + + if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) + return WERR_NOT_FOUND; + + return error; +} + + +static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, + const struct hive_key *key, + uint32_t idx, const char **name, + const char **classname, + NTTIME *last_mod_time) +{ + DATA_BLOB data; + struct regf_key_data *ret; + const struct regf_key_data *private_data = (const struct regf_key_data *)key; + struct nk_block *nk = private_data->nk; + uint32_t key_off=0; + + if (idx >= nk->num_subkeys) + return WERR_NO_MORE_ITEMS; + + data = hbin_get(private_data->hive, nk->subkeys_offset); + if (!data.data) { + DEBUG(0, ("Unable to find subkey list\n")); + return WERR_GENERAL_FAILURE; + } + + if (!strncmp((char *)data.data, "li", 2)) { + struct li_block li; + struct tdr_pull pull; + + DEBUG(10, ("Subkeys in LI list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + DEBUG(0, ("Error parsing LI list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(li.header, "li", 2)); + + if (li.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } + key_off = li.nk_offset[idx]; + + } else if (!strncmp((char *)data.data, "lf", 2)) { + struct lf_block lf; + struct tdr_pull pull; + + DEBUG(10, ("Subkeys in LF list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) { + DEBUG(0, ("Error parsing LF list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(lf.header, "lf", 2)); + + if (lf.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } + + key_off = lf.hr[idx].nk_offset; + } else if (!strncmp((char *)data.data, "lh", 2)) { + struct lh_block lh; + struct tdr_pull pull; + + DEBUG(10, ("Subkeys in LH list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + DEBUG(0, ("Error parsing LH list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); + + if (lh.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } + key_off = lh.hr[idx].nk_offset; + } else if (!strncmp((char *)data.data, "ri", 2)) { + struct ri_block ri; + struct tdr_pull pull; + uint16_t i; + uint16_t sublist_count = 0; + + DEBUG(10, ("Subkeys in RI list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) { + DEBUG(0, ("Error parsing RI list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(ri.header, "ri", 2)); + + for (i = 0; i < ri.key_count; i++) { + DATA_BLOB list_data; + + /* Get sublist data blob */ + list_data = hbin_get(private_data->hive, ri.offset[i]); + if (!list_data.data) { + DEBUG(0, ("Error getting RI list.")); + return WERR_GENERAL_FAILURE; + } + + ZERO_STRUCT(pull); + pull.data = list_data; + + if (!strncmp((char *)list_data.data, "li", 2)) { + struct li_block li; + + DEBUG(10, ("Subkeys in RI->LI list\n")); + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + DEBUG(0, ("Error parsing LI list from RI\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(li.header, "li", 2)); + + /* Advance to next sublist if necessary */ + if (idx >= sublist_count + li.key_count) { + sublist_count += li.key_count; + continue; + } + key_off = li.nk_offset[idx - sublist_count]; + sublist_count += li.key_count; + break; + } else if (!strncmp((char *)list_data.data, "lh", 2)) { + struct lh_block lh; + + DEBUG(10, ("Subkeys in RI->LH list\n")); + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + DEBUG(0, ("Error parsing LH list from RI\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); + + /* Advance to next sublist if necessary */ + if (idx >= sublist_count + lh.key_count) { + sublist_count += lh.key_count; + continue; + } + key_off = lh.hr[idx - sublist_count].nk_offset; + sublist_count += lh.key_count; + break; + } else { + DEBUG(0,("Unknown sublist in ri block\n")); + + return WERR_GENERAL_FAILURE; + } + + } + + if (idx > sublist_count) { + return WERR_NO_MORE_ITEMS; + } + + } else { + DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", + nk->subkeys_offset, data.data[0], data.data[1])); + return WERR_GENERAL_FAILURE; + } + + ret = regf_get_key (ctx, private_data->hive, key_off); + + if (classname != NULL) { + if (ret->nk->clsname_offset != -1) { + DATA_BLOB db = hbin_get(ret->hive, + ret->nk->clsname_offset); + *classname = talloc_strndup(ctx, + (char*)db.data, ret->nk->clsname_length); + } else + *classname = NULL; + } + + if (last_mod_time != NULL) + *last_mod_time = ret->nk->last_change; + + if (name != NULL) + *name = talloc_steal(ctx, ret->nk->key_name); + + talloc_free(ret); + + return WERR_OK; +} + +static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, + const struct hive_key *key, uint32_t offset, + const char *name, uint32_t *ret) +{ + DATA_BLOB subkey_data; + struct nk_block subkey; + struct tdr_pull pull; + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + + subkey_data = hbin_get(private_data->hive, offset); + if (!subkey_data.data) { + DEBUG(0, ("Unable to retrieve subkey HBIN\n")); + return WERR_GENERAL_FAILURE; + } + + ZERO_STRUCT(pull); + pull.data = subkey_data; + + if (NT_STATUS_IS_ERR(tdr_pull_nk_block(&pull, ctx, &subkey))) { + DEBUG(0, ("Error parsing NK structure.\n")); + return WERR_GENERAL_FAILURE; + } + + if (strncmp(subkey.header, "nk", 2)) { + DEBUG(0, ("Not an NK structure.\n")); + return WERR_GENERAL_FAILURE; + } + + if (!strcasecmp(subkey.key_name, name)) { + *ret = offset; + } else { + *ret = 0; + } + return WERR_OK; +} + +static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, + const struct hive_key *key, + const char *name, + struct hive_key **ret) +{ + DATA_BLOB data; + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + struct nk_block *nk = private_data->nk; + uint32_t key_off = 0; + + data = hbin_get(private_data->hive, nk->subkeys_offset); + if (!data.data) { + DEBUG(0, ("Unable to find subkey list\n")); + return WERR_GENERAL_FAILURE; + } + + if (!strncmp((char *)data.data, "li", 2)) { + struct li_block li; + struct tdr_pull pull; + uint16_t i; + + DEBUG(10, ("Subkeys in LI list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + DEBUG(0, ("Error parsing LI list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(li.header, "li", 2)); + + if (li.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } + + for (i = 0; i < li.key_count; i++) { + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, li.nk_offset[i], name, &key_off)); + if (key_off != 0) + break; + } + if (key_off == 0) + return WERR_NOT_FOUND; + } else if (!strncmp((char *)data.data, "lf", 2)) { + struct lf_block lf; + struct tdr_pull pull; + uint16_t i; + + DEBUG(10, ("Subkeys in LF list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) { + DEBUG(0, ("Error parsing LF list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(lf.header, "lf", 2)); + + if (lf.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } + + for (i = 0; i < lf.key_count; i++) { + if (strncmp(lf.hr[i].hash, name, 4)) { + continue; + } + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lf.hr[i].nk_offset, name, &key_off)); + if (key_off != 0) + break; + } + if (key_off == 0) + return WERR_NOT_FOUND; + } else if (!strncmp((char *)data.data, "lh", 2)) { + struct lh_block lh; + struct tdr_pull pull; + uint16_t i; + uint32_t hash; + + DEBUG(10, ("Subkeys in LH list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + DEBUG(0, ("Error parsing LH list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); + + if (lh.key_count != nk->num_subkeys) { + DEBUG(0, ("Subkey counts don't match\n")); + return WERR_GENERAL_FAILURE; + } + + hash = regf_create_lh_hash(name); + for (i = 0; i < lh.key_count; i++) { + if (lh.hr[i].base37 != hash) { + continue; + } + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lh.hr[i].nk_offset, name, &key_off)); + if (key_off != 0) + break; + } + if (key_off == 0) + return WERR_NOT_FOUND; + } else if (!strncmp((char *)data.data, "ri", 2)) { + struct ri_block ri; + struct tdr_pull pull; + uint16_t i, j; + + DEBUG(10, ("Subkeys in RI list\n")); + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) { + DEBUG(0, ("Error parsing RI list\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(ri.header, "ri", 2)); + + for (i = 0; i < ri.key_count; i++) { + DATA_BLOB list_data; + + /* Get sublist data blob */ + list_data = hbin_get(private_data->hive, ri.offset[i]); + if (list_data.data == NULL) { + DEBUG(0, ("Error getting RI list.")); + return WERR_GENERAL_FAILURE; + } + + ZERO_STRUCT(pull); + pull.data = list_data; + + if (!strncmp((char *)list_data.data, "li", 2)) { + struct li_block li; + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + DEBUG(0, ("Error parsing LI list from RI\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(li.header, "li", 2)); + + for (j = 0; j < li.key_count; j++) { + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, + li.nk_offset[j], name, &key_off)); + if (key_off) + break; + } + } else if (!strncmp((char *)list_data.data, "lh", 2)) { + struct lh_block lh; + uint32_t hash; + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + DEBUG(0, ("Error parsing LH list from RI\n")); + return WERR_GENERAL_FAILURE; + } + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); + + hash = regf_create_lh_hash(name); + for (j = 0; j < lh.key_count; j++) { + if (lh.hr[j].base37 != hash) { + continue; + } + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, + lh.hr[j].nk_offset, name, &key_off)); + if (key_off) + break; + } + } + if (key_off) + break; + } + if (!key_off) + return WERR_NOT_FOUND; + } else { + DEBUG(0, ("Unknown subkey list type.\n")); + return WERR_GENERAL_FAILURE; + } + + *ret = (struct hive_key *)regf_get_key (ctx, private_data->hive, key_off); + return WERR_OK; +} + +static WERROR regf_set_sec_desc (struct hive_key *key, + const struct security_descriptor *sec_desc) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + struct sk_block cur_sk, sk, new_sk; + struct regf_data *regf = private_data->hive; + struct nk_block root; + DATA_BLOB data; + uint32_t sk_offset, cur_sk_offset; + bool update_cur_sk = false; + + /* Get the root nk */ + hbin_get_tdr(regf, regf->header->data_offset, regf, + (tdr_pull_fn_t) tdr_pull_nk_block, &root); + + /* Push the security descriptor to a blob */ + if (NT_STATUS_IS_ERR(ndr_push_struct_blob(&data, regf, sec_desc, + (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { + DEBUG(0, ("Unable to push security descriptor\n")); + return WERR_GENERAL_FAILURE; + } + + /* Get the current security descriptor for the key */ + if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) { + DEBUG(0, ("Unable to find security descriptor for current key\n")); + return WERR_BADFILE; + } + /* If there's no change, change nothing. */ + if (memcmp(data.data, cur_sk.sec_desc, MIN(data.length, cur_sk.rec_size)) == 0) { + return WERR_OK; + } + + /* Delete the current sk if only this key is using it */ + if (cur_sk.ref_cnt == 1) { + /* Get the previous security descriptor for the key */ + if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + DEBUG(0, ("Unable to find prev security descriptor for current key\n")); + return WERR_BADFILE; + } + /* Change and store the previous security descriptor */ + sk.next_offset = cur_sk.next_offset; + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk); + + /* Get the next security descriptor for the key */ + if (!hbin_get_tdr(regf, cur_sk.next_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + DEBUG(0, ("Unable to find next security descriptor for current key\n")); + return WERR_BADFILE; + } + /* Change and store the next security descriptor */ + sk.prev_offset = cur_sk.prev_offset; + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.next_offset, &sk); + + hbin_free(regf, private_data->nk->sk_offset); + } else { + /* This key will no longer be referring to this sk */ + cur_sk.ref_cnt--; + update_cur_sk = true; + } + + sk_offset = root.sk_offset; + + do { + cur_sk_offset = sk_offset; + if (!hbin_get_tdr(regf, sk_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + DEBUG(0, ("Unable to find security descriptor\n")); + return WERR_BADFILE; + } + if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) { + private_data->nk->sk_offset = sk_offset; + sk.ref_cnt++; + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, sk_offset, &sk); + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, private_data->nk); + return WERR_OK; + } + sk_offset = sk.next_offset; + } while (sk_offset != root.sk_offset); + + ZERO_STRUCT(new_sk); + new_sk.header = "sk"; + new_sk.prev_offset = cur_sk_offset; + new_sk.next_offset = root.sk_offset; + new_sk.ref_cnt = 1; + new_sk.rec_size = data.length; + new_sk.sec_desc = data.data; + + sk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_sk_block, &new_sk); + if (sk_offset == -1) { + DEBUG(0, ("Error storing sk block\n")); + return WERR_GENERAL_FAILURE; + } + private_data->nk->sk_offset = sk_offset; + + if (update_cur_sk) { + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, private_data->nk->sk_offset, &cur_sk); + } + + /* Get the previous security descriptor for the key */ + if (!hbin_get_tdr(regf, new_sk.prev_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + DEBUG(0, ("Unable to find security descriptor for previous key\n")); + return WERR_BADFILE; + } + /* Change and store the previous security descriptor */ + sk.next_offset = sk_offset; + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk); + + /* Get the next security descriptor for the key (always root, as we append) */ + if (!hbin_get_tdr(regf, new_sk.next_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + DEBUG(0, ("Unable to find security descriptor for current key\n")); + return WERR_BADFILE; + } + /* Change and store the next security descriptor (always root, as we append) */ + sk.prev_offset = sk_offset; + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, root.sk_offset, &sk); + + + /* Store the nk. */ + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, private_data->offset, private_data->nk); + return WERR_OK; +} + +static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, + struct security_descriptor **sd) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + struct sk_block sk; + struct regf_data *regf = private_data->hive; + DATA_BLOB data; + + if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + DEBUG(0, ("Unable to find security descriptor\n")); + return WERR_GENERAL_FAILURE; + } + + if (strcmp(sk.header, "sk") != 0) { + DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header)); + return WERR_GENERAL_FAILURE; + } + + *sd = talloc(ctx, struct security_descriptor); + W_ERROR_HAVE_NO_MEMORY(*sd); + + data.data = sk.sec_desc; + data.length = sk.rec_size; + if (NT_STATUS_IS_ERR(ndr_pull_struct_blob(&data, ctx, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { + DEBUG(0, ("Error parsing security descriptor\n")); + return WERR_GENERAL_FAILURE; + } + + return WERR_OK; +} + +static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, + const char *name, uint32_t key_offset, uint32_t *ret) +{ + DATA_BLOB data; + + /* Create a new key if necessary */ + if (list_offset == -1) { + if (regf->header->version.major != 1) { + DEBUG(0, ("Can't store keys in unknown registry format\n")); + return WERR_NOT_SUPPORTED; + } + if (regf->header->version.minor < 3) { + /* Store LI */ + struct li_block li; + ZERO_STRUCT(li); + li.header = "li"; + li.key_count = 1; + + li.nk_offset = talloc_array(regf, uint32_t, 1); + W_ERROR_HAVE_NO_MEMORY(li.nk_offset); + li.nk_offset[0] = key_offset; + + *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_li_block, &li); + + talloc_free(li.nk_offset); + } else if (regf->header->version.minor == 3 || regf->header->version.minor == 4) { + /* Store LF */ + struct lf_block lf; + ZERO_STRUCT(lf); + lf.header = "lf"; + lf.key_count = 1; + + lf.hr = talloc_array(regf, struct hash_record, 1); + W_ERROR_HAVE_NO_MEMORY(lf.hr); + lf.hr[0].nk_offset = key_offset; + lf.hr[0].hash = talloc_strndup(lf.hr, name, 4); + W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash); + + *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_lf_block, &lf); + + talloc_free(lf.hr); + } else if (regf->header->version.minor == 5) { + /* Store LH */ + struct lh_block lh; + ZERO_STRUCT(lh); + lh.header = "lh"; + lh.key_count = 1; + + lh.hr = talloc_array(regf, struct lh_hash, 1); + W_ERROR_HAVE_NO_MEMORY(lh.hr); + lh.hr[0].nk_offset = key_offset; + lh.hr[0].base37 = regf_create_lh_hash(name); + + *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_lh_block, &lh); + + talloc_free(lh.hr); + } + return WERR_OK; + } + + data = hbin_get(regf, list_offset); + if (!data.data) { + DEBUG(0, ("Unable to find subkey list\n")); + return WERR_BADFILE; + } + + if (!strncmp((char *)data.data, "li", 2)) { + struct tdr_pull pull; + struct li_block li; + + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) { + DEBUG(0, ("Error parsing LI list\n")); + return WERR_BADFILE; + } + + if (strncmp(li.header, "li", 2) != 0) { + abort(); + DEBUG(0, ("LI header corrupt\n")); + return WERR_BADFILE; + } + + li.nk_offset = talloc_realloc(regf, li.nk_offset, uint32_t, li.key_count+1); + W_ERROR_HAVE_NO_MEMORY(li.nk_offset); + li.nk_offset[li.key_count] = key_offset; + li.key_count++; + *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_li_block, list_offset, &li); + + talloc_free(li.nk_offset); + } else if (!strncmp((char *)data.data, "lf", 2)) { + struct tdr_pull pull; + struct lf_block lf; + + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) { + DEBUG(0, ("Error parsing LF list\n")); + return WERR_BADFILE; + } + SMB_ASSERT(!strncmp(lf.header, "lf", 2)); + + lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1); + W_ERROR_HAVE_NO_MEMORY(lf.hr); + lf.hr[lf.key_count].nk_offset = key_offset; + lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4); + W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash); + lf.key_count++; + *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf); + + talloc_free(lf.hr); + } else if (!strncmp((char *)data.data, "lh", 2)) { + struct tdr_pull pull; + struct lh_block lh; + + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) { + DEBUG(0, ("Error parsing LH list\n")); + return WERR_BADFILE; + } + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); + + lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash, lh.key_count+1); + W_ERROR_HAVE_NO_MEMORY(lh.hr); + lh.hr[lh.key_count].nk_offset = key_offset; + lh.hr[lh.key_count].base37 = regf_create_lh_hash(name); + lh.key_count++; + *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lh_block, list_offset, &lh); + + talloc_free(lh.hr); + } else if (!strncmp((char *)data.data, "ri", 2)) { + /* FIXME */ + DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n")); + return WERR_NOT_SUPPORTED; + } else { + DEBUG(0, ("Cannot add to unknown subkey list\n")); + return WERR_BADFILE; + } + + return WERR_OK; +} + +static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, + uint32_t key_offset, uint32_t *ret) +{ + DATA_BLOB data; + + data = hbin_get(regf, list_offset); + if (!data.data) { + DEBUG(0, ("Unable to find subkey list\n")); + return WERR_BADFILE; + } + + if (strncmp((char *)data.data, "li", 2) == 0) { + struct li_block li; + struct tdr_pull pull; + uint16_t i; + bool found_offset = false; + + DEBUG(10, ("Subkeys in LI list\n")); + + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) { + DEBUG(0, ("Error parsing LI list\n")); + return WERR_BADFILE; + } + + SMB_ASSERT(!strncmp(li.header, "li", 2)); + + for (i = 0; i < li.key_count; i++) { + if (found_offset) { + li.nk_offset[i-1] = li.nk_offset[i]; + } + if (li.nk_offset[i] == key_offset) { + found_offset = true; + continue; + } + } + if (!found_offset) { + DEBUG(0, ("Subkey not found\n")); + return WERR_NOT_FOUND; + } + li.key_count--; + + /* If the there are no entries left, free the subkey list */ + if (li.key_count == 0) { + hbin_free(regf, list_offset); + *ret = -1; + } + + /* Store li block */ + *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_li_block, list_offset, &li); + } else if (strncmp((char *)data.data, "lf", 2) == 0) { + struct lf_block lf; + struct tdr_pull pull; + uint16_t i; + bool found_offset = false; + + DEBUG(10, ("Subkeys in LF list\n")); + + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) { + DEBUG(0, ("Error parsing LF list\n")); + return WERR_BADFILE; + } + + SMB_ASSERT(!strncmp(lf.header, "lf", 2)); + + for (i = 0; i < lf.key_count; i++) { + if (found_offset) { + lf.hr[i-1] = lf.hr[i]; + continue; + } + if (lf.hr[i].nk_offset == key_offset) { + found_offset = 1; + continue; + } + } + if (!found_offset) { + DEBUG(0, ("Subkey not found\n")); + return WERR_NOT_FOUND; + } + lf.key_count--; + + /* If the there are no entries left, free the subkey list */ + if (lf.key_count == 0) { + hbin_free(regf, list_offset); + *ret = -1; + return WERR_OK; + } + + /* Store lf block */ + *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_lf_block, list_offset, &lf); + } else if (strncmp((char *)data.data, "lh", 2) == 0) { + struct lh_block lh; + struct tdr_pull pull; + uint16_t i; + bool found_offset = false; + + DEBUG(10, ("Subkeys in LH list\n")); + + ZERO_STRUCT(pull); + pull.data = data; + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) { + DEBUG(0, ("Error parsing LF list\n")); + return WERR_BADFILE; + } + + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); + + for (i = 0; i < lh.key_count; i++) { + if (found_offset) { + lh.hr[i-1] = lh.hr[i]; + continue; + } + if (lh.hr[i].nk_offset == key_offset) { + found_offset = 1; + continue; + } + } + if (!found_offset) { + DEBUG(0, ("Subkey not found\n")); + return WERR_NOT_FOUND; + } + lh.key_count--; + + /* If the there are no entries left, free the subkey list */ + if (lh.key_count == 0) { + hbin_free(regf, list_offset); + *ret = -1; + return WERR_OK; + } + + /* Store lh block */ + *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_lh_block, list_offset, &lh); + } else if (strncmp((char *)data.data, "ri", 2) == 0) { + /* FIXME */ + DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n")); + return WERR_NOT_SUPPORTED; + } else { + DEBUG (0, ("Unknown header found in subkey list.\n")); + return WERR_BADFILE; + } + return WERR_OK; +} + +static WERROR regf_del_value (struct hive_key *key, const char *name) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + struct regf_data *regf = private_data->hive; + struct nk_block *nk = private_data->nk; + struct vk_block vk; + uint32_t vk_offset; + bool found_offset = false; + DATA_BLOB values; + uint32_t i; + + if (nk->values_offset == -1) { + return WERR_NOT_FOUND; + } + + values = hbin_get(regf, nk->values_offset); + + for (i = 0; i < nk->num_values; i++) { + if (found_offset) { + ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i]; + } else { + vk_offset = IVAL(values.data, i * 4); + if (!hbin_get_tdr(regf, vk_offset, private_data, + (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); + return WERR_BADFILE; + } + if (strcmp(vk.data_name, name) == 0) { + hbin_free(regf, vk_offset); + found_offset = true; + } + } + } + if (!found_offset) { + return WERR_NOT_FOUND; + } else { + nk->num_values--; + values.length = (nk->num_values)*4; + } + + /* Store values list and nk */ + if (nk->num_values == 0) { + hbin_free(regf, nk->values_offset); + nk->values_offset = -1; + } else { + nk->values_offset = hbin_store_resize(regf, nk->values_offset, values); + } + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk); + + return regf_save_hbin(private_data->hive); +} + + +static WERROR regf_del_key(const struct hive_key *parent, const char *name) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)parent; + struct regf_key_data *key; + struct nk_block *parent_nk; + WERROR error; + + SMB_ASSERT(private_data); + + parent_nk = private_data->nk; + + if (parent_nk->subkeys_offset == -1) { + DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n")); + return WERR_NOT_FOUND; + } + + /* Find the key */ + if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name, + (struct hive_key **)&key))) { + DEBUG(0, ("Key '%s' not found\n", name)); + return WERR_NOT_FOUND; + } + + if (key->nk->subkeys_offset != -1 || + key->nk->values_offset != -1) { + DEBUG(0, ("Key '%s' is not empty.\n", name)); + return WERR_FILE_EXISTS; + } + + /* Delete it from the subkey list. */ + error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset, + key->offset, &parent_nk->subkeys_offset); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n")); + return error; + } + + /* Re-store parent key */ + parent_nk->num_subkeys--; + hbin_store_tdr_resize(private_data->hive, + (tdr_push_fn_t) tdr_push_nk_block, + private_data->offset, parent_nk); + + if (key->nk->clsname_offset != -1) { + hbin_free(private_data->hive, key->nk->clsname_offset); + } + hbin_free(private_data->hive, key->offset); + + return regf_save_hbin(private_data->hive); +} + +static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, + const char *name, const char *classname, + struct security_descriptor *sec_desc, + struct hive_key **ret) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)parent; + struct nk_block *parent_nk = private_data->nk, nk; + struct nk_block *root; + struct regf_data *regf = private_data->hive; + uint32_t offset; + WERROR error; + + nk.header = "nk"; + nk.type = REG_SUB_KEY; + unix_to_nt_time(&nk.last_change, time(NULL)); + nk.uk1 = 0; + nk.parent_offset = private_data->offset; + nk.num_subkeys = 0; + nk.uk2 = 0; + nk.subkeys_offset = -1; + nk.unknown_offset = -1; + nk.num_values = 0; + nk.values_offset = -1; + memset(nk.unk3, 0, 5); + nk.clsname_offset = -1; /* FIXME: fill in */ + nk.clsname_length = 0; + nk.key_name = name; + + /* Get the security descriptor of the root key */ + root = talloc_zero(ctx, struct nk_block); + W_ERROR_HAVE_NO_MEMORY(root); + + if (!hbin_get_tdr(regf, regf->header->data_offset, root, + (tdr_pull_fn_t)tdr_pull_nk_block, root)) { + DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); + return WERR_GENERAL_FAILURE; + } + nk.sk_offset = root->sk_offset; + talloc_free(root); + + /* Store the new nk key */ + offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk); + + error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset, &parent_nk->subkeys_offset); + if (!W_ERROR_IS_OK(error)) { + hbin_free(regf, offset); + return error; + } + + parent_nk->num_subkeys++; + + /* Since the subkey offset of the parent can change, store it again */ + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, + nk.parent_offset, parent_nk); + + *ret = (struct hive_key *)regf_get_key(ctx, regf, offset); + + return regf_save_hbin(private_data->hive); +} + +static WERROR regf_set_value(struct hive_key *key, const char *name, + uint32_t type, const DATA_BLOB data) +{ + const struct regf_key_data *private_data = + (const struct regf_key_data *)key; + struct regf_data *regf = private_data->hive; + struct nk_block *nk = private_data->nk; + struct vk_block vk; + uint32_t i; + uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1; + DATA_BLOB values; + + ZERO_STRUCT(vk); + + /* find the value offset, if it exists */ + if (nk->values_offset != -1) { + values = hbin_get(regf, nk->values_offset); + + for (i = 0; i < nk->num_values; i++) { + tmp_vk_offset = IVAL(values.data, i * 4); + if (!hbin_get_tdr(regf, tmp_vk_offset, private_data, + (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", tmp_vk_offset)); + return WERR_GENERAL_FAILURE; + } + if (strcmp(vk.data_name, name) == 0) { + old_vk_offset = tmp_vk_offset; + break; + } + } + /* Free data, if any */ + if (!(vk.data_length & 0x80000000)) { + hbin_free(regf, vk.data_offset); + } + } + if (old_vk_offset == -1) { + vk.header = "vk"; + vk.name_length = strlen(name); + if (name != NULL && name[0] != 0) { + vk.flag = 1; + vk.data_name = name; + } else { + vk.data_name = NULL; + vk.flag = 0; + } + } + /* Set the type and data */ + vk.data_length = data.length; + vk.data_type = type; + if (type == REG_DWORD) { + vk.data_length |= 0x80000000; + vk.data_offset = *(uint32_t *)data.data; + } else { + /* Store data somewhere */ + vk.data_offset = hbin_store(regf, data); + } + if (old_vk_offset == -1) { + /* Store new vk */ + vk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_vk_block, &vk); + } else { + /* Store vk at offset */ + vk_offset = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_vk_block, old_vk_offset ,&vk); + } + + /* Re-allocate the value list */ + if (nk->values_offset == -1) { + nk->values_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_uint32, &vk_offset); + nk->num_values = 1; + } else { + + /* Change if we're changing, otherwise we're adding the value */ + if (old_vk_offset != -1) { + /* Find and overwrite the offset. */ + for (i = 0; i < nk->num_values; i++) { + if (IVAL(values.data, i * 4) == old_vk_offset) { + SIVAL(values.data, i * 4, vk_offset); + break; + } + } + } else { + /* Create a new value list */ + DATA_BLOB value_list; + + value_list.length = (nk->num_values+1)*4; + value_list.data = (void *)talloc_array(private_data, uint32_t, nk->num_values+1); + W_ERROR_HAVE_NO_MEMORY(value_list.data); + memcpy(value_list.data, values.data, nk->num_values * 4); + + SIVAL(value_list.data, nk->num_values * 4, vk_offset); + nk->num_values++; + nk->values_offset = hbin_store_resize(regf, nk->values_offset, value_list); + } + + } + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk); + return regf_save_hbin(private_data->hive); +} + +static WERROR regf_save_hbin(struct regf_data *regf) +{ + struct tdr_push *push = talloc_zero(regf, struct tdr_push); + int i; + + W_ERROR_HAVE_NO_MEMORY(push); + + if (lseek(regf->fd, 0, SEEK_SET) == -1) { + DEBUG(0, ("Error lseeking in regf file\n")); + return WERR_GENERAL_FAILURE; + } + + /* Recompute checksum */ + if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) { + DEBUG(0, ("Failed to push regf header\n")); + return WERR_GENERAL_FAILURE; + } + regf->header->chksum = regf_hdr_checksum(push->data.data); + talloc_free(push); + + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, + (tdr_push_fn_t)tdr_push_regf_hdr, regf->header))) { + DEBUG(0, ("Error writing registry file header\n")); + return WERR_GENERAL_FAILURE; + } + + if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) { + DEBUG(0, ("Error lseeking to 0x1000 in regf file\n")); + return WERR_GENERAL_FAILURE; + } + + for (i = 0; regf->hbins[i]; i++) { + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, + (tdr_push_fn_t)tdr_push_hbin_block, + regf->hbins[i]))) { + DEBUG(0, ("Error writing HBIN block\n")); + return WERR_GENERAL_FAILURE; + } + } + + return WERR_OK; +} + +WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, + int minor_version, struct hive_key **key) +{ + struct regf_data *regf; + struct regf_hdr *regf_hdr; + struct tdr_pull pull; + int i; + struct nk_block nk; + WERROR error; + + regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); + + W_ERROR_HAVE_NO_MEMORY(regf); + + DEBUG(5, ("Attempting to create registry file\n")); + + /* Get the header */ + regf->fd = creat(location, 0644); + + if (regf->fd == -1) { + DEBUG(0,("Could not create file: %s, %s\n", location, + strerror(errno))); + talloc_free(regf); + return WERR_GENERAL_FAILURE; + } + + regf_hdr = talloc_zero(regf, struct regf_hdr); + W_ERROR_HAVE_NO_MEMORY(regf_hdr); + regf_hdr->REGF_ID = "regf"; + unix_to_nt_time(®f_hdr->modtime, time(NULL)); + regf_hdr->version.major = 1; + regf_hdr->version.minor = minor_version; + regf_hdr->last_block = 0x1000; /* Block size */ + regf_hdr->description = talloc_strdup(regf_hdr, "registry created by Samba 4"); + W_ERROR_HAVE_NO_MEMORY(regf_hdr->description); + regf_hdr->chksum = 0; + + regf->header = regf_hdr; + + pull.offset = 0x1000; + + i = 0; + /* Create all hbin blocks */ + regf->hbins = talloc_array(regf, struct hbin_block *, 1); + W_ERROR_HAVE_NO_MEMORY(regf->hbins); + regf->hbins[0] = NULL; + + regf_hdr->data_offset = -1; /* FIXME */ + + nk.header = "nk"; + nk.type = REG_SUB_KEY; + unix_to_nt_time(&nk.last_change, time(NULL)); + nk.uk1 = 0; + nk.parent_offset = -1; + nk.num_subkeys = 0; + nk.uk2 = 0; + nk.subkeys_offset = -1; + nk.unknown_offset = -1; + nk.num_values = 0; + nk.values_offset = -1; + memset(nk.unk3, 0, 5); + nk.clsname_offset = -1; /* FIXME: fill in */ + nk.clsname_length = 0; + nk.key_name = ""; + + nk.sk_offset = -1; /* FIXME: fill in */ + + /* Store the new nk key */ + regf->header->data_offset = hbin_store_tdr(regf, + (tdr_push_fn_t)tdr_push_nk_block, &nk); + + *key = (struct hive_key *)regf_get_key(parent_ctx, regf, regf->header->data_offset); + + /* We can drop our own reference now that *key will have created one */ + talloc_free(regf); + + error = regf_save_hbin(regf); + if (!W_ERROR_IS_OK(error)) { + return error; + } + + return WERR_OK; +} + +WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, + const char *location, struct hive_key **key) +{ + struct regf_data *regf; + struct regf_hdr *regf_hdr; + struct tdr_pull pull; + int i; + + regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); + + W_ERROR_HAVE_NO_MEMORY(regf); + + DEBUG(5, ("Attempting to load registry file\n")); + + /* Get the header */ + regf->fd = open(location, O_RDWR); + + if (regf->fd == -1) { + DEBUG(0,("Could not load file: %s, %s\n", location, + strerror(errno))); + talloc_free(regf); + return WERR_GENERAL_FAILURE; + } + + ZERO_STRUCT(pull); + pull.data.data = (uint8_t*)fd_load(regf->fd, &pull.data.length, regf); + + if (pull.data.data == NULL) { + DEBUG(0, ("Error reading data\n")); + talloc_free(regf); + return WERR_GENERAL_FAILURE; + } + + regf_hdr = talloc(regf, struct regf_hdr); + W_ERROR_HAVE_NO_MEMORY(regf_hdr); + + if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(&pull, regf_hdr, regf_hdr))) { + talloc_free(regf); + return WERR_GENERAL_FAILURE; + } + + regf->header = regf_hdr; + + if (strcmp(regf_hdr->REGF_ID, "regf") != 0) { + DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n", + regf_hdr->REGF_ID, location)); + talloc_free(regf); + return WERR_GENERAL_FAILURE; + } + + /* Validate the header ... */ + if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) { + DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", + location, regf_hdr->chksum, + regf_hdr_checksum(pull.data.data))); + talloc_free(regf); + return WERR_GENERAL_FAILURE; + } + + pull.offset = 0x1000; + + i = 0; + /* Read in all hbin blocks */ + regf->hbins = talloc_array(regf, struct hbin_block *, 1); + W_ERROR_HAVE_NO_MEMORY(regf->hbins); + + regf->hbins[0] = NULL; + + while (pull.offset < pull.data.length && pull.offset <= regf->header->last_block) { + struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block); + + W_ERROR_HAVE_NO_MEMORY(hbin); + + if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) { + DEBUG(0, ("[%d] Error parsing HBIN block\n", i)); + talloc_free(regf); + return WERR_FOOBAR; + } + + if (strcmp(hbin->HBIN_ID, "hbin") != 0) { + DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n", i, hbin->HBIN_ID)); + talloc_free(regf); + return WERR_FOOBAR; + } + + regf->hbins[i] = hbin; + i++; + regf->hbins = talloc_realloc(regf, regf->hbins, struct hbin_block *, i+2); + regf->hbins[i] = NULL; + } + + DEBUG(1, ("%d HBIN blocks read\n", i)); + + *key = (struct hive_key *)regf_get_key(parent_ctx, regf, + regf->header->data_offset); + + /* We can drop our own reference now that *key will have created one */ + talloc_free(regf); + + return WERR_OK; +} + +static struct hive_operations reg_backend_regf = { + .name = "regf", + .get_key_info = regf_get_info, + .enum_key = regf_get_subkey_by_index, + .get_key_by_name = regf_get_subkey_by_name, + .get_value_by_name = regf_get_value_by_name, + .enum_value = regf_get_value, + .get_sec_desc = regf_get_sec_desc, + .set_sec_desc = regf_set_sec_desc, + .add_key = regf_add_key, + .set_value = regf_set_value, + .del_key = regf_del_key, + .delete_value = regf_del_value, +}; -- cgit From 6ca139026956916a4a956dd36d10d7f5a72272b8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 26 Aug 2007 22:12:02 +0000 Subject: r24684: Be a bit less verbose (This used to be commit 7a7af62dc4485d832436ed39dfba41b417ec2b10) --- source4/lib/registry/regf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 7fa71033d9..d74ffd2b4b 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1303,7 +1303,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } } if (!found_offset) { - DEBUG(0, ("Subkey not found\n")); + DEBUG(2, ("Subkey not found\n")); return WERR_NOT_FOUND; } li.key_count--; @@ -1345,7 +1345,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } } if (!found_offset) { - DEBUG(0, ("Subkey not found\n")); + DEBUG(2, ("Subkey not found\n")); return WERR_NOT_FOUND; } lf.key_count--; @@ -1487,7 +1487,7 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name) /* Find the key */ if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name, (struct hive_key **)&key))) { - DEBUG(0, ("Key '%s' not found\n", name)); + DEBUG(2, ("Key '%s' not found\n", name)); return WERR_NOT_FOUND; } -- cgit From cd962355abad90a2161765a7be7d26e63572cab7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 7 Sep 2007 15:08:14 +0000 Subject: r25000: Fix some more C++ compatibility warnings. (This used to be commit 08bb1ef643ab906f1645cf6f32763dc73b1884e4) --- source4/lib/registry/regf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index d74ffd2b4b..0c40773daa 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1664,7 +1664,7 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, DATA_BLOB value_list; value_list.length = (nk->num_values+1)*4; - value_list.data = (void *)talloc_array(private_data, uint32_t, nk->num_values+1); + value_list.data = talloc_array(private_data, uint32_t, nk->num_values+1); W_ERROR_HAVE_NO_MEMORY(value_list.data); memcpy(value_list.data, values.data, nk->num_values * 4); -- cgit From 7e297ecfa4db2c7ab720a63c7764bc0e20f8058c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 9 Sep 2007 19:34:30 +0000 Subject: r25047: Fix more warnings. (This used to be commit 69de86d2d2e49439760fbc61901eb87fb7fc5d55) --- source4/lib/registry/regf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 0c40773daa..17914a8f7c 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1664,7 +1664,7 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, DATA_BLOB value_list; value_list.length = (nk->num_values+1)*4; - value_list.data = talloc_array(private_data, uint32_t, nk->num_values+1); + value_list.data = (uint8_t *)talloc_array(private_data, uint32_t, nk->num_values+1); W_ERROR_HAVE_NO_MEMORY(value_list.data); memcpy(value_list.data, values.data, nk->num_values * 4); -- cgit From cc8f4eb3cd9b3bc4e3f3d61bfad240147e8a4e5e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 6 Oct 2007 00:17:44 +0000 Subject: r25544: Cleanup some more indents in lib/registry. Guenther (This used to be commit 0d9826dc54057db2cfebcb806e5442c4dcf60daa) --- source4/lib/registry/regf.c | 722 +++++++++++++++++++++++++------------------- 1 file changed, 419 insertions(+), 303 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 17914a8f7c..2dd27ca33d 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -8,15 +8,15 @@ 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 . */ - + #include "includes.h" #include "lib/registry/hive.h" #include "system/filesys.h" @@ -28,7 +28,7 @@ static struct hive_operations reg_backend_regf; /** - * There are several places on the web where the REGF format is explained; + * There are several places on the web where the REGF format is explained; * * TODO: Links */ @@ -53,18 +53,18 @@ static WERROR regf_save_hbin(struct regf_data *data); struct regf_key_data { struct hive_key key; - struct regf_data *hive; + struct regf_data *hive; uint32_t offset; struct nk_block *nk; }; -static struct hbin_block *hbin_by_offset(const struct regf_data *data, - uint32_t offset, uint32_t *rel_offset) +static struct hbin_block *hbin_by_offset(const struct regf_data *data, + uint32_t offset, uint32_t *rel_offset) { int i; for (i = 0; data->hbins[i]; i++) { - if (offset >= data->hbins[i]->offset_from_first && + if (offset >= data->hbins[i]->offset_from_first && offset < data->hbins[i]->offset_from_first+ data->hbins[i]->offset_to_next) { if (rel_offset != NULL) @@ -84,7 +84,7 @@ static uint32_t regf_hdr_checksum(const uint8_t *buffer) { uint32_t checksum = 0, x; int i; - + for (i = 0; i < 0x01FB; i+= 4) { x = IVAL(buffer, i); checksum ^= x; @@ -122,14 +122,14 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) ret.length = (ret.length ^ 0xffffffff) + 1; ret.length -= 4; /* 4 bytes for the length... */ - ret.data = hbin->data + + ret.data = hbin->data + (offset - hbin->offset_from_first - 0x20) + 4; - + return ret; } -static bool hbin_get_tdr (struct regf_data *regf, uint32_t offset, - TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p) +static bool hbin_get_tdr(struct regf_data *regf, uint32_t offset, + TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p) { struct tdr_pull pull; @@ -140,9 +140,10 @@ static bool hbin_get_tdr (struct regf_data *regf, uint32_t offset, DEBUG(1, ("Unable to get data at 0x%04x\n", offset)); return false; } - + if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) { - DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset)); + DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", + offset)); return false; } @@ -150,8 +151,8 @@ static bool hbin_get_tdr (struct regf_data *regf, uint32_t offset, } /* Allocate some new data */ -static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size, - uint32_t *offset) +static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size, + uint32_t *offset) { DATA_BLOB ret; uint32_t rel_offset = -1; /* Relative offset ! */ @@ -190,13 +191,15 @@ static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size, my_size = -my_size; } else if (my_size == size) { /* exact match */ rel_offset = j; - DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n", size)); + DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n", + size)); break; } else if (my_size > size) { /* data will remain */ rel_offset = j; /* Split this block and mark the next block as free */ - SIVAL(hbin->data, rel_offset+size, my_size-size); - DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n", my_size, size)); + SIVAL(hbin->data, rel_offset+size, my_size-size); + DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n", + my_size, size)); break; } } @@ -204,12 +207,14 @@ static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size, if (rel_offset != -1) break; } - - /* No space available in previous hbins, + + /* No space available in previous hbins, * allocate new one */ - if (data->hbins[i] == NULL) { - DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n", size)); - data->hbins = talloc_realloc(data, data->hbins, struct hbin_block *, i+2); + if (data->hbins[i] == NULL) { + DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n", + size)); + data->hbins = talloc_realloc(data, data->hbins, + struct hbin_block *, i+2); hbin = talloc(data->hbins, struct hbin_block); SMB_ASSERT(hbin != NULL); @@ -255,11 +260,12 @@ static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob) return ret; } -static uint32_t hbin_store_tdr (struct regf_data *data, tdr_push_fn_t push_fn, void *p) +static uint32_t hbin_store_tdr(struct regf_data *data, + tdr_push_fn_t push_fn, void *p) { struct tdr_push *push = talloc_zero(data, struct tdr_push); uint32_t ret; - + if (NT_STATUS_IS_ERR(push_fn(push, p))) { DEBUG(0, ("Error during push\n")); return -1; @@ -278,26 +284,27 @@ static void hbin_free (struct regf_data *data, uint32_t offset) { int32_t size; uint32_t rel_offset; - int32_t next_size; + int32_t next_size; struct hbin_block *hbin; SMB_ASSERT (offset > 0); - + hbin = hbin_by_offset(data, offset, &rel_offset); if (hbin == NULL) return; - + /* Get original size */ size = IVALS(hbin->data, rel_offset); if (size > 0) { - DEBUG(1, ("Trying to free already freed block at 0x%04x\n", offset)); + DEBUG(1, ("Trying to free already freed block at 0x%04x\n", + offset)); return; } /* Mark as unused */ size = -size; - + /* If the next block is free, merge into big free block */ if (rel_offset + size < hbin->offset_to_next) { next_size = IVALS(hbin->data, rel_offset+size); @@ -312,13 +319,14 @@ static void hbin_free (struct regf_data *data, uint32_t offset) /** * Store a data blob data was already stored, but has changed in size - * Will try to save it at the current location if possible, otherwise + * Will try to save it at the current location if possible, otherwise * does a free + store */ -static uint32_t hbin_store_resize(struct regf_data *data, - uint32_t orig_offset, DATA_BLOB blob) +static uint32_t hbin_store_resize(struct regf_data *data, + uint32_t orig_offset, DATA_BLOB blob) { uint32_t rel_offset; - struct hbin_block *hbin = hbin_by_offset(data, orig_offset, &rel_offset); + struct hbin_block *hbin = hbin_by_offset(data, orig_offset, + &rel_offset); int32_t my_size; int32_t orig_size; int32_t needed_size; @@ -343,7 +351,8 @@ static uint32_t hbin_store_resize(struct regf_data *data, * and free/merge it */ if (orig_size - needed_size > 0x4) { SIVALS(hbin->data, rel_offset, -needed_size); - SIVALS(hbin->data, rel_offset + needed_size, needed_size-orig_size); + SIVALS(hbin->data, rel_offset + needed_size, + needed_size-orig_size); hbin_free(data, orig_offset + needed_size); } return orig_offset; @@ -357,7 +366,7 @@ static uint32_t hbin_store_resize(struct regf_data *data, break; my_size = IVALS(hbin->data, i); - + if (my_size == 0x0) { DEBUG(0, ("Invalid zero-length block! File is corrupt.\n")); break; @@ -367,7 +376,8 @@ static uint32_t hbin_store_resize(struct regf_data *data, if (possible_size >= blob.length) { SIVAL(hbin->data, rel_offset, -possible_size); - memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length); + memcpy(hbin->data + rel_offset + 0x4, + blob.data, blob.length); return orig_offset; } } @@ -376,12 +386,13 @@ static uint32_t hbin_store_resize(struct regf_data *data, return hbin_store(data, blob); } -static uint32_t hbin_store_tdr_resize (struct regf_data *regf, tdr_push_fn_t push_fn, - uint32_t orig_offset, void *p) +static uint32_t hbin_store_tdr_resize(struct regf_data *regf, + tdr_push_fn_t push_fn, + uint32_t orig_offset, void *p) { struct tdr_push *push = talloc_zero(regf, struct tdr_push); uint32_t ret; - + if (NT_STATUS_IS_ERR(push_fn(push, p))) { DEBUG(0, ("Error during push\n")); return -1; @@ -394,13 +405,13 @@ static uint32_t hbin_store_tdr_resize (struct regf_data *regf, tdr_push_fn_t pus return ret; } -static uint32_t regf_create_lh_hash(const char *name) +static uint32_t regf_create_lh_hash(const char *name) { char *hash_name; uint32_t ret = 0; uint16_t i; - hash_name = strupper_talloc(NULL, name); + hash_name = strupper_talloc(NULL, name); for (i = 0; *(hash_name + i) != 0; i++) { ret *= 37; ret += *(hash_name + i); @@ -409,14 +420,14 @@ static uint32_t regf_create_lh_hash(const char *name) return ret; } -static WERROR regf_get_info (TALLOC_CTX *mem_ctx, - const struct hive_key *key, - const char **classname, - uint32_t *num_subkeys, - uint32_t *num_values, - NTTIME *last_mod_time) +static WERROR regf_get_info(TALLOC_CTX *mem_ctx, + const struct hive_key *key, + const char **classname, + uint32_t *num_subkeys, + uint32_t *num_values, + NTTIME *last_mod_time) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; if (num_subkeys != NULL) @@ -427,22 +438,23 @@ static WERROR regf_get_info (TALLOC_CTX *mem_ctx, if (classname != NULL) { if (private_data->nk->clsname_offset != -1) { - DATA_BLOB data = hbin_get(private_data->hive, - private_data->nk->clsname_offset); - *classname = talloc_strndup(mem_ctx, - (char*)data.data, private_data->nk->clsname_length); - } else + DATA_BLOB data = hbin_get(private_data->hive, + private_data->nk->clsname_offset); + *classname = talloc_strndup(mem_ctx, + (char*)data.data, + private_data->nk->clsname_length); + } else *classname = NULL; } /* TODO: Last mod time */ - + return WERR_OK; } -static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, - struct regf_data *regf, - uint32_t offset) +static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, + struct regf_data *regf, + uint32_t offset) { struct nk_block *nk; struct regf_key_data *ret; @@ -457,7 +469,8 @@ static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, ret->nk = nk; - if (!hbin_get_tdr(regf, offset, nk, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { + if (!hbin_get_tdr(regf, offset, nk, + (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return NULL; } @@ -472,11 +485,11 @@ static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, } -static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, - int idx, const char **name, - uint32_t *data_type, DATA_BLOB *data) +static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, + int idx, const char **name, + uint32_t *data_type, DATA_BLOB *data) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct vk_block *vk; struct regf_data *regf = private_data->hive; @@ -500,8 +513,9 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, vk = talloc(NULL, struct vk_block); W_ERROR_HAVE_NO_MEMORY(vk); - - if (!hbin_get_tdr(regf, vk_offset, vk, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { + + if (!hbin_get_tdr(regf, vk_offset, vk, + (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); talloc_free(vk); return WERR_GENERAL_FAILURE; @@ -514,7 +528,7 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, if (data_type != NULL) *data_type = vk->data_type; - if (vk->data_length & 0x80000000) { + if (vk->data_length & 0x80000000) { vk->data_length &=~0x80000000; data->data = (uint8_t *)&vk->data_offset; data->length = vk->data_length; @@ -527,13 +541,13 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, } talloc_free(vk); - + return WERR_OK; } -static WERROR regf_get_value_by_name (TALLOC_CTX *mem_ctx, - struct hive_key *key, const char *name, - uint32_t *type, DATA_BLOB *data) +static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx, + struct hive_key *key, const char *name, + uint32_t *type, DATA_BLOB *data) { int i; const char *vname; @@ -541,24 +555,25 @@ static WERROR regf_get_value_by_name (TALLOC_CTX *mem_ctx, /* FIXME: Do binary search? Is this list sorted at all? */ - for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i, - &vname, type, data)); i++) { + for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i, + &vname, type, data)); + i++) { if (!strcmp(vname, name)) return WERR_OK; - } + } if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_NOT_FOUND; return error; } - -static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, - const struct hive_key *key, - uint32_t idx, const char **name, - const char **classname, - NTTIME *last_mod_time) + +static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, + const struct hive_key *key, + uint32_t idx, const char **name, + const char **classname, + NTTIME *last_mod_time) { DATA_BLOB data; struct regf_key_data *ret; @@ -594,7 +609,7 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, return WERR_GENERAL_FAILURE; } key_off = li.nk_offset[idx]; - + } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; struct tdr_pull pull; @@ -618,17 +633,17 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, } else if (!strncmp((char *)data.data, "lh", 2)) { struct lh_block lh; struct tdr_pull pull; - + DEBUG(10, ("Subkeys in LH list\n")); ZERO_STRUCT(pull); pull.data = data; - + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list\n")); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(lh.header, "lh", 2)); - + if (lh.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; @@ -639,41 +654,43 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, struct tdr_pull pull; uint16_t i; uint16_t sublist_count = 0; - + DEBUG(10, ("Subkeys in RI list\n")); ZERO_STRUCT(pull); pull.data = data; - + if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) { DEBUG(0, ("Error parsing RI list\n")); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(ri.header, "ri", 2)); - + for (i = 0; i < ri.key_count; i++) { DATA_BLOB list_data; - + /* Get sublist data blob */ list_data = hbin_get(private_data->hive, ri.offset[i]); if (!list_data.data) { DEBUG(0, ("Error getting RI list.")); return WERR_GENERAL_FAILURE; } - + ZERO_STRUCT(pull); pull.data = list_data; - + if (!strncmp((char *)list_data.data, "li", 2)) { struct li_block li; DEBUG(10, ("Subkeys in RI->LI list\n")); - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, + nk, + &li))) { DEBUG(0, ("Error parsing LI list from RI\n")); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(li.header, "li", 2)); - + /* Advance to next sublist if necessary */ if (idx >= sublist_count + li.key_count) { sublist_count += li.key_count; @@ -684,10 +701,12 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, break; } else if (!strncmp((char *)list_data.data, "lh", 2)) { struct lh_block lh; - + DEBUG(10, ("Subkeys in RI->LH list\n")); - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, + nk, + &lh))) { DEBUG(0, ("Error parsing LH list from RI\n")); return WERR_GENERAL_FAILURE; } @@ -706,15 +725,15 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, return WERR_GENERAL_FAILURE; } - + } - + if (idx > sublist_count) { return WERR_NO_MORE_ITEMS; } } else { - DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", + DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", nk->subkeys_offset, data.data[0], data.data[1])); return WERR_GENERAL_FAILURE; } @@ -723,11 +742,12 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, if (classname != NULL) { if (ret->nk->clsname_offset != -1) { - DATA_BLOB db = hbin_get(ret->hive, - ret->nk->clsname_offset); - *classname = talloc_strndup(ctx, - (char*)db.data, ret->nk->clsname_length); - } else + DATA_BLOB db = hbin_get(ret->hive, + ret->nk->clsname_offset); + *classname = talloc_strndup(ctx, + (char*)db.data, + ret->nk->clsname_length); + } else *classname = NULL; } @@ -742,16 +762,17 @@ static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, return WERR_OK; } -static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, - const struct hive_key *key, uint32_t offset, - const char *name, uint32_t *ret) +static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, + const struct hive_key *key, + uint32_t offset, + const char *name, uint32_t *ret) { DATA_BLOB subkey_data; struct nk_block subkey; struct tdr_pull pull; - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; - + subkey_data = hbin_get(private_data->hive, offset); if (!subkey_data.data) { DEBUG(0, ("Unable to retrieve subkey HBIN\n")); @@ -760,7 +781,7 @@ static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, ZERO_STRUCT(pull); pull.data = subkey_data; - + if (NT_STATUS_IS_ERR(tdr_pull_nk_block(&pull, ctx, &subkey))) { DEBUG(0, ("Error parsing NK structure.\n")); return WERR_GENERAL_FAILURE; @@ -778,14 +799,14 @@ static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, } return WERR_OK; } - -static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, - const struct hive_key *key, - const char *name, - struct hive_key **ret) + +static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, + const struct hive_key *key, + const char *name, + struct hive_key **ret) { DATA_BLOB data; - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct nk_block *nk = private_data->nk; uint32_t key_off = 0; @@ -804,7 +825,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(10, ("Subkeys in LI list\n")); ZERO_STRUCT(pull); pull.data = data; - + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { DEBUG(0, ("Error parsing LI list\n")); return WERR_GENERAL_FAILURE; @@ -815,9 +836,12 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } - + for (i = 0; i < li.key_count; i++) { - W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, li.nk_offset[i], name, &key_off)); + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, + li.nk_offset[i], + name, + &key_off)); if (key_off != 0) break; } @@ -831,7 +855,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(10, ("Subkeys in LF list\n")); ZERO_STRUCT(pull); pull.data = data; - + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) { DEBUG(0, ("Error parsing LF list\n")); return WERR_GENERAL_FAILURE; @@ -842,12 +866,16 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } - + for (i = 0; i < lf.key_count; i++) { if (strncmp(lf.hr[i].hash, name, 4)) { continue; } - W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lf.hr[i].nk_offset, name, &key_off)); + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, + key, + lf.hr[i].nk_offset, + name, + &key_off)); if (key_off != 0) break; } @@ -862,7 +890,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(10, ("Subkeys in LH list\n")); ZERO_STRUCT(pull); pull.data = data; - + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list\n")); return WERR_GENERAL_FAILURE; @@ -873,16 +901,20 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } - + hash = regf_create_lh_hash(name); for (i = 0; i < lh.key_count; i++) { if (lh.hr[i].base37 != hash) { continue; } - W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lh.hr[i].nk_offset, name, &key_off)); + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, + key, + lh.hr[i].nk_offset, + name, + &key_off)); if (key_off != 0) break; - } + } if (key_off == 0) return WERR_NOT_FOUND; } else if (!strncmp((char *)data.data, "ri", 2)) { @@ -893,46 +925,52 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, DEBUG(10, ("Subkeys in RI list\n")); ZERO_STRUCT(pull); pull.data = data; - + if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) { DEBUG(0, ("Error parsing RI list\n")); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(ri.header, "ri", 2)); - + for (i = 0; i < ri.key_count; i++) { DATA_BLOB list_data; - + /* Get sublist data blob */ list_data = hbin_get(private_data->hive, ri.offset[i]); if (list_data.data == NULL) { DEBUG(0, ("Error getting RI list.")); return WERR_GENERAL_FAILURE; } - + ZERO_STRUCT(pull); pull.data = list_data; - + if (!strncmp((char *)list_data.data, "li", 2)) { struct li_block li; - - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, + nk, + &li))) { DEBUG(0, ("Error parsing LI list from RI\n")); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(li.header, "li", 2)); - + for (j = 0; j < li.key_count; j++) { - W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, - li.nk_offset[j], name, &key_off)); + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, + li.nk_offset[j], + name, + &key_off)); if (key_off) break; } } else if (!strncmp((char *)list_data.data, "lh", 2)) { struct lh_block lh; uint32_t hash; - - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, + nk, + &lh))) { DEBUG(0, ("Error parsing LH list from RI\n")); return WERR_GENERAL_FAILURE; } @@ -943,8 +981,10 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, if (lh.hr[j].base37 != hash) { continue; } - W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, - lh.hr[j].nk_offset, name, &key_off)); + W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, + lh.hr[j].nk_offset, + name, + &key_off)); if (key_off) break; } @@ -959,14 +999,15 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, return WERR_GENERAL_FAILURE; } - *ret = (struct hive_key *)regf_get_key (ctx, private_data->hive, key_off); + *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive, + key_off); return WERR_OK; } -static WERROR regf_set_sec_desc (struct hive_key *key, - const struct security_descriptor *sec_desc) +static WERROR regf_set_sec_desc(struct hive_key *key, + const struct security_descriptor *sec_desc) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct sk_block cur_sk, sk, new_sk; struct regf_data *regf = private_data->hive; @@ -976,47 +1017,51 @@ static WERROR regf_set_sec_desc (struct hive_key *key, bool update_cur_sk = false; /* Get the root nk */ - hbin_get_tdr(regf, regf->header->data_offset, regf, - (tdr_pull_fn_t) tdr_pull_nk_block, &root); + hbin_get_tdr(regf, regf->header->data_offset, regf, + (tdr_pull_fn_t) tdr_pull_nk_block, &root); /* Push the security descriptor to a blob */ - if (NT_STATUS_IS_ERR(ndr_push_struct_blob(&data, regf, sec_desc, - (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { + if (NT_STATUS_IS_ERR(ndr_push_struct_blob(&data, regf, sec_desc, + (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { DEBUG(0, ("Unable to push security descriptor\n")); return WERR_GENERAL_FAILURE; } - /* Get the current security descriptor for the key */ - if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf, - (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) { + /* Get the current security descriptor for the key */ + if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) { DEBUG(0, ("Unable to find security descriptor for current key\n")); return WERR_BADFILE; } /* If there's no change, change nothing. */ - if (memcmp(data.data, cur_sk.sec_desc, MIN(data.length, cur_sk.rec_size)) == 0) { + if (memcmp(data.data, cur_sk.sec_desc, + MIN(data.length, cur_sk.rec_size)) == 0) { return WERR_OK; } - /* Delete the current sk if only this key is using it */ + /* Delete the current sk if only this key is using it */ if (cur_sk.ref_cnt == 1) { - /* Get the previous security descriptor for the key */ - if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf, - (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + /* Get the previous security descriptor for the key */ + if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find prev security descriptor for current key\n")); return WERR_BADFILE; } /* Change and store the previous security descriptor */ sk.next_offset = cur_sk.next_offset; - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk); - - /* Get the next security descriptor for the key */ - if (!hbin_get_tdr(regf, cur_sk.next_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, + cur_sk.prev_offset, &sk); + + /* Get the next security descriptor for the key */ + if (!hbin_get_tdr(regf, cur_sk.next_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find next security descriptor for current key\n")); return WERR_BADFILE; } /* Change and store the next security descriptor */ sk.prev_offset = cur_sk.prev_offset; - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.next_offset, &sk); + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, + cur_sk.next_offset, &sk); hbin_free(regf, private_data->nk->sk_offset); } else { @@ -1029,20 +1074,26 @@ static WERROR regf_set_sec_desc (struct hive_key *key, do { cur_sk_offset = sk_offset; - if (!hbin_get_tdr(regf, sk_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + if (!hbin_get_tdr(regf, sk_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor\n")); return WERR_BADFILE; } if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) { private_data->nk->sk_offset = sk_offset; sk.ref_cnt++; - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, sk_offset, &sk); - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, private_data->nk); + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_sk_block, + sk_offset, &sk); + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_nk_block, + private_data->offset, + private_data->nk); return WERR_OK; } sk_offset = sk.next_offset; } while (sk_offset != root.sk_offset); - + ZERO_STRUCT(new_sk); new_sk.header = "sk"; new_sk.prev_offset = cur_sk_offset; @@ -1050,8 +1101,10 @@ static WERROR regf_set_sec_desc (struct hive_key *key, new_sk.ref_cnt = 1; new_sk.rec_size = data.length; new_sk.sec_desc = data.data; - - sk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_sk_block, &new_sk); + + sk_offset = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_sk_block, + &new_sk); if (sk_offset == -1) { DEBUG(0, ("Error storing sk block\n")); return WERR_GENERAL_FAILURE; @@ -1059,47 +1112,58 @@ static WERROR regf_set_sec_desc (struct hive_key *key, private_data->nk->sk_offset = sk_offset; if (update_cur_sk) { - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, private_data->nk->sk_offset, &cur_sk); + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_sk_block, + private_data->nk->sk_offset, &cur_sk); } - /* Get the previous security descriptor for the key */ - if (!hbin_get_tdr(regf, new_sk.prev_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + /* Get the previous security descriptor for the key */ + if (!hbin_get_tdr(regf, new_sk.prev_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor for previous key\n")); return WERR_BADFILE; } /* Change and store the previous security descriptor */ sk.next_offset = sk_offset; - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk); - - /* Get the next security descriptor for the key (always root, as we append) */ - if (!hbin_get_tdr(regf, new_sk.next_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_sk_block, + cur_sk.prev_offset, &sk); + + /* Get the next security descriptor for the key (always root, as we append) */ + if (!hbin_get_tdr(regf, new_sk.next_offset, regf, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor for current key\n")); return WERR_BADFILE; } /* Change and store the next security descriptor (always root, as we append) */ sk.prev_offset = sk_offset; - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, root.sk_offset, &sk); + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_sk_block, + root.sk_offset, &sk); /* Store the nk. */ - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, private_data->offset, private_data->nk); + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_sk_block, + private_data->offset, private_data->nk); return WERR_OK; } -static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, - struct security_descriptor **sd) +static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, + struct security_descriptor **sd) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct sk_block sk; struct regf_data *regf = private_data->hive; DATA_BLOB data; - if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { + if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx, + (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor\n")); return WERR_GENERAL_FAILURE; } - + if (strcmp(sk.header, "sk") != 0) { DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header)); return WERR_GENERAL_FAILURE; @@ -1110,7 +1174,8 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, data.data = sk.sec_desc; data.length = sk.rec_size; - if (NT_STATUS_IS_ERR(ndr_pull_struct_blob(&data, ctx, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { + if (NT_STATUS_IS_ERR(ndr_pull_struct_blob(&data, ctx, *sd, + (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { DEBUG(0, ("Error parsing security descriptor\n")); return WERR_GENERAL_FAILURE; } @@ -1118,45 +1183,51 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, return WERR_OK; } -static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, - const char *name, uint32_t key_offset, uint32_t *ret) +static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, + const char *name, + uint32_t key_offset, uint32_t *ret) { DATA_BLOB data; /* Create a new key if necessary */ - if (list_offset == -1) { + if (list_offset == -1) { if (regf->header->version.major != 1) { DEBUG(0, ("Can't store keys in unknown registry format\n")); return WERR_NOT_SUPPORTED; } - if (regf->header->version.minor < 3) { + if (regf->header->version.minor < 3) { /* Store LI */ struct li_block li; ZERO_STRUCT(li); li.header = "li"; - li.key_count = 1; + li.key_count = 1; li.nk_offset = talloc_array(regf, uint32_t, 1); W_ERROR_HAVE_NO_MEMORY(li.nk_offset); li.nk_offset[0] = key_offset; - *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_li_block, &li); + *ret = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_li_block, + &li); talloc_free(li.nk_offset); - } else if (regf->header->version.minor == 3 || regf->header->version.minor == 4) { + } else if (regf->header->version.minor == 3 || + regf->header->version.minor == 4) { /* Store LF */ struct lf_block lf; ZERO_STRUCT(lf); lf.header = "lf"; lf.key_count = 1; - + lf.hr = talloc_array(regf, struct hash_record, 1); W_ERROR_HAVE_NO_MEMORY(lf.hr); lf.hr[0].nk_offset = key_offset; lf.hr[0].hash = talloc_strndup(lf.hr, name, 4); W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash); - *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_lf_block, &lf); + *ret = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_lf_block, + &lf); talloc_free(lf.hr); } else if (regf->header->version.minor == 5) { @@ -1165,19 +1236,21 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, ZERO_STRUCT(lh); lh.header = "lh"; lh.key_count = 1; - + lh.hr = talloc_array(regf, struct lh_hash, 1); W_ERROR_HAVE_NO_MEMORY(lh.hr); lh.hr[0].nk_offset = key_offset; lh.hr[0].base37 = regf_create_lh_hash(name); - *ret = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_lh_block, &lh); + *ret = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_lh_block, + &lh); talloc_free(lh.hr); } return WERR_OK; - } - + } + data = hbin_get(regf, list_offset); if (!data.data) { DEBUG(0, ("Unable to find subkey list\n")); @@ -1187,7 +1260,7 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, if (!strncmp((char *)data.data, "li", 2)) { struct tdr_pull pull; struct li_block li; - + ZERO_STRUCT(pull); pull.data = data; @@ -1201,13 +1274,16 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, DEBUG(0, ("LI header corrupt\n")); return WERR_BADFILE; } - - li.nk_offset = talloc_realloc(regf, li.nk_offset, uint32_t, li.key_count+1); + + li.nk_offset = talloc_realloc(regf, li.nk_offset, + uint32_t, li.key_count+1); W_ERROR_HAVE_NO_MEMORY(li.nk_offset); li.nk_offset[li.key_count] = key_offset; li.key_count++; - *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_li_block, list_offset, &li); - + *ret = hbin_store_tdr_resize(regf, + (tdr_push_fn_t)tdr_push_li_block, + list_offset, &li); + talloc_free(li.nk_offset); } else if (!strncmp((char *)data.data, "lf", 2)) { struct tdr_pull pull; @@ -1221,14 +1297,17 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, return WERR_BADFILE; } SMB_ASSERT(!strncmp(lf.header, "lf", 2)); - - lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1); + + lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, + lf.key_count+1); W_ERROR_HAVE_NO_MEMORY(lf.hr); lf.hr[lf.key_count].nk_offset = key_offset; lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4); W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash); lf.key_count++; - *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf); + *ret = hbin_store_tdr_resize(regf, + (tdr_push_fn_t)tdr_push_lf_block, + list_offset, &lf); talloc_free(lf.hr); } else if (!strncmp((char *)data.data, "lh", 2)) { @@ -1243,13 +1322,16 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, return WERR_BADFILE; } SMB_ASSERT(!strncmp(lh.header, "lh", 2)); - - lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash, lh.key_count+1); + + lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash, + lh.key_count+1); W_ERROR_HAVE_NO_MEMORY(lh.hr); lh.hr[lh.key_count].nk_offset = key_offset; lh.hr[lh.key_count].base37 = regf_create_lh_hash(name); lh.key_count++; - *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lh_block, list_offset, &lh); + *ret = hbin_store_tdr_resize(regf, + (tdr_push_fn_t)tdr_push_lh_block, + list_offset, &lh); talloc_free(lh.hr); } else if (!strncmp((char *)data.data, "ri", 2)) { @@ -1260,12 +1342,12 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, DEBUG(0, ("Cannot add to unknown subkey list\n")); return WERR_BADFILE; } - + return WERR_OK; } -static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, - uint32_t key_offset, uint32_t *ret) +static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, + uint32_t key_offset, uint32_t *ret) { DATA_BLOB data; @@ -1280,17 +1362,17 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, struct tdr_pull pull; uint16_t i; bool found_offset = false; - + DEBUG(10, ("Subkeys in LI list\n")); - + ZERO_STRUCT(pull); - pull.data = data; - + pull.data = data; + if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) { DEBUG(0, ("Error parsing LI list\n")); return WERR_BADFILE; } - + SMB_ASSERT(!strncmp(li.header, "li", 2)); for (i = 0; i < li.key_count; i++) { @@ -1315,23 +1397,25 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } /* Store li block */ - *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_li_block, list_offset, &li); + *ret = hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_li_block, + list_offset, &li); } else if (strncmp((char *)data.data, "lf", 2) == 0) { struct lf_block lf; struct tdr_pull pull; uint16_t i; bool found_offset = false; - + DEBUG(10, ("Subkeys in LF list\n")); - + ZERO_STRUCT(pull); - pull.data = data; - + pull.data = data; + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) { DEBUG(0, ("Error parsing LF list\n")); return WERR_BADFILE; } - + SMB_ASSERT(!strncmp(lf.header, "lf", 2)); for (i = 0; i < lf.key_count; i++) { @@ -1349,7 +1433,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, return WERR_NOT_FOUND; } lf.key_count--; - + /* If the there are no entries left, free the subkey list */ if (lf.key_count == 0) { hbin_free(regf, list_offset); @@ -1358,23 +1442,25 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } /* Store lf block */ - *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_lf_block, list_offset, &lf); + *ret = hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_lf_block, + list_offset, &lf); } else if (strncmp((char *)data.data, "lh", 2) == 0) { struct lh_block lh; struct tdr_pull pull; uint16_t i; bool found_offset = false; - + DEBUG(10, ("Subkeys in LH list\n")); - + ZERO_STRUCT(pull); - pull.data = data; - + pull.data = data; + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) { DEBUG(0, ("Error parsing LF list\n")); return WERR_BADFILE; } - + SMB_ASSERT(!strncmp(lh.header, "lh", 2)); for (i = 0; i < lh.key_count; i++) { @@ -1392,7 +1478,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, return WERR_NOT_FOUND; } lh.key_count--; - + /* If the there are no entries left, free the subkey list */ if (lh.key_count == 0) { hbin_free(regf, list_offset); @@ -1401,7 +1487,9 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } /* Store lh block */ - *ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_lh_block, list_offset, &lh); + *ret = hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_lh_block, + list_offset, &lh); } else if (strncmp((char *)data.data, "ri", 2) == 0) { /* FIXME */ DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n")); @@ -1415,7 +1503,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, static WERROR regf_del_value (struct hive_key *key, const char *name) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct regf_data *regf = private_data->hive; struct nk_block *nk = private_data->nk; @@ -1436,11 +1524,13 @@ static WERROR regf_del_value (struct hive_key *key, const char *name) ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i]; } else { vk_offset = IVAL(values.data, i * 4); - if (!hbin_get_tdr(regf, vk_offset, private_data, - (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) { - DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); + if (!hbin_get_tdr(regf, vk_offset, private_data, + (tdr_pull_fn_t)tdr_pull_vk_block, + &vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", + vk_offset)); return WERR_BADFILE; - } + } if (strcmp(vk.data_name, name) == 0) { hbin_free(regf, vk_offset); found_offset = true; @@ -1458,10 +1548,13 @@ static WERROR regf_del_value (struct hive_key *key, const char *name) if (nk->num_values == 0) { hbin_free(regf, nk->values_offset); nk->values_offset = -1; - } else { - nk->values_offset = hbin_store_resize(regf, nk->values_offset, values); + } else { + nk->values_offset = hbin_store_resize(regf, + nk->values_offset, + values); } - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk); + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, + private_data->offset, nk); return regf_save_hbin(private_data->hive); } @@ -1469,14 +1562,14 @@ static WERROR regf_del_value (struct hive_key *key, const char *name) static WERROR regf_del_key(const struct hive_key *parent, const char *name) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)parent; struct regf_key_data *key; struct nk_block *parent_nk; WERROR error; SMB_ASSERT(private_data); - + parent_nk = private_data->nk; if (parent_nk->subkeys_offset == -1) { @@ -1485,21 +1578,21 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name) } /* Find the key */ - if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name, - (struct hive_key **)&key))) { + if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name, + (struct hive_key **)&key))) { DEBUG(2, ("Key '%s' not found\n", name)); return WERR_NOT_FOUND; } - - if (key->nk->subkeys_offset != -1 || + + if (key->nk->subkeys_offset != -1 || key->nk->values_offset != -1) { DEBUG(0, ("Key '%s' is not empty.\n", name)); return WERR_FILE_EXISTS; } - + /* Delete it from the subkey list. */ - error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset, - key->offset, &parent_nk->subkeys_offset); + error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset, + key->offset, &parent_nk->subkeys_offset); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n")); return error; @@ -1507,9 +1600,9 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name) /* Re-store parent key */ parent_nk->num_subkeys--; - hbin_store_tdr_resize(private_data->hive, - (tdr_push_fn_t) tdr_push_nk_block, - private_data->offset, parent_nk); + hbin_store_tdr_resize(private_data->hive, + (tdr_push_fn_t) tdr_push_nk_block, + private_data->offset, parent_nk); if (key->nk->clsname_offset != -1) { hbin_free(private_data->hive, key->nk->clsname_offset); @@ -1519,12 +1612,12 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name) return regf_save_hbin(private_data->hive); } -static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, - const char *name, const char *classname, - struct security_descriptor *sec_desc, - struct hive_key **ret) +static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, + const char *name, const char *classname, + struct security_descriptor *sec_desc, + struct hive_key **ret) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)parent; struct nk_block *parent_nk = private_data->nk, nk; struct nk_block *root; @@ -1547,32 +1640,33 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, nk.clsname_offset = -1; /* FIXME: fill in */ nk.clsname_length = 0; nk.key_name = name; - + /* Get the security descriptor of the root key */ root = talloc_zero(ctx, struct nk_block); W_ERROR_HAVE_NO_MEMORY(root); - if (!hbin_get_tdr(regf, regf->header->data_offset, root, - (tdr_pull_fn_t)tdr_pull_nk_block, root)) { + if (!hbin_get_tdr(regf, regf->header->data_offset, root, + (tdr_pull_fn_t)tdr_pull_nk_block, root)) { DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return WERR_GENERAL_FAILURE; } nk.sk_offset = root->sk_offset; talloc_free(root); - + /* Store the new nk key */ offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk); - - error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset, &parent_nk->subkeys_offset); + + error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset, + &parent_nk->subkeys_offset); if (!W_ERROR_IS_OK(error)) { hbin_free(regf, offset); return error; } - + parent_nk->num_subkeys++; /* Since the subkey offset of the parent can change, store it again */ - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, + hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, nk.parent_offset, parent_nk); *ret = (struct hive_key *)regf_get_key(ctx, regf, offset); @@ -1580,10 +1674,10 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, return regf_save_hbin(private_data->hive); } -static WERROR regf_set_value(struct hive_key *key, const char *name, - uint32_t type, const DATA_BLOB data) +static WERROR regf_set_value(struct hive_key *key, const char *name, + uint32_t type, const DATA_BLOB data) { - const struct regf_key_data *private_data = + const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct regf_data *regf = private_data->hive; struct nk_block *nk = private_data->nk; @@ -1600,9 +1694,11 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, for (i = 0; i < nk->num_values; i++) { tmp_vk_offset = IVAL(values.data, i * 4); - if (!hbin_get_tdr(regf, tmp_vk_offset, private_data, - (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) { - DEBUG(0, ("Unable to get VK block at %d\n", tmp_vk_offset)); + if (!hbin_get_tdr(regf, tmp_vk_offset, private_data, + (tdr_pull_fn_t)tdr_pull_vk_block, + &vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", + tmp_vk_offset)); return WERR_GENERAL_FAILURE; } if (strcmp(vk.data_name, name) == 0) { @@ -1612,7 +1708,7 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, } /* Free data, if any */ if (!(vk.data_length & 0x80000000)) { - hbin_free(regf, vk.data_offset); + hbin_free(regf, vk.data_offset); } } if (old_vk_offset == -1) { @@ -1638,15 +1734,21 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, } if (old_vk_offset == -1) { /* Store new vk */ - vk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_vk_block, &vk); + vk_offset = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_vk_block, + &vk); } else { /* Store vk at offset */ - vk_offset = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_vk_block, old_vk_offset ,&vk); + vk_offset = hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_vk_block, + old_vk_offset ,&vk); } /* Re-allocate the value list */ if (nk->values_offset == -1) { - nk->values_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_uint32, &vk_offset); + nk->values_offset = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_uint32, + &vk_offset); nk->num_values = 1; } else { @@ -1664,17 +1766,23 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, DATA_BLOB value_list; value_list.length = (nk->num_values+1)*4; - value_list.data = (uint8_t *)talloc_array(private_data, uint32_t, nk->num_values+1); + value_list.data = (uint8_t *)talloc_array(private_data, + uint32_t, + nk->num_values+1); W_ERROR_HAVE_NO_MEMORY(value_list.data); memcpy(value_list.data, values.data, nk->num_values * 4); SIVAL(value_list.data, nk->num_values * 4, vk_offset); nk->num_values++; - nk->values_offset = hbin_store_resize(regf, nk->values_offset, value_list); + nk->values_offset = hbin_store_resize(regf, + nk->values_offset, + value_list); } - + } - hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk); + hbin_store_tdr_resize(regf, + (tdr_push_fn_t) tdr_push_nk_block, + private_data->offset, nk); return regf_save_hbin(private_data->hive); } @@ -1698,8 +1806,9 @@ static WERROR regf_save_hbin(struct regf_data *regf) regf->header->chksum = regf_hdr_checksum(push->data.data); talloc_free(push); - if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, - (tdr_push_fn_t)tdr_push_regf_hdr, regf->header))) { + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, + (tdr_push_fn_t)tdr_push_regf_hdr, + regf->header))) { DEBUG(0, ("Error writing registry file header\n")); return WERR_GENERAL_FAILURE; } @@ -1707,13 +1816,13 @@ static WERROR regf_save_hbin(struct regf_data *regf) if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) { DEBUG(0, ("Error lseeking to 0x1000 in regf file\n")); return WERR_GENERAL_FAILURE; - } + } for (i = 0; regf->hbins[i]; i++) { - if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, - (tdr_push_fn_t)tdr_push_hbin_block, - regf->hbins[i]))) { - DEBUG(0, ("Error writing HBIN block\n")); + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, + (tdr_push_fn_t)tdr_push_hbin_block, + regf->hbins[i]))) { + DEBUG(0, ("Error writing HBIN block\n")); return WERR_GENERAL_FAILURE; } } @@ -1721,8 +1830,8 @@ static WERROR regf_save_hbin(struct regf_data *regf) return WERR_OK; } -WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, - int minor_version, struct hive_key **key) +WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, + int minor_version, struct hive_key **key) { struct regf_data *regf; struct regf_hdr *regf_hdr; @@ -1754,7 +1863,8 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, regf_hdr->version.major = 1; regf_hdr->version.minor = minor_version; regf_hdr->last_block = 0x1000; /* Block size */ - regf_hdr->description = talloc_strdup(regf_hdr, "registry created by Samba 4"); + regf_hdr->description = talloc_strdup(regf_hdr, + "registry created by Samba 4"); W_ERROR_HAVE_NO_MEMORY(regf_hdr->description); regf_hdr->chksum = 0; @@ -1785,14 +1895,16 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, nk.clsname_offset = -1; /* FIXME: fill in */ nk.clsname_length = 0; nk.key_name = ""; - + nk.sk_offset = -1; /* FIXME: fill in */ - + /* Store the new nk key */ - regf->header->data_offset = hbin_store_tdr(regf, - (tdr_push_fn_t)tdr_push_nk_block, &nk); - - *key = (struct hive_key *)regf_get_key(parent_ctx, regf, regf->header->data_offset); + regf->header->data_offset = hbin_store_tdr(regf, + (tdr_push_fn_t)tdr_push_nk_block, + &nk); + + *key = (struct hive_key *)regf_get_key(parent_ctx, regf, + regf->header->data_offset); /* We can drop our own reference now that *key will have created one */ talloc_free(regf); @@ -1805,8 +1917,8 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, return WERR_OK; } -WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, - const char *location, struct hive_key **key) +WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, + const char *location, struct hive_key **key) { struct regf_data *regf; struct regf_hdr *regf_hdr; @@ -1850,7 +1962,7 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, if (strcmp(regf_hdr->REGF_ID, "regf") != 0) { DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n", - regf_hdr->REGF_ID, location)); + regf_hdr->REGF_ID, location)); talloc_free(regf); return WERR_GENERAL_FAILURE; } @@ -1858,8 +1970,8 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, /* Validate the header ... */ if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) { DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", - location, regf_hdr->chksum, - regf_hdr_checksum(pull.data.data))); + location, regf_hdr->chksum, + regf_hdr_checksum(pull.data.data))); talloc_free(regf); return WERR_GENERAL_FAILURE; } @@ -1873,8 +1985,10 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, regf->hbins[0] = NULL; - while (pull.offset < pull.data.length && pull.offset <= regf->header->last_block) { - struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block); + while (pull.offset < pull.data.length && + pull.offset <= regf->header->last_block) { + struct hbin_block *hbin = talloc(regf->hbins, + struct hbin_block); W_ERROR_HAVE_NO_MEMORY(hbin); @@ -1885,21 +1999,23 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, } if (strcmp(hbin->HBIN_ID, "hbin") != 0) { - DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n", i, hbin->HBIN_ID)); + DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n", + i, hbin->HBIN_ID)); talloc_free(regf); return WERR_FOOBAR; } regf->hbins[i] = hbin; i++; - regf->hbins = talloc_realloc(regf, regf->hbins, struct hbin_block *, i+2); + regf->hbins = talloc_realloc(regf, regf->hbins, + struct hbin_block *, i+2); regf->hbins[i] = NULL; - } + } DEBUG(1, ("%d HBIN blocks read\n", i)); - *key = (struct hive_key *)regf_get_key(parent_ctx, regf, - regf->header->data_offset); + *key = (struct hive_key *)regf_get_key(parent_ctx, regf, + regf->header->data_offset); /* We can drop our own reference now that *key will have created one */ talloc_free(regf); -- cgit From 529763a9aa192a6785ba878aceeb1683c2510913 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Nov 2007 19:24:51 +0100 Subject: r25920: ndr: change NTSTAUS into enum ndr_err_code (samba4 callers) lib/messaging/ lib/registry/ lib/ldb-samba/ librpc/rpc/ auth/auth_winbind.c auth/gensec/ auth/kerberos/ dsdb/repl/ dsdb/samdb/ dsdb/schema/ torture/ cluster/ctdb/ kdc/ ntvfs/ipc/ torture/rap/ ntvfs/ utils/getntacl.c ntptr/ smb_server/ libcli/wrepl/ wrepl_server/ libcli/cldap/ libcli/dgram/ libcli/ldap/ libcli/raw/ libcli/nbt/ libnet/ winbind/ rpc_server/ metze (This used to be commit 6223c7fddc972687eb577e04fc1c8e0604c35435) --- source4/lib/registry/regf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 2dd27ca33d..3ae299b3ef 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1021,7 +1021,7 @@ static WERROR regf_set_sec_desc(struct hive_key *key, (tdr_pull_fn_t) tdr_pull_nk_block, &root); /* Push the security descriptor to a blob */ - if (NT_STATUS_IS_ERR(ndr_push_struct_blob(&data, regf, sec_desc, + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { DEBUG(0, ("Unable to push security descriptor\n")); return WERR_GENERAL_FAILURE; @@ -1174,7 +1174,7 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, data.data = sk.sec_desc; data.length = sk.rec_size; - if (NT_STATUS_IS_ERR(ndr_pull_struct_blob(&data, ctx, *sd, + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { DEBUG(0, ("Error parsing security descriptor\n")); return WERR_GENERAL_FAILURE; -- cgit From 5e00673a4063c9a51580a36ba1f824bd8ea0de66 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 Dec 2007 22:46:47 +0100 Subject: r26438: Store iconv convenience in tdr push contexts. (This used to be commit dffef3162778aebe2f8d77e2da60b22adb7d60ef) --- source4/lib/registry/regf.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 3ae299b3ef..2485d2899c 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -24,6 +24,7 @@ #include "lib/registry/tdr_regf.h" #include "librpc/gen_ndr/ndr_security.h" #include "librpc/gen_ndr/winreg.h" +#include "param/param.h" static struct hive_operations reg_backend_regf; @@ -47,6 +48,7 @@ struct regf_data { int fd; struct hbin_block **hbins; struct regf_hdr *header; + struct smb_iconv_convenience *iconv_convenience; }; static WERROR regf_save_hbin(struct regf_data *data); @@ -263,7 +265,7 @@ static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob) static uint32_t hbin_store_tdr(struct regf_data *data, tdr_push_fn_t push_fn, void *p) { - struct tdr_push *push = talloc_zero(data, struct tdr_push); + struct tdr_push *push = tdr_push_init(data, data->iconv_convenience); uint32_t ret; if (NT_STATUS_IS_ERR(push_fn(push, p))) { @@ -390,7 +392,7 @@ static uint32_t hbin_store_tdr_resize(struct regf_data *regf, tdr_push_fn_t push_fn, uint32_t orig_offset, void *p) { - struct tdr_push *push = talloc_zero(regf, struct tdr_push); + struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience); uint32_t ret; if (NT_STATUS_IS_ERR(push_fn(push, p))) { @@ -1788,7 +1790,7 @@ static WERROR regf_set_value(struct hive_key *key, const char *name, static WERROR regf_save_hbin(struct regf_data *regf) { - struct tdr_push *push = talloc_zero(regf, struct tdr_push); + struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience); int i; W_ERROR_HAVE_NO_MEMORY(push); @@ -1806,7 +1808,7 @@ static WERROR regf_save_hbin(struct regf_data *regf) regf->header->chksum = regf_hdr_checksum(push->data.data); talloc_free(push); - if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience, (tdr_push_fn_t)tdr_push_regf_hdr, regf->header))) { DEBUG(0, ("Error writing registry file header\n")); @@ -1819,7 +1821,7 @@ static WERROR regf_save_hbin(struct regf_data *regf) } for (i = 0; regf->hbins[i]; i++) { - if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, + if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience, (tdr_push_fn_t)tdr_push_hbin_block, regf->hbins[i]))) { DEBUG(0, ("Error writing HBIN block\n")); @@ -1842,6 +1844,8 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); + regf->iconv_convenience = lp_iconv_convenience(global_loadparm); + W_ERROR_HAVE_NO_MEMORY(regf); DEBUG(5, ("Attempting to create registry file\n")); @@ -1927,6 +1931,8 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); + regf->iconv_convenience = lp_iconv_convenience(global_loadparm); + W_ERROR_HAVE_NO_MEMORY(regf); DEBUG(5, ("Attempting to load registry file\n")); -- cgit From 27b21a386ebeed66dd804a8b2e2256b739e32543 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 Dec 2007 22:46:51 +0100 Subject: r26439: Require tdr_pull users to specify a smb_iconv convenience context. (This used to be commit 76fd57be292fb19ae4ede38977732847e6ed8eff) --- source4/lib/registry/regf.c | 200 +++++++++++++++++++++++++------------------- 1 file changed, 112 insertions(+), 88 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 2485d2899c..8eb5760f56 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -133,21 +133,22 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) static bool hbin_get_tdr(struct regf_data *regf, uint32_t offset, TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p) { - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); - ZERO_STRUCT(pull); - - pull.data = hbin_get(regf, offset); - if (!pull.data.data) { + pull->data = hbin_get(regf, offset); + if (!pull->data.data) { DEBUG(1, ("Unable to get data at 0x%04x\n", offset)); + talloc_free(pull); return false; } - if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) { + if (NT_STATUS_IS_ERR(pull_fn(pull, ctx, p))) { DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset)); + talloc_free(pull); return false; } + talloc_free(pull); return true; } @@ -594,16 +595,17 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, if (!strncmp((char *)data.data, "li", 2)) { struct li_block li; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience); DEBUG(10, ("Subkeys in LI list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); SMB_ASSERT(!strncmp(li.header, "li", 2)); if (li.key_count != nk->num_subkeys) { @@ -614,16 +616,17 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience); DEBUG(10, ("Subkeys in LF list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) { + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) { DEBUG(0, ("Error parsing LF list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lf.header, "lf", 2)); if (lf.key_count != nk->num_subkeys) { @@ -634,16 +637,17 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, key_off = lf.hr[idx].nk_offset; } else if (!strncmp((char *)data.data, "lh", 2)) { struct lh_block lh; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience); DEBUG(10, ("Subkeys in LH list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lh.header, "lh", 2)); if (lh.key_count != nk->num_subkeys) { @@ -653,16 +657,16 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, key_off = lh.hr[idx].nk_offset; } else if (!strncmp((char *)data.data, "ri", 2)) { struct ri_block ri; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; uint16_t sublist_count = 0; DEBUG(10, ("Subkeys in RI list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) { + if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) { DEBUG(0, ("Error parsing RI list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(ri.header, "ri", 2)); @@ -674,21 +678,22 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, list_data = hbin_get(private_data->hive, ri.offset[i]); if (!list_data.data) { DEBUG(0, ("Error getting RI list.")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } - ZERO_STRUCT(pull); - pull.data = list_data; + pull->data = list_data; if (!strncmp((char *)list_data.data, "li", 2)) { struct li_block li; DEBUG(10, ("Subkeys in RI->LI list\n")); - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, + if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list from RI\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(li.header, "li", 2)); @@ -706,10 +711,11 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, DEBUG(10, ("Subkeys in RI->LH list\n")); - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list from RI\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(lh.header, "lh", 2)); @@ -724,11 +730,14 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, break; } else { DEBUG(0,("Unknown sublist in ri block\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } } + talloc_free(pull); + if (idx > sublist_count) { return WERR_NO_MORE_ITEMS; @@ -771,7 +780,7 @@ static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, { DATA_BLOB subkey_data; struct nk_block subkey; - struct tdr_pull pull; + struct tdr_pull *pull; const struct regf_key_data *private_data = (const struct regf_key_data *)key; @@ -781,13 +790,16 @@ static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, return WERR_GENERAL_FAILURE; } - ZERO_STRUCT(pull); - pull.data = subkey_data; + pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); + + pull->data = subkey_data; - if (NT_STATUS_IS_ERR(tdr_pull_nk_block(&pull, ctx, &subkey))) { + if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) { DEBUG(0, ("Error parsing NK structure.\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); if (strncmp(subkey.header, "nk", 2)) { DEBUG(0, ("Not an NK structure.\n")); @@ -821,17 +833,18 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, if (!strncmp((char *)data.data, "li", 2)) { struct li_block li; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; DEBUG(10, ("Subkeys in LI list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) { + if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); SMB_ASSERT(!strncmp(li.header, "li", 2)); if (li.key_count != nk->num_subkeys) { @@ -851,17 +864,18 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, return WERR_NOT_FOUND; } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; DEBUG(10, ("Subkeys in LF list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) { + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) { DEBUG(0, ("Error parsing LF list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lf.header, "lf", 2)); if (lf.key_count != nk->num_subkeys) { @@ -885,18 +899,19 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, return WERR_NOT_FOUND; } else if (!strncmp((char *)data.data, "lh", 2)) { struct lh_block lh; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; uint32_t hash; DEBUG(10, ("Subkeys in LH list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) { + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lh.header, "lh", 2)); if (lh.key_count != nk->num_subkeys) { @@ -921,15 +936,15 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, return WERR_NOT_FOUND; } else if (!strncmp((char *)data.data, "ri", 2)) { struct ri_block ri; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i, j; DEBUG(10, ("Subkeys in RI list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) { + if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) { DEBUG(0, ("Error parsing RI list\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(ri.header, "ri", 2)); @@ -941,19 +956,20 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, list_data = hbin_get(private_data->hive, ri.offset[i]); if (list_data.data == NULL) { DEBUG(0, ("Error getting RI list.")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } - ZERO_STRUCT(pull); - pull.data = list_data; + pull->data = list_data; if (!strncmp((char *)list_data.data, "li", 2)) { struct li_block li; - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, + if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list from RI\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(li.header, "li", 2)); @@ -970,10 +986,11 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, struct lh_block lh; uint32_t hash; - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list from RI\n")); + talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(lh.header, "lh", 2)); @@ -994,6 +1011,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, if (key_off) break; } + talloc_free(pull); if (!key_off) return WERR_NOT_FOUND; } else { @@ -1260,16 +1278,17 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, } if (!strncmp((char *)data.data, "li", 2)) { - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); struct li_block li; - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) { + if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) { DEBUG(0, ("Error parsing LI list\n")); + talloc_free(pull); return WERR_BADFILE; } + talloc_free(pull); if (strncmp(li.header, "li", 2) != 0) { abort(); @@ -1288,16 +1307,17 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, talloc_free(li.nk_offset); } else if (!strncmp((char *)data.data, "lf", 2)) { - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); struct lf_block lf; - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) { + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) { DEBUG(0, ("Error parsing LF list\n")); + talloc_free(pull); return WERR_BADFILE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lf.header, "lf", 2)); lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, @@ -1313,16 +1333,17 @@ static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset, talloc_free(lf.hr); } else if (!strncmp((char *)data.data, "lh", 2)) { - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); struct lh_block lh; - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) { + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) { DEBUG(0, ("Error parsing LH list\n")); + talloc_free(pull); return WERR_BADFILE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lh.header, "lh", 2)); lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash, @@ -1361,19 +1382,20 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, if (strncmp((char *)data.data, "li", 2) == 0) { struct li_block li; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); uint16_t i; bool found_offset = false; DEBUG(10, ("Subkeys in LI list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) { + if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) { DEBUG(0, ("Error parsing LI list\n")); + talloc_free(pull); return WERR_BADFILE; } + talloc_free(pull); SMB_ASSERT(!strncmp(li.header, "li", 2)); @@ -1404,19 +1426,20 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, list_offset, &li); } else if (strncmp((char *)data.data, "lf", 2) == 0) { struct lf_block lf; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); uint16_t i; bool found_offset = false; DEBUG(10, ("Subkeys in LF list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) { + if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) { DEBUG(0, ("Error parsing LF list\n")); + talloc_free(pull); return WERR_BADFILE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lf.header, "lf", 2)); @@ -1449,19 +1472,20 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, list_offset, &lf); } else if (strncmp((char *)data.data, "lh", 2) == 0) { struct lh_block lh; - struct tdr_pull pull; + struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience); uint16_t i; bool found_offset = false; DEBUG(10, ("Subkeys in LH list\n")); - ZERO_STRUCT(pull); - pull.data = data; + pull->data = data; - if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) { + if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) { DEBUG(0, ("Error parsing LF list\n")); + talloc_free(pull); return WERR_BADFILE; } + talloc_free(pull); SMB_ASSERT(!strncmp(lh.header, "lh", 2)); @@ -1837,7 +1861,6 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, { struct regf_data *regf; struct regf_hdr *regf_hdr; - struct tdr_pull pull; int i; struct nk_block nk; WERROR error; @@ -1874,8 +1897,6 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, regf->header = regf_hdr; - pull.offset = 0x1000; - i = 0; /* Create all hbin blocks */ regf->hbins = talloc_array(regf, struct hbin_block *, 1); @@ -1926,7 +1947,7 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, { struct regf_data *regf; struct regf_hdr *regf_hdr; - struct tdr_pull pull; + struct tdr_pull *pull; int i; regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); @@ -1947,10 +1968,11 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, return WERR_GENERAL_FAILURE; } - ZERO_STRUCT(pull); - pull.data.data = (uint8_t*)fd_load(regf->fd, &pull.data.length, regf); + pull = tdr_pull_init(regf, regf->iconv_convenience); + + pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, regf); - if (pull.data.data == NULL) { + if (pull->data.data == NULL) { DEBUG(0, ("Error reading data\n")); talloc_free(regf); return WERR_GENERAL_FAILURE; @@ -1959,7 +1981,7 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, regf_hdr = talloc(regf, struct regf_hdr); W_ERROR_HAVE_NO_MEMORY(regf_hdr); - if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(&pull, regf_hdr, regf_hdr))) { + if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) { talloc_free(regf); return WERR_GENERAL_FAILURE; } @@ -1974,15 +1996,15 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, } /* Validate the header ... */ - if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) { + if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) { DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", location, regf_hdr->chksum, - regf_hdr_checksum(pull.data.data))); + regf_hdr_checksum(pull->data.data))); talloc_free(regf); return WERR_GENERAL_FAILURE; } - pull.offset = 0x1000; + pull->offset = 0x1000; i = 0; /* Read in all hbin blocks */ @@ -1991,14 +2013,14 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, regf->hbins[0] = NULL; - while (pull.offset < pull.data.length && - pull.offset <= regf->header->last_block) { + while (pull->offset < pull->data.length && + pull->offset <= regf->header->last_block) { struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block); W_ERROR_HAVE_NO_MEMORY(hbin); - if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) { + if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) { DEBUG(0, ("[%d] Error parsing HBIN block\n", i)); talloc_free(regf); return WERR_FOOBAR; @@ -2018,6 +2040,8 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, regf->hbins[i] = NULL; } + talloc_free(pull); + DEBUG(1, ("%d HBIN blocks read\n", i)); *key = (struct hive_key *)regf_get_key(parent_ctx, regf, -- cgit From 96a200511e884a88dcf48fa5b313b2cddb2df566 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 14 Dec 2007 00:27:31 +0100 Subject: r26443: Remove global_loadparm instances. (This used to be commit 8242c696235d1bfb402b5c276a57f36d93610545) --- source4/lib/registry/regf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 8eb5760f56..210b4c9ada 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1942,8 +1942,8 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, return WERR_OK; } -WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, - const char *location, struct hive_key **key) +WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, + struct loadparm_context *lp_ctx, struct hive_key **key) { struct regf_data *regf; struct regf_hdr *regf_hdr; @@ -1952,7 +1952,7 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); - regf->iconv_convenience = lp_iconv_convenience(global_loadparm); + regf->iconv_convenience = lp_iconv_convenience(lp_ctx); W_ERROR_HAVE_NO_MEMORY(regf); -- cgit From 45015eda2421253f858f0a4500a57c2855f9686c Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Fri, 14 Dec 2007 10:38:26 +0100 Subject: r26451: Janitorial: fix warnings in lib/registry/ This does not fix the discarded qualifier warnings in tests, as the test data is currently passed as const. Jelmer wants to provide a test function that passes non-const test data, thus allowing for a cleaner way to fix those warnings. (This used to be commit 46dfa63d4f7381c5c6ce3f4b8b0bd9aa9e16950c) --- source4/lib/registry/regf.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 210b4c9ada..28bd0ad461 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -488,7 +488,7 @@ static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx, } -static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key, +static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key, int idx, const char **name, uint32_t *data_type, DATA_BLOB *data) { @@ -1529,8 +1529,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, static WERROR regf_del_value (struct hive_key *key, const char *name) { - const struct regf_key_data *private_data = - (const struct regf_key_data *)key; + struct regf_key_data *private_data = (struct regf_key_data *)key; struct regf_data *regf = private_data->hive; struct nk_block *nk = private_data->nk; struct vk_block vk; @@ -1703,8 +1702,7 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, static WERROR regf_set_value(struct hive_key *key, const char *name, uint32_t type, const DATA_BLOB data) { - const struct regf_key_data *private_data = - (const struct regf_key_data *)key; + struct regf_key_data *private_data = (struct regf_key_data *)key; struct regf_data *regf = private_data->hive; struct nk_block *nk = private_data->nk; struct vk_block vk; -- cgit From 86dc05e99f124db47f2743d1fc23117a7f5145ab Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 1 Jan 2008 22:05:05 -0600 Subject: r26638: libndr: Require explicitly specifying iconv_convenience for ndr_struct_push_blob(). (This used to be commit 61ad78ac98937ef7a9aa32075a91a1c95b7606b3) --- source4/lib/registry/regf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 28bd0ad461..7d2df182fe 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1041,8 +1041,8 @@ static WERROR regf_set_sec_desc(struct hive_key *key, (tdr_pull_fn_t) tdr_pull_nk_block, &root); /* Push the security descriptor to a blob */ - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, sec_desc, - (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL, + sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { DEBUG(0, ("Unable to push security descriptor\n")); return WERR_GENERAL_FAILURE; } -- cgit From 7d5f0e0893d42b56145a3ffa34e3b4b9906cbd91 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 1 Jan 2008 22:05:13 -0600 Subject: r26639: librpc: Pass iconv convenience on from RPC connection to NDR library, so it can be overridden by OpenChange. (This used to be commit 2f29f80e07adef1f020173f2cd6d947d0ef505ce) --- source4/lib/registry/regf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 7d2df182fe..9264339a6c 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1194,7 +1194,7 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key, data.data = sk.sec_desc; data.length = sk.rec_size; - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd, + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, NULL, *sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { DEBUG(0, ("Error parsing security descriptor\n")); return WERR_GENERAL_FAILURE; -- cgit From 47f6bbf8cf5bdd03c72c59d00e3e1eab8895590e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 7 Jan 2008 14:11:29 -0600 Subject: r26689: registry: Return max_subkeynamelen, max_valnamelen and max_valbufsize in getkeyinfo(). (This used to be commit b06896d2378e536f5044dbe500a5232a89d6d0b5) --- source4/lib/registry/regf.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 9264339a6c..9b126cc808 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -428,7 +428,10 @@ static WERROR regf_get_info(TALLOC_CTX *mem_ctx, const char **classname, uint32_t *num_subkeys, uint32_t *num_values, - NTTIME *last_mod_time) + NTTIME *last_mod_time, + uint32_t *max_subkeynamelen, + uint32_t *max_valnamelen, + uint32_t *max_valbufsize) { const struct regf_key_data *private_data = (const struct regf_key_data *)key; @@ -452,6 +455,12 @@ static WERROR regf_get_info(TALLOC_CTX *mem_ctx, /* TODO: Last mod time */ + /* TODO: max valnamelen */ + + /* TODO: max valbufsize */ + + /* TODO: max subkeynamelen */ + return WERR_OK; } -- cgit From 85d60d2d091a2eb6bd4c73c87c94b10ee93167ee Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 18 Jan 2008 02:45:00 +0100 Subject: registry: Improve error codes and update tests. Rather than map the error returned by the registry to the correct error, return the correct error in the first place. Also deal with the fact that the right error code is now returned in a couple of places. (This used to be commit 1e31fcb8a097810a97e2d4bb1f243f1b34cc2415) --- source4/lib/registry/regf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 9b126cc808..475ec7bb5d 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -575,7 +575,7 @@ static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx, } if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) - return WERR_NOT_FOUND; + return WERR_BADFILE; return error; } -- cgit From 55ad09a01b31f2d2c9503f744b519e089f9f936b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 18 Jan 2008 03:37:06 +0100 Subject: registry: Use correct return values. (This used to be commit 98ebdbe52fd615ea62a3caa17acfe8bb31b8f85d) --- source4/lib/registry/regf.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 475ec7bb5d..15b60745f0 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -870,7 +870,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, break; } if (key_off == 0) - return WERR_NOT_FOUND; + return WERR_BADFILE; } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); @@ -905,7 +905,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, break; } if (key_off == 0) - return WERR_NOT_FOUND; + return WERR_BADFILE; } else if (!strncmp((char *)data.data, "lh", 2)) { struct lh_block lh; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); @@ -942,7 +942,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, break; } if (key_off == 0) - return WERR_NOT_FOUND; + return WERR_BADFILE; } else if (!strncmp((char *)data.data, "ri", 2)) { struct ri_block ri; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); @@ -1022,7 +1022,7 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, } talloc_free(pull); if (!key_off) - return WERR_NOT_FOUND; + return WERR_BADFILE; } else { DEBUG(0, ("Unknown subkey list type.\n")); return WERR_GENERAL_FAILURE; @@ -1419,7 +1419,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } if (!found_offset) { DEBUG(2, ("Subkey not found\n")); - return WERR_NOT_FOUND; + return WERR_BADFILE; } li.key_count--; @@ -1464,7 +1464,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } if (!found_offset) { DEBUG(2, ("Subkey not found\n")); - return WERR_NOT_FOUND; + return WERR_BADFILE; } lf.key_count--; @@ -1510,7 +1510,7 @@ static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset, } if (!found_offset) { DEBUG(0, ("Subkey not found\n")); - return WERR_NOT_FOUND; + return WERR_BADFILE; } lh.key_count--; @@ -1548,7 +1548,7 @@ static WERROR regf_del_value (struct hive_key *key, const char *name) uint32_t i; if (nk->values_offset == -1) { - return WERR_NOT_FOUND; + return WERR_BADFILE; } values = hbin_get(regf, nk->values_offset); @@ -1572,7 +1572,7 @@ static WERROR regf_del_value (struct hive_key *key, const char *name) } } if (!found_offset) { - return WERR_NOT_FOUND; + return WERR_BADFILE; } else { nk->num_values--; values.length = (nk->num_values)*4; @@ -1608,14 +1608,14 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name) if (parent_nk->subkeys_offset == -1) { DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n")); - return WERR_NOT_FOUND; + return WERR_BADFILE; } /* Find the key */ if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name, (struct hive_key **)&key))) { DEBUG(2, ("Key '%s' not found\n", name)); - return WERR_NOT_FOUND; + return WERR_BADFILE; } if (key->nk->subkeys_offset != -1 || -- cgit From c38c2765d1059b33f044a42c6555f3d10d339911 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 21 Feb 2008 17:17:37 +0100 Subject: Remove yet more uses of global_loadparm. (This used to be commit e01c1e87c0fe9709df7eb5b863f7ce85564174cd) --- source4/lib/registry/regf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 15b60745f0..cf3e564c0e 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1863,7 +1863,9 @@ static WERROR regf_save_hbin(struct regf_data *regf) return WERR_OK; } -WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, +WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, + struct smb_iconv_convenience *iconv_convenience, + const char *location, int minor_version, struct hive_key **key) { struct regf_data *regf; @@ -1874,7 +1876,7 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); - regf->iconv_convenience = lp_iconv_convenience(global_loadparm); + regf->iconv_convenience = iconv_convenience; W_ERROR_HAVE_NO_MEMORY(regf); @@ -1950,7 +1952,7 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location, } WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, - struct loadparm_context *lp_ctx, struct hive_key **key) + struct smb_iconv_convenience *iconv_convenience, struct hive_key **key) { struct regf_data *regf; struct regf_hdr *regf_hdr; @@ -1959,7 +1961,7 @@ WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); - regf->iconv_convenience = lp_iconv_convenience(lp_ctx); + regf->iconv_convenience = iconv_convenience; W_ERROR_HAVE_NO_MEMORY(regf); -- cgit From 79eea32976d2991319c9d0ad32a150f34b029f99 Mon Sep 17 00:00:00 2001 From: Andrew Kroeger Date: Sat, 16 Feb 2008 15:19:00 -0600 Subject: registry: Implement recursive deletes for regf-backed registry. When deleting a registry key that contains subkeys or values, Windows performs a recursive deletion that removes any subkeys or values. This update makes deletes for an regf-backed registry consistent with Windows. The regf-backed registry does not have transactional integrity when performing multiple operations. Therefore, if an error occurs during the recursive deletion, the regf-backed registry may be left in an inconsistent state. (This used to be commit b0321bad290d1a9399b4aba140a622e3af6d7575) --- source4/lib/registry/regf.c | 53 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 15b60745f0..6a35799a7e 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -1618,10 +1618,55 @@ static WERROR regf_del_key(const struct hive_key *parent, const char *name) return WERR_BADFILE; } - if (key->nk->subkeys_offset != -1 || - key->nk->values_offset != -1) { - DEBUG(0, ("Key '%s' is not empty.\n", name)); - return WERR_FILE_EXISTS; + if (key->nk->subkeys_offset != -1) { + char *sk_name; + struct hive_key *sk = (struct hive_key *)key; + int i = key->nk->num_subkeys; + while (i--) { + /* Get subkey information. */ + error = regf_get_subkey_by_index(parent_nk, sk, 0, + (const char **)&sk_name, + NULL, NULL); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Can't retrieve subkey by index.\n")); + return error; + } + + /* Delete subkey. */ + error = regf_del_key(sk, sk_name); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Can't delete key '%s'.\n", sk_name)); + return error; + } + + talloc_free(sk_name); + } + } + + if (key->nk->values_offset != -1) { + char *val_name; + struct hive_key *sk = (struct hive_key *)key; + DATA_BLOB data; + int i = key->nk->num_values; + while (i--) { + /* Get value information. */ + error = regf_get_value(parent_nk, sk, 0, + (const char **)&val_name, + NULL, &data); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Can't retrieve value by index.\n")); + return error; + } + + /* Delete value. */ + error = regf_del_value(sk, val_name); + if (!W_ERROR_IS_OK(error)) { + DEBUG(0, ("Can't delete value '%s'.\n", val_name)); + return error; + } + + talloc_free(val_name); + } } /* Delete it from the subkey list. */ -- cgit From ec7394e7d2f589905044cff3cb1899f0815991d6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 2 Apr 2008 13:59:48 +0200 Subject: Merge hive.h into registry.h (This used to be commit 3ca14fdf74d2510049bbdbbd2a5be341412cda1b) --- source4/lib/registry/regf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index a192f3be4d..46ccca922b 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -18,13 +18,13 @@ along with this program. If not, see . */ #include "includes.h" -#include "lib/registry/hive.h" #include "system/filesys.h" #include "system/time.h" #include "lib/registry/tdr_regf.h" #include "librpc/gen_ndr/ndr_security.h" #include "librpc/gen_ndr/winreg.h" #include "param/param.h" +#include "lib/registry/registry.h" static struct hive_operations reg_backend_regf; -- cgit From 12147fca2b3acd37eb20db82996714320cd4e9b2 Mon Sep 17 00:00:00 2001 From: Wilco Baan Hofman Date: Mon, 14 Apr 2008 22:52:51 +0200 Subject: Add support for security descriptors. Also patched the regf backend to support this. Did not touch the ldb, dir and rpc backends yet. (This used to be commit c4626f21a898da27a051f2c67f8fd73f55d4fc7d) --- source4/lib/registry/regf.c | 64 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 11 deletions(-) (limited to 'source4/lib/registry/regf.c') diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c index 46ccca922b..57a895aa00 100644 --- a/source4/lib/registry/regf.c +++ b/source4/lib/registry/regf.c @@ -25,6 +25,8 @@ #include "librpc/gen_ndr/winreg.h" #include "param/param.h" #include "lib/registry/registry.h" +#include "libcli/security/security.h" + static struct hive_operations reg_backend_regf; @@ -1915,9 +1917,12 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, { struct regf_data *regf; struct regf_hdr *regf_hdr; - int i; struct nk_block nk; + struct sk_block sk; WERROR error; + DATA_BLOB data; + struct security_descriptor *sd; + uint32_t sk_offset; regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); @@ -1945,20 +1950,17 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, regf_hdr->version.minor = minor_version; regf_hdr->last_block = 0x1000; /* Block size */ regf_hdr->description = talloc_strdup(regf_hdr, - "registry created by Samba 4"); + "Registry created by Samba 4"); W_ERROR_HAVE_NO_MEMORY(regf_hdr->description); regf_hdr->chksum = 0; regf->header = regf_hdr; - i = 0; /* Create all hbin blocks */ regf->hbins = talloc_array(regf, struct hbin_block *, 1); W_ERROR_HAVE_NO_MEMORY(regf->hbins); regf->hbins[0] = NULL; - regf_hdr->data_offset = -1; /* FIXME */ - nk.header = "nk"; nk.type = REG_SUB_KEY; unix_to_nt_time(&nk.last_change, time(NULL)); @@ -1971,27 +1973,67 @@ WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, nk.num_values = 0; nk.values_offset = -1; memset(nk.unk3, 0, 5); - nk.clsname_offset = -1; /* FIXME: fill in */ + nk.clsname_offset = -1; nk.clsname_length = 0; - nk.key_name = ""; + nk.sk_offset = 0x80; + nk.key_name = "SambaRootKey"; + + /* + * It should be noted that changing the key_name to something shorter + * creates a shorter nk block, which makes the position of the sk block + * change. All Windows registries I've seen have the sk at 0x80. + * I therefore recommend that our regf files share that offset -- Wilco + */ + + /* Create a security descriptor. */ + sd = security_descriptor_dacl_create(regf, + 0, + NULL, NULL, + SID_NT_AUTHENTICATED_USERS, + SEC_ACE_TYPE_ACCESS_ALLOWED, + SEC_GENERIC_ALL, + SEC_ACE_FLAG_OBJECT_INHERIT, + NULL); + + /* Push the security descriptor to a blob */ + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL, + sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { + DEBUG(0, ("Unable to push security descriptor\n")); + return WERR_GENERAL_FAILURE; + } - nk.sk_offset = -1; /* FIXME: fill in */ + ZERO_STRUCT(sk); + sk.header = "sk"; + sk.prev_offset = 0x80; + sk.next_offset = 0x80; + sk.ref_cnt = 1; + sk.rec_size = data.length; + sk.sec_desc = data.data; /* Store the new nk key */ regf->header->data_offset = hbin_store_tdr(regf, (tdr_push_fn_t)tdr_push_nk_block, &nk); + /* Store the sk block */ + sk_offset = hbin_store_tdr(regf, + (tdr_push_fn_t) tdr_push_sk_block, + &sk); + if (sk_offset != 0x80) { + DEBUG(0, ("Error storing sk block, should be at 0x80, stored at 0x%x\n", nk.sk_offset)); + return WERR_GENERAL_FAILURE; + } + *key = (struct hive_key *)regf_get_key(parent_ctx, regf, regf->header->data_offset); - /* We can drop our own reference now that *key will have created one */ - talloc_free(regf); - error = regf_save_hbin(regf); if (!W_ERROR_IS_OK(error)) { return error; } + + /* We can drop our own reference now that *key will have created one */ + talloc_free(regf); return WERR_OK; } -- cgit