source: trunk/include/regfi.h @ 136

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

fixed various integer issues and memory allocation issues

polished error message functions and added initial messages in a few places

  • Property svn:keywords set to Id
File size: 14.0 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 136 2009-01-23 17:29:51Z 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/* NK record types */
114#define REGFI_NK_TYPE_LINKKEY      0x0010
115#define REGFI_NK_TYPE_NORMALKEY    0x0020
116 /* XXX: Unknown key type that shows up in Vista registries */
117#define REGFI_NK_TYPE_UNKNOWN1     0x1020
118#define REGFI_NK_TYPE_ROOTKEY1     0x002c
119 /* XXX: Unknown root key type that shows up in Vista registries */
120#define REGFI_NK_TYPE_ROOTKEY2     0x00ac
121
122
123/* HBIN block */
124typedef struct _regfi_hbin
125{
126  uint32 file_off;       /* my offset in the registry file */
127  uint32 ref_count;      /* how many active records are pointing to this
128                          * block (not used currently)
129                          */
130 
131  uint32 first_hbin_off; /* offset from first hbin block */
132  uint32 block_size;     /* block size of this block
133                          * Should be a multiple of 4096 (0x1000)
134                          */
135  uint32 next_block;     /* relative offset to next block. 
136                          * NOTE: This value may be unreliable!
137                          */
138
139  uint8 magic[REGFI_HBIN_MAGIC_SIZE]; /* "hbin" */
140} REGFI_HBIN;
141
142
143/* Subkey List -- list of key offsets and hashed names for consistency */
144typedef struct 
145{
146  uint32 nk_off;
147  uint32 hash;
148} REGFI_SUBKEY_LIST_ELEM;
149
150
151typedef struct 
152{
153  uint32 offset;        /* Real offset of this record's cell in the file */
154  uint32 cell_size;      /* ((start_offset - end_offset) & 0xfffffff8) */
155  uint32 num_keys;
156  REGFI_SUBKEY_LIST_ELEM* elements;
157 
158  uint8 magic[REGFI_CELL_MAGIC_SIZE];
159} REGFI_SUBKEY_LIST;
160
161
162/* Key Value */
163typedef struct 
164{
165  uint32 offset;        /* Real offset of this record's cell in the file */
166  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
167
168  REGFI_HBIN* hbin;     /* pointer to HBIN record (in memory) containing
169                         * this nk record
170                         */
171  uint8* data;
172  uint16 name_length;
173  char*  valuename;
174  uint32 hbin_off;      /* offset from beginning of this hbin block */
175 
176  uint32 data_size;
177  uint32 data_off;      /* offset of data cell (virtual) */
178  uint32 type;
179  uint8  magic[REGFI_CELL_MAGIC_SIZE];
180  uint16 flag;
181  uint16 unknown1;
182  bool data_in_offset;
183} REGFI_VK_REC;
184
185
186/* Key Security */
187struct _regfi_sk_rec;
188
189typedef struct _regfi_sk_rec
190{
191  uint32 offset;        /* Real file offset of this record */
192  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
193
194  WINSEC_DESC* sec_desc;
195  uint32 hbin_off;      /* offset from beginning of this hbin block */
196 
197  uint32 sk_off;        /* offset parsed from NK record used as a key
198                         * to lookup reference to this SK record
199                         */
200 
201  uint32 prev_sk_off;
202  uint32 next_sk_off;
203  uint32 ref_count;
204  uint32 desc_size;     /* size of security descriptor */
205  uint16 unknown_tag;
206  uint8  magic[REGFI_CELL_MAGIC_SIZE];
207} REGFI_SK_REC;
208
209
210/* Key Name */
211typedef struct
212{
213  uint32 offset;        /* Real offset of this record's cell in the file */
214  uint32 cell_size;     /* Actual or estimated length of the cell. 
215                         * Always in multiples of 8.
216                         */
217
218  /* link in the other records here */
219  REGFI_VK_REC** values;
220  REGFI_SUBKEY_LIST* subkeys;
221 
222  /* header information */
223  uint16 key_type;
224  uint8  magic[REGFI_CELL_MAGIC_SIZE];
225  NTTIME mtime;
226  uint16 name_length;
227  uint16 classname_length;
228  char* classname;
229  char* keyname;
230  uint32 parent_off;                /* pointer to parent key */
231  uint32 classname_off;
232 
233  /* max lengths */
234  uint32 max_bytes_subkeyname;      /* max subkey name * 2 */
235  uint32 max_bytes_subkeyclassname; /* max subkey classname length (as if) */
236  uint32 max_bytes_valuename;       /* max valuename * 2 */
237  uint32 max_bytes_value;           /* max value data size */
238 
239  /* unknowns */
240  uint32 unknown1;
241  uint32 unknown2;
242  uint32 unknown3;
243  uint32 unk_index;                 /* nigel says run time index ? */
244 
245  /* children */
246  uint32 num_subkeys;
247  uint32 subkeys_off;   /* offset of subkey list that points to NK records */
248  uint32 num_values;
249  uint32 values_off;    /* value lists which point to VK records */
250  uint32 sk_off;        /* offset to SK record */
251} REGFI_NK_REC;
252
253
254
255/* REGF block */
256typedef struct 
257{
258  /* Run-time information */
259  /************************/
260  int fd;         /* file descriptor */
261
262  /* Experimental hbin lists */
263  range_list* hbins;
264
265  /* Error/warning/info messages returned by lower layer functions */
266  char* last_message;
267
268  /* For sanity checking (not part of the registry header) */
269  uint32 file_length;
270
271
272  /* Data parsed from file header */
273  /********************************/
274  uint8  magic[REGFI_REGF_MAGIC_SIZE];/* "regf" */
275  NTTIME mtime;
276  uint32 data_offset;           /* offset to record in the first (or any?)
277                                 * hbin block
278                                 */
279  uint32 last_block;            /* offset to last hbin block in file */
280
281  uint32 checksum;              /* Stored checksum. */
282  uint32 computed_checksum;     /* Our own calculation of the checksum.
283                                 * (XOR of bytes 0x0000 - 0x01FB)
284                                 */
285 
286  /* unknown data structure values */
287  uint32 unknown1;
288  uint32 unknown2;
289  uint32 unknown3;
290  uint32 unknown4;
291  uint32 unknown5;
292  uint32 unknown6;
293  uint32 unknown7;
294} REGFI_FILE;
295
296
297
298typedef struct 
299{
300  REGFI_FILE* f;
301  void_stack* key_positions;
302  lru_cache* sk_recs;
303  REGFI_NK_REC* cur_key;
304  uint32 cur_subkey;
305  uint32 cur_value;
306} REGFI_ITERATOR;
307
308
309typedef struct 
310{
311  /* XXX: Should probably eliminate the storage of keys here
312   *      once key caching is implemented.
313   */
314  REGFI_NK_REC* nk;
315  uint32 cur_subkey;
316  /* We could store a cur_value here as well, but didn't see
317   * the use in it right now.
318   */
319} REGFI_ITER_POSITION;
320
321
322/******************************************************************************/
323/*                         Main iterator API                                  */
324/******************************************************************************/
325REGFI_FILE*           regfi_open(const char* filename);
326int                   regfi_close(REGFI_FILE* r);
327
328/* regfi_get_messages: Get errors, warnings, and/or verbose information
329 *                     relating to processing of the given registry file.
330 *
331 * Arguments:
332 *   file     -- the structure for the registry file
333 *
334 * Returns:
335 *   A newly allocated char* which must be free()d by the caller.
336 */
337char*                 regfi_get_messages(REGFI_FILE* file);
338
339REGFI_ITERATOR*       regfi_iterator_new(REGFI_FILE* fh);
340void                  regfi_iterator_free(REGFI_ITERATOR* i);
341bool                  regfi_iterator_down(REGFI_ITERATOR* i);
342bool                  regfi_iterator_up(REGFI_ITERATOR* i);
343bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
344
345bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i, 
346                                                 const char* subkey_name);
347bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i, 
348                                               const char** path);
349const REGFI_NK_REC*   regfi_iterator_cur_key(REGFI_ITERATOR* i);
350const REGFI_SK_REC*   regfi_iterator_cur_sk(REGFI_ITERATOR* i);
351const REGFI_NK_REC*   regfi_iterator_first_subkey(REGFI_ITERATOR* i);
352const REGFI_NK_REC*   regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
353const REGFI_NK_REC*   regfi_iterator_next_subkey(REGFI_ITERATOR* i);
354
355bool                  regfi_iterator_find_value(REGFI_ITERATOR* i, 
356                                                const char* value_name);
357const REGFI_VK_REC*   regfi_iterator_first_value(REGFI_ITERATOR* i);
358const REGFI_VK_REC*   regfi_iterator_cur_value(REGFI_ITERATOR* i);
359const REGFI_VK_REC*   regfi_iterator_next_value(REGFI_ITERATOR* i);
360
361
362/********************************************************/
363/* Middle-layer structure caching, loading, and linking */
364/********************************************************/
365REGFI_HBIN*           regfi_lookup_hbin(REGFI_FILE* file, uint32 offset);
366REGFI_NK_REC*         regfi_load_key(REGFI_FILE* file, uint32 offset, 
367                                     bool strict);
368REGFI_SUBKEY_LIST*    regfi_load_subkeylist(REGFI_FILE* file, uint32 offset, 
369                                            uint32 num_keys, uint32 max_size, 
370                                            bool strict);
371REGFI_VK_REC**        regfi_load_valuelist(REGFI_FILE* file, uint32 offset, 
372                                           uint32 num_values, uint32 max_size, 
373                                           bool strict);
374
375/************************************/
376/*  Low-layer data structure access */
377/************************************/
378REGFI_FILE*           regfi_parse_regf(int fd, bool strict);
379REGFI_HBIN*           regfi_parse_hbin(REGFI_FILE* file, uint32 offset, 
380                                       bool strict);
381
382
383/* regfi_parse_nk: Parses an NK record.
384 *
385 * Arguments:
386 *   f        -- the registry file structure
387 *   offset   -- the offset of the cell (not the record) to be parsed.
388 *   max_size -- the maximum size the NK cell could be. (for validation)
389 *   strict   -- if true, rejects any malformed records.  Otherwise,
390 *               tries to minimally validate integrity.
391 * Returns:
392 *   A newly allocated NK record structure, or NULL on failure.
393 */
394REGFI_NK_REC*         regfi_parse_nk(REGFI_FILE* file, uint32 offset, 
395                                     uint32 max_size, bool strict);
396
397REGFI_VK_REC*         regfi_parse_vk(REGFI_FILE* file, uint32 offset, 
398                                     uint32 max_size, bool strict);
399
400uint8*                regfi_parse_data(REGFI_FILE* file, uint32 offset, 
401                                       uint32 length, uint32 max_size, 
402                                       bool strict);
403
404REGFI_SK_REC*         regfi_parse_sk(REGFI_FILE* file, uint32 offset, 
405                                     uint32 max_size, bool strict);
406
407range_list*           regfi_parse_unalloc_cells(REGFI_FILE* file);
408
409bool                  regfi_parse_cell(int fd, uint32 offset, 
410                                       uint8* hdr, uint32 hdr_len,
411                                       uint32* cell_length, bool* unalloc);
412
413char*                 regfi_parse_classname(REGFI_FILE* file, uint32 offset,
414                                            uint16* name_length, 
415                                            uint32 max_size, bool strict);
416
417
418/************************************/
419/*    Private Functions             */
420/************************************/
421REGFI_NK_REC*         regfi_rootkey(REGFI_FILE* file);
422void                  regfi_key_free(REGFI_NK_REC* nk);
423void                  regfi_subkeylist_free(REGFI_SUBKEY_LIST* list);
424uint32                regfi_read(int fd, uint8* buf, uint32* length);
425
426const char*           regfi_type_val2str(unsigned int val);
427int                   regfi_type_str2val(const char* str);
428
429char*                 regfi_get_sacl(WINSEC_DESC* sec_desc);
430char*                 regfi_get_dacl(WINSEC_DESC* sec_desc);
431char*                 regfi_get_owner(WINSEC_DESC* sec_desc);
432char*                 regfi_get_group(WINSEC_DESC* sec_desc);
433
434REGFI_SUBKEY_LIST*    regfi_merge_subkeylists(uint16 num_lists, 
435                                              REGFI_SUBKEY_LIST** lists,
436                                              bool strict);
437void                  regfi_add_message(REGFI_FILE* file, const char* fmt, ...);
438#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.