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
Line 
1/*
2 * Branched from Samba project, Subversion repository version #6903:
3 *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/include/regfio.h?rev=6903&view=auto
4 *
5 * Unix SMB/CIFS implementation.
6 * Windows NT registry I/O library
7 *
8 * Copyright (C) 2005-2008 Timothy D. Morgan
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
33#ifndef _REGFI_H
34#define _REGFI_H
35
36#include <stdlib.h>
37#include <stdio.h>
38#include <stdbool.h>
39#include <string.h>
40#include <errno.h>
41#include <time.h>
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"
49#include "void_stack.h"
50#include "range_list.h"
51#include "lru_cache.h"
52
53/******************************************************************************/
54/* Macros */
55 
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
62#define REG_DWORD_LE                   4  /* DWORD, little endian */
63#define REG_DWORD_BE                   5  /* DWORD, big endian */
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
69#define REG_QWORD                      11 /* 64-bit little endian */
70/* XXX: Has MS defined a REG_QWORD_BE? */
71/* Not a real type in the registry */
72#define REG_KEY                        0x7FFFFFFF
73
74#define REGFI_FLAG_NONE         0x0
75#define REGFI_FLAG_SAVE_UNALLOC 0x1
76
77#define REGF_BLOCKSIZE          0x1000
78#define REGF_ALLOC_BLOCK        0x1000  /* Minimum allocation unit for hbins */
79#define REGF_MAX_DEPTH          512
80
81/* header sizes for various records */
82
83#define REGF_MAGIC_SIZE         4
84#define HBIN_MAGIC_SIZE         4
85#define HBIN_HEADER_REC_SIZE    0x20
86#define REC_HDR_SIZE            2
87
88#define REGF_OFFSET_NONE        0xffffffff
89#define REGFI_NK_MIN_LENGTH     0x4C
90#define REGFI_VK_MIN_LENGTH     0x14
91#define REGFI_SK_MIN_LENGTH     0x14
92#define REGFI_HASH_LIST_MIN_LENGTH     0x4
93
94/* Flags for the vk records */
95
96#define VK_FLAG_NAME_PRESENT    0x0001
97#define VK_DATA_IN_OFFSET       0x80000000
98#define VK_MAX_DATA_LENGTH      1024*1024
99
100/* NK record macros */
101
102#define NK_TYPE_LINKKEY         0x0010
103#define NK_TYPE_NORMALKEY       0x0020
104#define NK_TYPE_ROOTKEY         0x002c
105  /* TODO: Unknown type that shows up in Vista registries */
106#define NK_TYPE_UNKNOWN1         0x1020
107
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-- };
111
112
113/* HBIN block */
114typedef struct regf_hbin
115{
116  uint32 file_off;       /* my offset in the registry file */
117  uint32 ref_count;      /* how many active records are pointing to this
118                          * block (not used currently)
119                          */
120 
121  uint32 first_hbin_off; /* offset from first hbin block */
122  uint32 block_size;     /* block size of this block
123                          * Should be a multiple of 4096 (0x1000)
124                          */
125  uint32 next_block;     /* relative offset to next block. 
126                          * NOTE: This value may be unreliable!
127                          */
128
129  uint8 magic[HBIN_MAGIC_SIZE]; /* "hbin" */
130} REGF_HBIN;
131
132
133/* Hash List -- list of key offsets and hashed names for consistency */
134typedef struct 
135{
136  uint32 nk_off;
137  uint32 hash;
138} REGF_HASH_LIST_ELEM;
139
140
141typedef struct 
142{
143  uint32 offset;        /* Real offset of this record's cell in the file */
144  uint32 cell_size;      /* ((start_offset - end_offset) & 0xfffffff8) */
145  REGF_HBIN* hbin;       /* pointer to HBIN record (in memory) containing
146                          * this nk record
147                          */
148  uint32 hbin_off;       /* offset from beginning of this hbin block */
149  REGF_HASH_LIST_ELEM* hashes;
150 
151  uint8 magic[REC_HDR_SIZE];
152  uint16 num_keys;
153} REGF_HASH_LIST;
154
155
156/* Key Value */
157typedef struct 
158{
159  uint32 offset;        /* Real offset of this record's cell in the file */
160  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
161
162  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
163                         * this nk record
164                         */
165  uint8* data;
166  uint16 name_length;
167  char*  valuename;
168  uint32 hbin_off;      /* offset from beginning of this hbin block */
169 
170  uint32 data_size;
171  uint32 data_off;      /* offset of data cell (virtual) */
172  uint32 type;
173  uint8  magic[REC_HDR_SIZE];
174  uint16 flag;
175  uint16 unknown1;
176} REGF_VK_REC;
177
178
179/* Key Security */
180struct _regf_sk_rec;
181
182typedef struct _regf_sk_rec
183{
184  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
185                         * this nk record
186                         */
187  SEC_DESC* sec_desc;
188  uint32 hbin_off;      /* offset from beginning of this hbin block */
189  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
190  uint32 offset;        /* Real file offset of this record */
191 
192  uint32 sk_off;        /* offset parsed from NK record used as a key
193                         * to lookup reference to this SK record
194                         */
195 
196  uint32 prev_sk_off;
197  uint32 next_sk_off;
198  uint32 ref_count;
199  uint32 desc_size;     /* size of security descriptor */
200  uint16 unknown_tag;
201  uint8  magic[REC_HDR_SIZE];
202} REGF_SK_REC;
203
204
205/* Key Name */
206typedef struct
207{
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                         */
212
213  /* link in the other records here */
214  REGF_VK_REC** values;
215  REGF_HASH_LIST* subkeys;
216 
217  /* header information */
218  /* XXX: should we be looking for types other than the root key type? */
219  uint16 key_type;     
220  uint8  magic[REC_HDR_SIZE];
221  NTTIME mtime;
222  uint16 name_length;
223  uint16 classname_length;
224  char* classname;
225  char* keyname;
226  uint32 parent_off;    /* back pointer in registry hive */
227  uint32 classname_off; 
228 
229  /* max lengths */
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 */
234 
235  /* unknowns */
236  uint32 unknown1;
237  uint32 unknown2;
238  uint32 unknown3;
239  uint32 unk_index;                 /* nigel says run time index ? */
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 */
246  uint32 sk_off;        /* offset to SK record */ 
247} REGF_NK_REC;
248
249
250
251/* REGF block */
252typedef struct 
253{
254  /* run time information */
255  int fd;         /* file descriptor */
256  /* For sanity checking (not part of the registry header) */
257  uint32 file_length;
258  void* mem_ctx;  /* memory context for run-time file access information */
259
260  /* Experimental hbin lists */
261  range_list* hbins;
262  range_list* unalloc_cells;
263
264  /* file format information */ 
265  uint8  magic[REGF_MAGIC_SIZE];/* "regf" */
266  NTTIME mtime;
267  uint32 data_offset;           /* offset to record in the first (or any?)
268                                 * hbin block
269                                 */
270  uint32 last_block;            /* offset to last hbin block in file */
271
272  uint32 checksum;              /* Stored checksum. */
273  uint32 computed_checksum;     /* Our own calculation of the checksum.
274                                 * (XOR of bytes 0x0000 - 0x01FB)
275                                 */
276 
277  /* unknown data structure values */
278  uint32 unknown1;
279  uint32 unknown2;
280  uint32 unknown3;
281  uint32 unknown4;
282  uint32 unknown5;
283  uint32 unknown6;
284  uint32 unknown7;
285} REGF_FILE;
286
287
288
289typedef struct 
290{
291  REGF_FILE* f;
292  void_stack* key_positions;
293  lru_cache* sk_recs;
294  REGF_NK_REC* cur_key;
295  uint32 cur_subkey;
296  uint32 cur_value;
297} REGFI_ITERATOR;
298
299
300typedef struct 
301{
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
310/******************************************************************************/
311/* Function Declarations */
312/*  Main API */
313const char*           regfi_type_val2str(unsigned int val);
314int                   regfi_type_str2val(const char* str);
315
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);
320
321REGF_FILE*            regfi_open(const char* filename, uint32 flags);
322int                   regfi_close(REGF_FILE* r);
323
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);
329
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);
335const REGF_SK_REC*    regfi_iterator_cur_sk(REGFI_ITERATOR* i);
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);
339
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);
345
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);
352
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
369/* Private Functions */
370REGF_NK_REC*          regfi_rootkey(REGF_FILE* file);
371void                  regfi_key_free(REGF_NK_REC* nk);
372uint32                regfi_read(int fd, uint8* buf, uint32* length);
373
374
375
376/****************/
377/* Experimental */
378/****************/
379REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict);
380
381REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset, 
382                                    uint32 num_keys, uint32 max_size, 
383                                    bool strict);
384
385REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset, 
386                                   uint32 num_values, uint32 max_size, 
387                                   bool strict);
388
389REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset, 
390                            uint32 max_size, bool strict);
391
392uint8* regfi_parse_data(REGF_FILE* file, uint32 offset, 
393                        uint32 length, bool strict);
394
395
396#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.