From 4729c3db26f719cd936825d91b2514df7ac0e61b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 4 Sep 2005 13:13:47 +0000 Subject: r10025: Add some utility functions for storing/loading tdr encoded data (This used to be commit bcd433bfc1450317b75e22942dee1c42bb24ae79) --- source4/lib/registry/reg_backend_nt4.c | 171 +++++++++++++++------------------ source4/lib/tdr/tdr.h | 3 + 2 files changed, 82 insertions(+), 92 deletions(-) diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c index 46057bcd63..cf67abb322 100644 --- a/source4/lib/registry/reg_backend_nt4.c +++ b/source4/lib/registry/reg_backend_nt4.c @@ -31,6 +31,7 @@ struct regf_data { DATA_BLOB data; struct hbin_block **hbins; + struct regf_hdr *header; }; static struct hbin_block *hbin_by_offset (const struct regf_data *data, uint32_t offset, uint32_t *rel_offset) @@ -67,7 +68,7 @@ static uint32_t regf_hdr_checksum(const uint8_t *buffer) return checksum; } -static DATA_BLOB hbin_get_data(const struct regf_data *data, uint32_t offset) +static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset) { DATA_BLOB ret; struct hbin_block *hbin; @@ -94,6 +95,31 @@ static DATA_BLOB hbin_get_data(const struct regf_data *data, uint32_t offset) return ret; } +static BOOL hbin_get_tdr (struct regf_data *regf, uint32_t offset, tdr_pull_fn_t pull_fn, void *p) +{ + DATA_BLOB data; + struct tdr_pull *pull; + + data = hbin_get(regf, offset); + if (!data.data) { + DEBUG(1, ("Unable to get data at 0x%04x\n", offset)); + return False; + } + + pull = talloc_zero(regf, struct tdr_pull); + pull->data = data; + + if (NT_STATUS_IS_ERR(pull_fn(pull, p))) { + DEBUG(1, ("Error parsing record at 0x%04x using tdr\n", offset)); + talloc_free(pull); + return False; + } + + /* FIXME: Free pull ! */ + + return True; +} + /* Allocate some new data */ static DATA_BLOB hbin_alloc (struct regf_data *data, uint32_t size, uint32_t *offset) { @@ -197,6 +223,23 @@ 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) +{ + 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) @@ -278,6 +321,23 @@ static uint32_t hbin_store_resize (struct regf_data *data, uint32_t 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 WERROR regf_num_subkeys (struct registry_key *key, uint32_t *count) { struct nk_block *nk = key->backend_data; @@ -298,24 +358,13 @@ static WERROR regf_num_values (struct registry_key *key, uint32_t *count) static struct registry_key *regf_get_key (TALLOC_CTX *ctx, struct regf_data *regf, uint32_t offset) { - DATA_BLOB data = hbin_get_data(regf, offset); - struct tdr_pull *pull; struct registry_key *ret; struct nk_block *nk; - if (data.data == NULL) { - DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); - return NULL; - } - ret = talloc_zero(ctx, struct registry_key); - pull = talloc_zero(ret, struct tdr_pull); - pull->data = data; nk = talloc(ret, struct nk_block); - - if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, nk))) { - DEBUG(1, ("Error parsing 'nk' record\n")); - talloc_free(ret); + if (!hbin_get_tdr(regf, offset, (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { + DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return NULL; } @@ -337,14 +386,14 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx { struct nk_block *nk = key->backend_data; struct vk_block *vk; - struct tdr_pull *pull; + struct regf_data *regf = key->hive->backend_data; uint32_t vk_offset; DATA_BLOB data; if (idx >= nk->num_values) return WERR_NO_MORE_ITEMS; - data = hbin_get_data(key->hive->backend_data, nk->values_offset); + data = hbin_get(regf, nk->values_offset); if (!data.data) { DEBUG(0, ("Unable to find value list\n")); return WERR_GENERAL_FAILURE; @@ -356,12 +405,6 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx vk_offset = IVAL(data.data, idx * 4); - data = hbin_get_data(key->hive->backend_data, vk_offset); - if (!data.data) { - DEBUG(0, ("Unable to find value\n")); - return WERR_GENERAL_FAILURE; - } - *ret = talloc_zero(ctx, struct registry_value); if (!(*ret)) return WERR_NOMEM; @@ -370,11 +413,8 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx if (!vk) return WERR_NOMEM; - pull = talloc_zero(*ret, struct tdr_pull); - pull->data = data; - - if (NT_STATUS_IS_ERR(tdr_pull_vk_block(pull, vk))) { - DEBUG(0, ("Error parsing vk block\n")); + if (!hbin_get_tdr(regf, vk_offset, (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { + DEBUG(0, ("Unable to get VK block at %d\n", vk_offset)); return WERR_GENERAL_FAILURE; } @@ -385,7 +425,7 @@ static WERROR regf_get_value (TALLOC_CTX *ctx, struct registry_key *key, int idx (*ret)->data.data = (uint8_t *)&vk->data_offset; (*ret)->data.length = vk->data_length; } else { - (*ret)->data = hbin_get_data(key->hive->backend_data, vk->data_offset); + (*ret)->data = hbin_get(regf, vk->data_offset); } if ((*ret)->data.length < vk->data_length) { @@ -404,7 +444,7 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id if (idx >= nk->num_subkeys) return WERR_NO_MORE_ITEMS; - data = hbin_get_data(key->hive->backend_data, nk->subkeys_offset); + data = hbin_get(key->hive->backend_data, nk->subkeys_offset); if (!data.data) { DEBUG(0, ("Unable to find subkey list\n")); return WERR_GENERAL_FAILURE; @@ -452,27 +492,15 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, struct registry_key *key, int id static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struct security_descriptor **sd) { struct nk_block *nk = key->backend_data; - struct tdr_pull *tdr; struct sk_block sk; + struct regf_data *regf = key->hive->backend_data; DATA_BLOB data; - data = hbin_get_data(key->hive->backend_data, nk->sk_offset); - if (!data.data) { + if (!hbin_get_tdr(regf, nk->sk_offset, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find security descriptor\n")); return WERR_GENERAL_FAILURE; } - - tdr = talloc_zero(ctx, struct tdr_pull); - if (!tdr) - return WERR_NOMEM; - - tdr->data = data; - - if (NT_STATUS_IS_ERR(tdr_pull_sk_block(tdr, &sk))) { - DEBUG(0, ("Error parsing SK block\n")); - return WERR_GENERAL_FAILURE; - } - + if (strcmp(sk.header, "sk") != 0) { DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header)); return WERR_GENERAL_FAILURE; @@ -489,8 +517,6 @@ static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, struct registry_key *key, struc return WERR_GENERAL_FAILURE; } - talloc_free(tdr); - return WERR_OK; } @@ -498,8 +524,6 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons { uint32_t ret; struct lf_block lf; - struct tdr_pull *pull = NULL; - struct tdr_push *push; /* Add to subkeys list */ if (list_offset == -1) { /* Need to create subkeys list */ @@ -507,38 +531,17 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons lf.key_count = 0; lf.hr = NULL; } else { - DATA_BLOB data; - pull = talloc(regf, struct tdr_pull); - - data = hbin_get_data(regf, list_offset); - if (!data.data) { + if (!hbin_get_tdr(regf, list_offset, (tdr_pull_fn_t)tdr_pull_lf_block, &lf)) { DEBUG(0, ("Can't get subkeys list\n")); - talloc_free(pull); - return -1; - } - - if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, &lf))) { - DEBUG(0, ("Unable to parse lf list\n")); - talloc_free(pull); return -1; } } - lf.hr = talloc_realloc(pull, lf.hr, struct hash_record, lf.key_count+1); + lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1); lf.hr[lf.key_count].nk_off = key_offset; lf.hr[lf.key_count].hash = name; - push = talloc_zero(regf, struct tdr_push); - - if (NT_STATUS_IS_ERR(tdr_push_lf_block(push, &lf))) { - DEBUG(0, ("Error storing lf block\n")); - return -1; - } - - ret = hbin_store_resize (regf, list_offset, push->data); - - talloc_free(push); - talloc_free(pull); + ret = hbin_store_tdr_resize(regf, (tdr_push_fn_t)tdr_push_lf_block, list_offset, &lf); return ret; } @@ -546,8 +549,6 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const char *name, uint32_t access_mask, struct security_descriptor *sec_desc, struct registry_key **ret) { struct nk_block *parent_nk = parent->backend_data, nk; - DATA_BLOB data; - struct tdr_push *push; uint32_t offset; nk.header = "nk"; @@ -566,29 +567,13 @@ static WERROR regf_add_key (TALLOC_CTX *ctx, struct registry_key *parent, const nk.clsname_length = 0; nk.key_name = name; - push = talloc_zero(ctx, struct tdr_push); - if (NT_STATUS_IS_ERR(tdr_push_nk_block(push, &nk))) { - DEBUG(0, ("Error storing 'nk' block\n")); - return WERR_GENERAL_FAILURE; - } - - offset = hbin_store(parent->hive->backend_data, push->data); + offset = hbin_store_tdr(parent->hive->backend_data, (tdr_push_fn_t) tdr_push_nk_block, &nk); parent_nk->subkeys_offset = lf_add_entry(parent->hive->backend_data, parent_nk->subkeys_offset, name, nk.parent_offset); parent_nk->num_subkeys++; - ZERO_STRUCTP(push); - - if (NT_STATUS_IS_ERR(tdr_push_nk_block(push, parent_nk))) { - DEBUG(0, ("Error storing parent 'nk' block\n")); - return WERR_GENERAL_FAILURE; - } - - data = hbin_get_data(parent->hive->backend_data, nk.parent_offset); - memcpy(data.data, push->data.data, push->data.length); - - talloc_free(push); + hbin_store_tdr_resize(parent->hive->backend_data, (tdr_push_fn_t) tdr_push_nk_block, nk.parent_offset, parent_nk); /* FIXME: Set sec desc ! */ @@ -628,6 +613,8 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key) 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, h->location)); diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h index 9d9d2b8adf..a37a1efaaa 100644 --- a/source4/lib/tdr/tdr.h +++ b/source4/lib/tdr/tdr.h @@ -52,3 +52,6 @@ struct tdr_print { (s) = talloc_array_size(tdr, sizeof(*(s)), n); \ if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \ } while (0) + +typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, void *); +typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, void *); -- cgit