source: trunk/include/regfi.h @ 145

Last change on this file since 145 was 145, checked in by tim, 15 years ago

decoupled value parsing from key parsing

moved linking of value records and data records up to the load layer

rewrote key/value/data linking algorithm in reglookup-recover which improved recovery results

fixed a NULL pointer dereference in range_list.c

  • Property svn:keywords set to Id
File size: 16.9 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 * Windows NT (and later) registry parsing library
6 *
7 * Copyright (C) 2005-2009 Timothy D. Morgan
8 * Copyright (C) 2005 Gerald (Jerry) Carter
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 3 of the License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 * $Id: regfi.h 145 2009-02-15 23:36:20Z tim $
24 */
25
26/************************************************************
27 * Most of this information was obtained from
28 * http://www.wednesday.demon.co.uk/dosreg.html
29 * Thanks Nigel!
30 ***********************************************************/
31
32#ifndef _REGFI_H
33#define _REGFI_H
34
35#include <stdlib.h>
36#include <stdio.h>
37#include <stdbool.h>
38#include <stdarg.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 "winsec.h"
50#include "void_stack.h"
51#include "range_list.h"
52#include "lru_cache.h"
53
54/******************************************************************************/
55
56/* regfi library error message types */
57#define REGFI_MSG_INFO  0x0001
58#define REGFI_MSG_WARN  0x0004
59#define REGFI_MSG_ERROR 0x0010
60
61/* Windows is lame */
62#ifdef O_BINARY
63#define REGFI_OPEN_FLAGS O_RDONLY|O_BINARY
64#else
65#define REGFI_OPEN_FLAGS O_RDONLY
66#endif
67
68/* Registry data types */
69#define REG_NONE                       0
70#define REG_SZ                         1
71#define REG_EXPAND_SZ                  2
72#define REG_BINARY                     3
73#define REG_DWORD                      4
74#define REG_DWORD_LE                   4  /* DWORD, little endian */
75#define REG_DWORD_BE                   5  /* DWORD, big endian */
76#define REG_LINK                       6
77#define REG_MULTI_SZ                   7
78#define REG_RESOURCE_LIST              8
79#define REG_FULL_RESOURCE_DESCRIPTOR   9
80#define REG_RESOURCE_REQUIREMENTS_LIST 10
81#define REG_QWORD                      11 /* 64-bit little endian */
82/* XXX: Has MS defined a REG_QWORD_BE? */
83/* Not a real type in the registry */
84#define REG_KEY                    0x7FFFFFFF
85
86#define REGFI_REGF_SIZE            0x1000 /* "regf" header block size */
87#define REGFI_HBIN_ALLOC           0x1000 /* Minimum allocation unit for HBINs */
88#define REGFI_MAX_DEPTH            512
89#define REGFI_OFFSET_NONE          0xffffffff
90
91/* XXX: This is totally arbitrary right now. */
92#define REGFI_MAX_SUBKEY_DEPTH     255   
93
94/* Header sizes and magic number lengths for various records */
95#define REGFI_REGF_MAGIC_SIZE      4
96#define REGFI_HBIN_MAGIC_SIZE      4
97#define REGFI_CELL_MAGIC_SIZE      2
98#define REGFI_HBIN_HEADER_SIZE     0x20
99#define REGFI_NK_MIN_LENGTH        0x4C
100#define REGFI_VK_MIN_LENGTH        0x14
101#define REGFI_SK_MIN_LENGTH        0x14
102#define REGFI_SUBKEY_LIST_MIN_LEN  0x4
103
104
105/* Constants used for validation */
106/* XXX: Can we add clock resolution validation as well as range?  It has
107 *      been reported that Windows timestamps are never more than a
108 *      certain granularity (250ms?), which could be used to help
109 *      eliminate false positives.  Would need to validate this and
110 *      perhaps conservatively implement a check.
111 */
112 /* Minimum time is Jan 1, 1990 00:00:00 */
113#define REGFI_MTIME_MIN_HIGH       0x01B41E6D
114#define REGFI_MTIME_MIN_LOW        0x26F98000
115 /* Maximum time is Jan 1, 2290 00:00:00
116  * (We hope no one is using Windows by then...)
117  */
118#define REGFI_MTIME_MAX_HIGH       0x03047543
119#define REGFI_MTIME_MAX_LOW        0xC80A4000
120
121
122/* Flags for the vk records */
123#define REGFI_VK_FLAG_NAME_PRESENT 0x0001
124#define REGFI_VK_DATA_IN_OFFSET    0x80000000
125#define REGFI_VK_MAX_DATA_LENGTH   1024*1024
126
127
128/* NK record types */
129/* XXX: This is starting to look like this is a flags field. 
130 *      Need to decipher the meaning of each flag.
131 */
132#define REGFI_NK_TYPE_LINKKEY      0x0010
133#define REGFI_NK_TYPE_NORMALKEY    0x0020
134 /* XXX: Unknown key type that shows up in Vista registries */
135#define REGFI_NK_TYPE_UNKNOWN1     0x1020
136 /* XXX: Unknown key types that shows up in W2K3 registries */
137#define REGFI_NK_TYPE_UNKNOWN2     0x4020
138#define REGFI_NK_TYPE_UNKNOWN3     0x0000  /* XXX: This type seems to have UTF-16 names!!! */
139#define REGFI_NK_TYPE_ROOTKEY1     0x002c
140 /* XXX: Unknown root key type that shows up in Vista registries */
141#define REGFI_NK_TYPE_ROOTKEY2     0x00ac
142
143#if 0
144/* Initial hypothesis of NK flags: */
145/***********************************/
146#define REGFI_NK_FLAG_LINK         0x0010
147/* The name will be in ASCII if this next bit is set, otherwise UTF-16LE */
148#define REGFI_NK_FLAG_ASCIINAME    0x0020
149/* These next two combine to form the "c" on both known root key types */
150#define REGFI_NK_FLAG_ROOT1        0x0008
151#define REGFI_NK_FLAG_ROOT2        0x0004
152/* These next two show up on normal-seeming keys in Vista and W2K3 registries */
153#define REGFI_NK_FLAG_UNKNOWN1     0x4000
154#define REGFI_NK_FLAG_UNKNOWN2     0x1000
155/* This next one shows up on root keys in some Vista "software" registries */
156#define REGFI_NK_FLAG_UNKNOWN3     0x0080
157#endif
158
159
160
161/* HBIN block */
162typedef struct _regfi_hbin
163{
164  uint32 file_off;       /* my offset in the registry file */
165  uint32 ref_count;      /* how many active records are pointing to this
166                          * block (not used currently)
167                          */
168 
169  uint32 first_hbin_off; /* offset from first hbin block */
170  uint32 block_size;     /* block size of this block
171                          * Should be a multiple of 4096 (0x1000)
172                          */
173  uint32 next_block;     /* relative offset to next block. 
174                          * NOTE: This value may be unreliable!
175                          */
176
177  uint8 magic[REGFI_HBIN_MAGIC_SIZE]; /* "hbin" */
178} REGFI_HBIN;
179
180
181/* Subkey List -- list of key offsets and hashed names for consistency */
182typedef struct 
183{
184  /* Virtual offset of NK record or additional subkey list,
185   * depending on this list's type.
186   */
187  uint32 offset;
188
189  uint32 hash;
190} REGFI_SUBKEY_LIST_ELEM;
191
192
193typedef struct _regfi_subkey_list
194{
195  /* Real offset of this record's cell in the file */
196  uint32 offset;
197
198  uint32 cell_size;
199 
200  /* Number of immediate children */
201  uint32 num_children; 
202
203  /* Total number of keys referenced by this list and it's children */
204  uint32 num_keys;     
205
206  REGFI_SUBKEY_LIST_ELEM* elements;
207  uint8 magic[REGFI_CELL_MAGIC_SIZE];
208
209  /* Set if the magic indicates this subkey list points to child subkey lists */
210  bool recursive_type; 
211} REGFI_SUBKEY_LIST;
212
213
214typedef uint32 REGFI_VALUE_LIST_ELEM;
215typedef struct _regfi_value_list
216{
217  /* Actual number of values referenced by this list. 
218   * May differ from parent key's num_values if there were parsing errors.
219   */
220  uint32 num_values;
221
222  REGFI_VALUE_LIST_ELEM* elements;
223} REGFI_VALUE_LIST;
224
225
226/* Key Value */
227typedef struct 
228{
229  uint32 offset;        /* Real offset of this record's cell in the file */
230  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
231
232  REGFI_HBIN* hbin;     /* pointer to HBIN record (in memory) containing
233                         * this nk record
234                         */
235  uint8* data;
236  uint16 name_length;
237  char*  valuename;
238  uint32 hbin_off;      /* offset from beginning of this hbin block */
239 
240  uint32 data_size;
241  uint32 data_off;      /* offset of data cell (virtual) */
242  uint32 type;
243  uint8  magic[REGFI_CELL_MAGIC_SIZE];
244  uint16 flag;
245  uint16 unknown1;
246  bool data_in_offset;
247} REGFI_VK_REC;
248
249
250/* Key Security */
251struct _regfi_sk_rec;
252
253typedef struct _regfi_sk_rec
254{
255  uint32 offset;        /* Real file offset of this record */
256  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
257
258  WINSEC_DESC* sec_desc;
259  uint32 hbin_off;      /* offset from beginning of this hbin block */
260 
261  uint32 sk_off;        /* offset parsed from NK record used as a key
262                         * to lookup reference to this SK record
263                         */
264 
265  uint32 prev_sk_off;
266  uint32 next_sk_off;
267  uint32 ref_count;
268  uint32 desc_size;     /* size of security descriptor */
269  uint16 unknown_tag;
270  uint8  magic[REGFI_CELL_MAGIC_SIZE];
271} REGFI_SK_REC;
272
273
274/* Key Name */
275typedef struct
276{
277  uint32 offset;        /* Real offset of this record's cell in the file */
278  uint32 cell_size;     /* Actual or estimated length of the cell. 
279                         * Always in multiples of 8.
280                         */
281
282  /* link in the other records here */
283  REGFI_VALUE_LIST* values;
284  REGFI_SUBKEY_LIST* subkeys;
285 
286  /* header information */
287  uint16 key_type;
288  uint8  magic[REGFI_CELL_MAGIC_SIZE];
289  NTTIME mtime;
290  uint16 name_length;
291  uint16 classname_length;
292  char* classname;
293  char* keyname;
294  uint32 parent_off;                /* pointer to parent key */
295  uint32 classname_off;
296 
297  /* max lengths */
298  uint32 max_bytes_subkeyname;      /* max subkey name * 2 */
299  uint32 max_bytes_subkeyclassname; /* max subkey classname length (as if) */
300  uint32 max_bytes_valuename;       /* max valuename * 2 */
301  uint32 max_bytes_value;           /* max value data size */
302 
303  /* unknowns */
304  uint32 unknown1;
305  uint32 unknown2;
306  uint32 unknown3;
307  uint32 unk_index;                 /* nigel says run time index ? */
308 
309  /* children */
310  uint32 num_subkeys;
311  uint32 subkeys_off;   /* offset of subkey list that points to NK records */
312  uint32 num_values;
313  uint32 values_off;    /* value lists which point to VK records */
314  uint32 sk_off;        /* offset to SK record */
315} REGFI_NK_REC;
316
317
318
319/* REGF block */
320typedef struct 
321{
322  /* Run-time information */
323  /************************/
324  /* file descriptor */
325  int fd;
326
327  /* For sanity checking (not part of the registry header) */
328  uint32 file_length;
329
330  /* Metadata about hbins */
331  range_list* hbins;
332
333  /* Error/warning/info messages returned by lower layer functions */
334  char* last_message;
335
336  /* Mask for error message types that will be stored. */
337  uint16 msg_mask;
338
339
340  /* Data parsed from file header */
341  /********************************/
342  uint8  magic[REGFI_REGF_MAGIC_SIZE];/* "regf" */
343  NTTIME mtime;
344  uint32 data_offset;           /* offset to record in the first (or any?)
345                                 * hbin block
346                                 */
347  uint32 last_block;            /* offset to last hbin block in file */
348
349  uint32 checksum;              /* Stored checksum. */
350  uint32 computed_checksum;     /* Our own calculation of the checksum.
351                                 * (XOR of bytes 0x0000 - 0x01FB)
352                                 */
353 
354  /* XXX: Some of these we have some clues about (major/minor version, etc).
355   *      Should verify and update names accordingly.
356   */
357  /* unknown data structure values */
358  uint32 unknown1;
359  uint32 unknown2;
360  uint32 unknown3;
361  uint32 unknown4;
362  uint32 unknown5;
363  uint32 unknown6;
364  uint32 unknown7;
365} REGFI_FILE;
366
367
368/* XXX: Should move all caching (SK records, HBINs, NKs, etc) to a single
369 *      structure, probably REGFI_FILE.  Once key caching is in place,
370 *      convert key_positions stack to store just key offsets rather than
371 *      whole keys.
372 */
373typedef struct 
374{
375  REGFI_FILE* f;
376  void_stack* key_positions;
377  lru_cache* sk_recs;
378  REGFI_NK_REC* cur_key;
379  uint32 cur_subkey;
380  uint32 cur_value;
381} REGFI_ITERATOR;
382
383
384typedef struct 
385{
386  /* XXX: Should probably eliminate the storage of keys here
387   *      once key caching is implemented.
388   */
389  REGFI_NK_REC* nk;
390  uint32 cur_subkey;
391  /* We could store a cur_value here as well, but didn't see
392   * the use in it right now.
393   */
394} REGFI_ITER_POSITION;
395
396
397/******************************************************************************/
398/*                         Main iterator API                                  */
399/******************************************************************************/
400REGFI_FILE*           regfi_open(const char* filename);
401int                   regfi_close(REGFI_FILE* r);
402
403/* regfi_get_messages: Get errors, warnings, and/or verbose information
404 *                     relating to processing of the given registry file.
405 *
406 * Arguments:
407 *   file     -- the structure for the registry file
408 *
409 * Returns:
410 *   A newly allocated char* which must be free()d by the caller.
411 */
412char*                 regfi_get_messages(REGFI_FILE* file);
413void                  regfi_set_message_mask(REGFI_FILE* file, uint16 mask);
414
415REGFI_ITERATOR*       regfi_iterator_new(REGFI_FILE* fh);
416void                  regfi_iterator_free(REGFI_ITERATOR* i);
417bool                  regfi_iterator_down(REGFI_ITERATOR* i);
418bool                  regfi_iterator_up(REGFI_ITERATOR* i);
419bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
420
421bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i, 
422                                                 const char* subkey_name);
423bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i, 
424                                               const char** path);
425const REGFI_NK_REC*   regfi_iterator_cur_key(REGFI_ITERATOR* i);
426const REGFI_SK_REC*   regfi_iterator_cur_sk(REGFI_ITERATOR* i);
427const REGFI_NK_REC*   regfi_iterator_first_subkey(REGFI_ITERATOR* i);
428const REGFI_NK_REC*   regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
429const REGFI_NK_REC*   regfi_iterator_next_subkey(REGFI_ITERATOR* i);
430
431bool                  regfi_iterator_find_value(REGFI_ITERATOR* i, 
432                                                const char* value_name);
433const REGFI_VK_REC*   regfi_iterator_first_value(REGFI_ITERATOR* i);
434const REGFI_VK_REC*   regfi_iterator_cur_value(REGFI_ITERATOR* i);
435const REGFI_VK_REC*   regfi_iterator_next_value(REGFI_ITERATOR* i);
436
437
438/********************************************************/
439/* Middle-layer structure caching, loading, and linking */
440/********************************************************/
441REGFI_HBIN*           regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset);
442REGFI_NK_REC*         regfi_load_key(REGFI_FILE* file, uint32 offset, 
443                                     bool strict);
444REGFI_SUBKEY_LIST*    regfi_load_subkeylist(REGFI_FILE* file, uint32 offset, 
445                                            uint32 num_keys, uint32 max_size, 
446                                            bool strict);
447REGFI_VK_REC*         regfi_load_value(REGFI_FILE* file, uint32 offset, 
448                                       bool strict);
449REGFI_VALUE_LIST*     regfi_load_valuelist(REGFI_FILE* file, uint32 offset, 
450                                           uint32 num_values, uint32 max_size, 
451                                           bool strict);
452
453/************************************/
454/*  Low-layer data structure access */
455/************************************/
456REGFI_FILE*           regfi_parse_regf(int fd, bool strict);
457REGFI_HBIN*           regfi_parse_hbin(REGFI_FILE* file, uint32 offset, 
458                                       bool strict);
459
460
461/* regfi_parse_nk: Parses an NK record.
462 *
463 * Arguments:
464 *   f        -- the registry file structure
465 *   offset   -- the offset of the cell (not the record) to be parsed.
466 *   max_size -- the maximum size the NK cell could be. (for validation)
467 *   strict   -- if true, rejects any malformed records.  Otherwise,
468 *               tries to minimally validate integrity.
469 * Returns:
470 *   A newly allocated NK record structure, or NULL on failure.
471 */
472REGFI_NK_REC*         regfi_parse_nk(REGFI_FILE* file, uint32 offset, 
473                                     uint32 max_size, bool strict);
474
475REGFI_SUBKEY_LIST*    regfi_parse_subkeylist(REGFI_FILE* file, uint32 offset,
476                                             uint32 max_size, bool strict);
477
478REGFI_VK_REC*         regfi_parse_vk(REGFI_FILE* file, uint32 offset, 
479                                     uint32 max_size, bool strict);
480
481uint8*                regfi_parse_data(REGFI_FILE* file, 
482                                       uint32 data_type, uint32 offset, 
483                                       uint32 length, uint32 max_size, 
484                                       bool data_in_offset, bool strict);
485
486REGFI_SK_REC*         regfi_parse_sk(REGFI_FILE* file, uint32 offset, 
487                                     uint32 max_size, bool strict);
488
489range_list*           regfi_parse_unalloc_cells(REGFI_FILE* file);
490
491bool                  regfi_parse_cell(int fd, uint32 offset, 
492                                       uint8* hdr, uint32 hdr_len,
493                                       uint32* cell_length, bool* unalloc);
494
495char*                 regfi_parse_classname(REGFI_FILE* file, uint32 offset,
496                                            uint16* name_length, 
497                                            uint32 max_size, bool strict);
498
499
500/************************************/
501/*    Private Functions             */
502/************************************/
503REGFI_NK_REC*         regfi_rootkey(REGFI_FILE* file);
504void                  regfi_key_free(REGFI_NK_REC* nk);
505void                  regfi_subkeylist_free(REGFI_SUBKEY_LIST* list);
506uint32                regfi_read(int fd, uint8* buf, uint32* length);
507
508const char*           regfi_type_val2str(unsigned int val);
509int                   regfi_type_str2val(const char* str);
510
511char*                 regfi_get_sacl(WINSEC_DESC* sec_desc);
512char*                 regfi_get_dacl(WINSEC_DESC* sec_desc);
513char*                 regfi_get_owner(WINSEC_DESC* sec_desc);
514char*                 regfi_get_group(WINSEC_DESC* sec_desc);
515
516REGFI_SUBKEY_LIST*    regfi_merge_subkeylists(uint16 num_lists, 
517                                              REGFI_SUBKEY_LIST** lists,
518                                              bool strict);
519REGFI_SUBKEY_LIST*    regfi_load_subkeylist_aux(REGFI_FILE* file, uint32 offset,
520                                                uint32 max_size, bool strict,
521                                                uint8 depth_left);
522void                  regfi_add_message(REGFI_FILE* file, uint16 msg_type, 
523                                        const char* fmt, ...);
524#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.