Author: jelmer
Date: 2006-05-05 13:16:58 +0000 (Fri, 05 May 2006)
New Revision: 15458

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15458

Log:
Fix support for Windows XP-style registry files and support for large numbers 
of subkeys.

Patch by Wilco Baan Hofman <[EMAIL PROTECTED]>

Modified:
   branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c
   branches/SAMBA_4_0/source/lib/registry/regf.idl


Changeset:
Modified: branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c
===================================================================
--- branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c    2006-05-05 
13:02:14 UTC (rev 15457)
+++ branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c    2006-05-05 
13:16:58 UTC (rev 15458)
@@ -2,6 +2,7 @@
    Samba CIFS implementation
    Registry backend for REGF files
    Copyright (C) 2005 Jelmer Vernooij, [EMAIL PROTECTED]
+   Copyright (C) 2006 Wilco Baan Hofman, [EMAIL PROTECTED]
 
    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 @@
        }
 
        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 @@
                        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;
+               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"));
+               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)) {
-               DEBUG(4, ("Subkeys in RI list\n"));
-               SMB_ASSERT(0);
-       } else if (!strncmp((char *)data.data, "lh", 2)) {
-               DEBUG(4, ("Subkeys in LH list\n"));
-               SMB_ASSERT(0);
+               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 @@
        }
 
        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 @@
        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))) {

Modified: branches/SAMBA_4_0/source/lib/registry/regf.idl
===================================================================
--- branches/SAMBA_4_0/source/lib/registry/regf.idl     2006-05-05 13:02:14 UTC 
(rev 15457)
+++ branches/SAMBA_4_0/source/lib/registry/regf.idl     2006-05-05 13:16:58 UTC 
(rev 15458)
@@ -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, [EMAIL PROTECTED]
+   Copyright (C) 2006 Wilco Baan Hofman, [EMAIL PROTECTED]
    
  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 @@
                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 @@
        } vk_block;
 
        typedef [noprint] struct {
-               uint32 nk_off;
+               uint32 nk_offset;
                [charset(DOS)] uint8 hash[4];
        } hash_record;
 

Reply via email to