source: trunk/include/regfi.h @ 138

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

extended error message logging to allow for message type filtering

fine tuned message verbosity to more reasonable default levels for reglookup and reglookup-recover

updated related documentation

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