summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2006-05-05 13:16:58 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:05:38 -0500
commitbd90da5b60b82c8ddc82fa434aa724fba0749e0c (patch)
tree7071ddf7de1b1dc5ac00bfe4c896a381c0c2a40d /source4/lib
parentb56789c3491d227dd4107a37de701101c780a0f9 (diff)
downloadsamba-bd90da5b60b82c8ddc82fa434aa724fba0749e0c.tar.gz
samba-bd90da5b60b82c8ddc82fa434aa724fba0749e0c.tar.bz2
samba-bd90da5b60b82c8ddc82fa434aa724fba0749e0c.zip
r15458: Fix support for Windows XP-style registry files and support for large numbers of subkeys.
Patch by Wilco Baan Hofman <wilco@baanhofman.nl> (This used to be commit 02859870d62b875eca5feff175c489a93fa7ad84)
Diffstat (limited to 'source4/lib')
-rw-r--r--source4/lib/registry/reg_backend_nt4.c126
-rw-r--r--source4/lib/registry/regf.idl20
2 files changed, 126 insertions, 20 deletions
diff --git a/source4/lib/registry/reg_backend_nt4.c b/source4/lib/registry/reg_backend_nt4.c
index 569b1e1942..1413cb7c5e 100644
--- a/source4/lib/registry/reg_backend_nt4.c
+++ b/source4/lib/registry/reg_backend_nt4.c
@@ -2,6 +2,7 @@
Samba CIFS implementation
Registry backend for REGF files
Copyright (C) 2005 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
@@ -484,8 +485,25 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, const struct registry_key *key,
}
if (!strncmp((char *)data.data, "li", 2)) {
- DEBUG(4, ("Subkeys in LI list\n"));
- SMB_ASSERT(0);
+ 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;
@@ -498,19 +516,107 @@ static WERROR regf_get_subkey (TALLOC_CTX *ctx, const struct registry_key *key,
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_off;
- } else if (!strncmp((char *)data.data, "ri", 2)) {
- DEBUG(4, ("Subkeys in RI list\n"));
- SMB_ASSERT(0);
+ key_off = lf.hr[idx].nk_offset;
} else if (!strncmp((char *)data.data, "lh", 2)) {
- DEBUG(4, ("Subkeys in LH list\n"));
- SMB_ASSERT(0);
+ struct lh_block lh;
+ struct tdr_pull pull;
+
+ DEBUG(10, ("Subkeys in LH list"));
+ 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;
+
+ 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(key->hive->backend_data, 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;
+
+ 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;
+
+ 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"));
+ SMB_ASSERT(0);
+ }
+
+ }
+
+ 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;
@@ -577,7 +683,7 @@ static uint32_t lf_add_entry (struct regf_data *regf, uint32_t list_offset, cons
}
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].nk_offset = key_offset;
lf.hr[lf.key_count].hash = talloc_strndup(regf, name, 4);
lf.key_count++;
@@ -736,7 +842,7 @@ static WERROR nt_open_hive (struct registry_hive *h, struct registry_key **key)
regf->hbins = talloc_array(regf, struct hbin_block *, 1);
regf->hbins[0] = NULL;
- while (pull.offset < pull.data.length) {
+ while (pull.offset < pull.data.length && pull.offset < regf->header->last_block) {
struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block);
if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) {
diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl
index 8f5db8c236..48a34462e6 100644
--- a/source4/lib/registry/regf.idl
+++ b/source4/lib/registry/regf.idl
@@ -2,13 +2,13 @@
Definitions for the REGF registry file format as used by
Windows NT4 and above.
- Written by Jelmer Vernooij, 2005
+ Copyright (C) 2005 Jelmer Vernooij, jelmer@samba.org
+ Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl
Based on two files from Samba 3:
regedit.c by Richard Sharpe
regfio.c by Jerry Carter
- Thanks to Wilco Baan Hofman for some of the info on li and ri fields.
*/
interface regf
@@ -114,25 +114,25 @@ interface regf
uint8 sec_desc[rec_size];
} sk_block;
- typedef [noprint,nopush,nopull] struct {
- uint32 offset_nk;
+ typedef [noprint] struct {
+ uint32 nk_offset;
uint32 base37; /* base37 of key name */
} lh_hash;
/* Subkey listing with hash of first 4 characters */
- typedef [noprint,nopush,nopull] struct {
+ typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
- lh_hash hashes[key_count];
+ lh_hash hr[key_count];
} lh_block;
- typedef [noprint,nopush,nopull] struct {
+ typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
- uint32 offset_nk[key_count];
+ uint32 nk_offset[key_count];
} li_block;
- typedef [noprint,nopush,nopull] struct {
+ typedef [public,noprint] struct {
[charset(DOS)] uint8 header[2];
uint16 key_count;
uint32 offset[key_count]; /* li/lh offset */
@@ -151,7 +151,7 @@ interface regf
} vk_block;
typedef [noprint] struct {
- uint32 nk_off;
+ uint32 nk_offset;
[charset(DOS)] uint8 hash[4];
} hash_record;