source: trunk/include/regfi.h @ 109

Last change on this file since 109 was 109, checked in by tim, 16 years ago

reworked SK record caching to prevent unnecessary loads.

SK records now cached in iterators on an as-needed basis

  • Property svn:keywords set to Id
File size: 11.7 KB
RevLine 
[30]1/*
2 * Branched from Samba project, Subversion repository version #6903:
[84]3 *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/include/regfio.h?rev=6903&view=auto
[30]4 *
5 * Unix SMB/CIFS implementation.
6 * Windows NT registry I/O library
7 *
[101]8 * Copyright (C) 2005-2008 Timothy D. Morgan
[30]9 * Copyright (C) 2005 Gerald (Jerry) Carter
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Id: regfi.h 109 2008-04-29 20:38:27Z tim $
25 */
26
27/************************************************************
28 * Most of this information was obtained from
29 * http://www.wednesday.demon.co.uk/dosreg.html
30 * Thanks Nigel!
31 ***********************************************************/
32
[78]33#ifndef _REGFI_H
34#define _REGFI_H
[30]35
[31]36#include <stdlib.h>
37#include <stdio.h>
[30]38#include <stdbool.h>
[31]39#include <string.h>
[30]40#include <errno.h>
[31]41#include <time.h>
[30]42#include <fcntl.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <unistd.h>
46#include <assert.h>
47
48#include "smb_deps.h"
[78]49#include "void_stack.h"
[99]50#include "range_list.h"
[108]51#include "lru_cache.h"
[30]52
53/******************************************************************************/
54/* Macros */
55 
[32]56/* Registry data types */
57#define REG_NONE                       0
58#define REG_SZ                         1
59#define REG_EXPAND_SZ                  2
60#define REG_BINARY                     3
61#define REG_DWORD                      4
[54]62#define REG_DWORD_LE                   4  /* DWORD, little endian */
63#define REG_DWORD_BE                   5  /* DWORD, big endian */
[32]64#define REG_LINK                       6
65#define REG_MULTI_SZ                   7
66#define REG_RESOURCE_LIST              8
67#define REG_FULL_RESOURCE_DESCRIPTOR   9
68#define REG_RESOURCE_REQUIREMENTS_LIST 10
[72]69#define REG_QWORD                      11 /* 64-bit little endian */
70/* XXX: Has MS defined a REG_QWORD_BE? */
[32]71/* Not a real type in the registry */
[81]72#define REG_KEY                        0x7FFFFFFF
[32]73
[107]74#define REGFI_FLAG_NONE         0x0
75#define REGFI_FLAG_SAVE_UNALLOC 0x1
[32]76
[30]77#define REGF_BLOCKSIZE          0x1000
[97]78#define REGF_ALLOC_BLOCK        0x1000  /* Minimum allocation unit for hbins */
[78]79#define REGF_MAX_DEPTH          512
[30]80
81/* header sizes for various records */
82
[97]83#define REGF_MAGIC_SIZE         4
84#define HBIN_MAGIC_SIZE         4
85#define HBIN_HEADER_REC_SIZE    0x20
[30]86#define REC_HDR_SIZE            2
87
88#define REGF_OFFSET_NONE        0xffffffff
[101]89#define REGFI_NK_MIN_LENGTH     0x4C
90#define REGFI_VK_MIN_LENGTH     0x14
[102]91#define REGFI_SK_MIN_LENGTH     0x14
[104]92#define REGFI_HASH_LIST_MIN_LENGTH     0x4
[30]93
94/* Flags for the vk records */
95
96#define VK_FLAG_NAME_PRESENT    0x0001
97#define VK_DATA_IN_OFFSET       0x80000000
[77]98#define VK_MAX_DATA_LENGTH      1024*1024
[30]99
100/* NK record macros */
101
102#define NK_TYPE_LINKKEY         0x0010
103#define NK_TYPE_NORMALKEY       0x0020
104#define NK_TYPE_ROOTKEY         0x002c
[101]105  /* TODO: Unknown type that shows up in Vista registries */
106#define NK_TYPE_UNKNOWN1         0x1020
[30]107
[54]108#define HBIN_STORE_REF(x, y) { x->hbin = y; y->ref_count++ };
109/* if the count == 0; we can clean up */
110#define HBIN_REMOVE_REF(x, y){ x->hbin = NULL; y->ref_count-- };
[30]111
112
113/* HBIN block */
[97]114typedef struct regf_hbin
115{
[53]116  uint32 file_off;       /* my offset in the registry file */
[84]117  uint32 ref_count;      /* how many active records are pointing to this
[54]118                          * block (not used currently)
119                          */
[84]120 
[53]121  uint32 first_hbin_off; /* offset from first hbin block */
[97]122  uint32 block_size;     /* block size of this block
123                          * Should be a multiple of 4096 (0x1000)
[54]124                          */
[99]125  uint32 next_block;     /* relative offset to next block. 
126                          * NOTE: This value may be unreliable!
[97]127                          */
128
129  uint8 magic[HBIN_MAGIC_SIZE]; /* "hbin" */
[30]130} REGF_HBIN;
131
[97]132
133/* Hash List -- list of key offsets and hashed names for consistency */
134typedef struct 
135{
[53]136  uint32 nk_off;
[104]137  uint32 hash;
138} REGF_HASH_LIST_ELEM;
[30]139
[97]140
141typedef struct 
142{
[104]143  uint32 offset;        /* Real offset of this record's cell in the file */
144  uint32 cell_size;      /* ((start_offset - end_offset) & 0xfffffff8) */
[84]145  REGF_HBIN* hbin;       /* pointer to HBIN record (in memory) containing
[54]146                          * this nk record
147                          */
148  uint32 hbin_off;       /* offset from beginning of this hbin block */
[104]149  REGF_HASH_LIST_ELEM* hashes;
[53]150 
[104]151  uint8 magic[REC_HDR_SIZE];
[53]152  uint16 num_keys;
[104]153} REGF_HASH_LIST;
[30]154
[97]155
[30]156/* Key Value */
[97]157typedef struct 
158{
[101]159  uint32 offset;        /* Real offset of this record's cell in the file */
160  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
161
[84]162  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
[54]163                         * this nk record
164                         */
[101]165  uint8* data;
166  uint16 name_length;
[84]167  char*  valuename;
[53]168  uint32 hbin_off;      /* offset from beginning of this hbin block */
169 
170  uint32 data_size;
[101]171  uint32 data_off;      /* offset of data cell (virtual) */
[53]172  uint32 type;
[101]173  uint8  magic[REC_HDR_SIZE];
[53]174  uint16 flag;
[101]175  uint16 unknown1;
[30]176} REGF_VK_REC;
177
178
179/* Key Security */
180struct _regf_sk_rec;
181
[97]182typedef struct _regf_sk_rec
183{
[84]184  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
[54]185                         * this nk record
186                         */
[84]187  SEC_DESC* sec_desc;
[53]188  uint32 hbin_off;      /* offset from beginning of this hbin block */
[99]189  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
[102]190  uint32 offset;        /* Real file offset of this record */
[53]191 
[54]192  uint32 sk_off;        /* offset parsed from NK record used as a key
193                         * to lookup reference to this SK record
194                         */
[53]195 
196  uint32 prev_sk_off;
197  uint32 next_sk_off;
198  uint32 ref_count;
[102]199  uint32 desc_size;     /* size of security descriptor */
200  uint16 unknown_tag;
201  uint8  magic[REC_HDR_SIZE];
[30]202} REGF_SK_REC;
203
[81]204
[104]205/* Key Name */
206typedef struct
[97]207{
[99]208  uint32 offset;        /* Real offset of this record's cell in the file */
209  uint32 cell_size;     /* Actual or estimated length of the cell. 
210                         * Always in multiples of 8.
211                         */
[84]212
213  /* link in the other records here */
[101]214  REGF_VK_REC** values;
[104]215  REGF_HASH_LIST* subkeys;
[53]216 
217  /* header information */
[84]218  /* XXX: should we be looking for types other than the root key type? */
219  uint16 key_type;     
[101]220  uint8  magic[REC_HDR_SIZE];
[53]221  NTTIME mtime;
[99]222  uint16 name_length;
223  uint16 classname_length;
[84]224  char* classname;
225  char* keyname;
[53]226  uint32 parent_off;    /* back pointer in registry hive */
227  uint32 classname_off; 
228 
229  /* max lengths */
[54]230  uint32 max_bytes_subkeyname;      /* max subkey name * 2 */
231  uint32 max_bytes_subkeyclassname; /* max subkey classname length (as if) */
232  uint32 max_bytes_valuename;       /* max valuename * 2 */
233  uint32 max_bytes_value;           /* max value data size */
[53]234 
235  /* unknowns */
[99]236  uint32 unknown1;
237  uint32 unknown2;
238  uint32 unknown3;
[54]239  uint32 unk_index;                 /* nigel says run time index ? */
[53]240 
241  /* children */
242  uint32 num_subkeys;
243  uint32 subkeys_off;   /* hash records that point to NK records */     
244  uint32 num_values;
245  uint32 values_off;    /* value lists which point to VK records */
[97]246  uint32 sk_off;        /* offset to SK record */ 
[30]247} REGF_NK_REC;
248
[81]249
[97]250
[30]251/* REGF block */
[97]252typedef struct 
253{
[53]254  /* run time information */
[54]255  int fd;         /* file descriptor */
[97]256  /* For sanity checking (not part of the registry header) */
257  uint32 file_length;
[84]258  void* mem_ctx;  /* memory context for run-time file access information */
[99]259
260  /* Experimental hbin lists */
261  range_list* hbins;
262  range_list* unalloc_cells;
263
[108]264  /* file format information */ 
[97]265  uint8  magic[REGF_MAGIC_SIZE];/* "regf" */
[84]266  NTTIME mtime;
[54]267  uint32 data_offset;           /* offset to record in the first (or any?)
268                                 * hbin block
269                                 */
[53]270  uint32 last_block;            /* offset to last hbin block in file */
[97]271
272  uint32 checksum;              /* Stored checksum. */
273  uint32 computed_checksum;     /* Our own calculation of the checksum.
274                                 * (XOR of bytes 0x0000 - 0x01FB)
275                                 */
[53]276 
[97]277  /* unknown data structure values */
[53]278  uint32 unknown1;
279  uint32 unknown2;
280  uint32 unknown3;
281  uint32 unknown4;
282  uint32 unknown5;
283  uint32 unknown6;
[97]284  uint32 unknown7;
[53]285} REGF_FILE;
[30]286
287
[97]288
289typedef struct 
290{
[78]291  REGF_FILE* f;
[80]292  void_stack* key_positions;
[109]293  lru_cache* sk_recs;
[80]294  REGF_NK_REC* cur_key;
[78]295  uint32 cur_subkey;
296  uint32 cur_value;
297} REGFI_ITERATOR;
298
[80]299
[97]300typedef struct 
301{
[80]302  REGF_NK_REC* nk;
303  uint32 cur_subkey;
304  /* We could store a cur_value here as well, but didn't see
305   * the use in it right now.
306   */
307} REGFI_ITER_POSITION;
308
309
[54]310/******************************************************************************/
[30]311/* Function Declarations */
[99]312/*  Main API */
[84]313const char*           regfi_type_val2str(unsigned int val);
314int                   regfi_type_str2val(const char* str);
[32]315
[84]316char*                 regfi_get_sacl(SEC_DESC* sec_desc);
317char*                 regfi_get_dacl(SEC_DESC* sec_desc);
318char*                 regfi_get_owner(SEC_DESC* sec_desc);
319char*                 regfi_get_group(SEC_DESC* sec_desc);
[53]320
[107]321REGF_FILE*            regfi_open(const char* filename, uint32 flags);
[84]322int                   regfi_close(REGF_FILE* r);
[30]323
[84]324REGFI_ITERATOR*       regfi_iterator_new(REGF_FILE* fh);
325void                  regfi_iterator_free(REGFI_ITERATOR* i);
326bool                  regfi_iterator_down(REGFI_ITERATOR* i);
327bool                  regfi_iterator_up(REGFI_ITERATOR* i);
328bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
[30]329
[84]330bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i, 
331                                                 const char* subkey_name);
332bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i, 
333                                               const char** path);
334const REGF_NK_REC*    regfi_iterator_cur_key(REGFI_ITERATOR* i);
[109]335const REGF_SK_REC*    regfi_iterator_cur_sk(REGFI_ITERATOR* i);
[84]336const REGF_NK_REC*    regfi_iterator_first_subkey(REGFI_ITERATOR* i);
337const REGF_NK_REC*    regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
338const REGF_NK_REC*    regfi_iterator_next_subkey(REGFI_ITERATOR* i);
[80]339
[84]340bool                  regfi_iterator_find_value(REGFI_ITERATOR* i, 
341                                                const char* value_name);
342const REGF_VK_REC*    regfi_iterator_first_value(REGFI_ITERATOR* i);
343const REGF_VK_REC*    regfi_iterator_cur_value(REGFI_ITERATOR* i);
344const REGF_VK_REC*    regfi_iterator_next_value(REGFI_ITERATOR* i);
[80]345
[99]346/************************************/
347/*  Low-layer data structure access */
348/************************************/
349REGF_FILE*            regfi_parse_regf(int fd, bool strict);
350REGF_HBIN*            regfi_parse_hbin(REGF_FILE* file, uint32 offset, 
351                                       bool strict, bool save_unalloc);
[80]352
[99]353
354/* regfi_parse_nk: Parses an NK record.
355 *
356 * Arguments:
357 *   f        -- the registry file structure
358 *   offset   -- the offset of the cell (not the record) to be parsed.
359 *   max_size -- the maximum size the NK cell could be. (for validation)
360 *   strict   -- if true, rejects any malformed records.  Otherwise,
361 *               tries to minimally validate integrity.
362 * Returns:
363 *   A newly allocated NK record structure, or NULL on failure.
364 */
365REGF_NK_REC*          regfi_parse_nk(REGF_FILE* file, uint32 offset, 
366                                     uint32 max_size, bool strict);
367
368
[84]369/* Private Functions */
370REGF_NK_REC*          regfi_rootkey(REGF_FILE* file);
371void                  regfi_key_free(REGF_NK_REC* nk);
[99]372uint32                regfi_read(int fd, uint8* buf, uint32* length);
[78]373
[84]374
[97]375
376/****************/
377/* Experimental */
378/****************/
[105]379REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict);
380
[104]381REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset, 
[105]382                                    uint32 num_keys, uint32 max_size, 
383                                    bool strict);
[97]384
[103]385REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset, 
[105]386                                   uint32 num_values, uint32 max_size, 
387                                   bool strict);
[103]388
[101]389REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset, 
390                            uint32 max_size, bool strict);
[103]391
[101]392uint8* regfi_parse_data(REGF_FILE* file, uint32 offset, 
393                        uint32 length, bool strict);
[97]394
[101]395
[78]396#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.