diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2006-05-05 13:16:58 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:05:38 -0500 |
commit | bd90da5b60b82c8ddc82fa434aa724fba0749e0c (patch) | |
tree | 7071ddf7de1b1dc5ac00bfe4c896a381c0c2a40d /source4/lib | |
parent | b56789c3491d227dd4107a37de701101c780a0f9 (diff) | |
download | samba-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.c | 126 | ||||
-rw-r--r-- | source4/lib/registry/regf.idl | 20 |
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; |