source: trunk/include/regfi.h @ 137

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

Added error messages to most parse functions in regfi

Relaxed validation requirements on NK types and missing value data

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