source: trunk/include/regfi.h @ 102

Last change on this file since 102 was 102, checked in by tim, 16 years ago

simplified root key search routines

rewrote sk record parsing

fixed nasty bug in parsing data-in-offset

  • Property svn:keywords set to Id
File size: 11.4 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 102 2008-04-03 02:30:26Z 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
52/******************************************************************************/
53/* Macros */
54 
55/* Registry data types */
56#define REG_NONE                       0
57#define REG_SZ                         1
58#define REG_EXPAND_SZ                  2
59#define REG_BINARY                     3
60#define REG_DWORD                      4
61#define REG_DWORD_LE                   4  /* DWORD, little endian */
62#define REG_DWORD_BE                   5  /* DWORD, big endian */
63#define REG_LINK                       6
64#define REG_MULTI_SZ                   7
65#define REG_RESOURCE_LIST              8
66#define REG_FULL_RESOURCE_DESCRIPTOR   9
67#define REG_RESOURCE_REQUIREMENTS_LIST 10
68#define REG_QWORD                      11 /* 64-bit little endian */
69/* XXX: Has MS defined a REG_QWORD_BE? */
70/* Not a real type in the registry */
71#define REG_KEY                        0x7FFFFFFF
72
73
74#define REGF_BLOCKSIZE          0x1000
75#define REGF_ALLOC_BLOCK        0x1000  /* Minimum allocation unit for hbins */
76#define REGF_MAX_DEPTH          512
77
78/* header sizes for various records */
79
80#define REGF_MAGIC_SIZE         4
81#define HBIN_MAGIC_SIZE         4
82#define HBIN_HEADER_REC_SIZE    0x20
83#define REC_HDR_SIZE            2
84
85#define REGF_OFFSET_NONE        0xffffffff
86#define REGFI_NK_MIN_LENGTH     0x4C
87#define REGFI_VK_MIN_LENGTH     0x14
88#define REGFI_SK_MIN_LENGTH     0x14
89
90/* Flags for the vk records */
91
92#define VK_FLAG_NAME_PRESENT    0x0001
93#define VK_DATA_IN_OFFSET       0x80000000
94#define VK_MAX_DATA_LENGTH      1024*1024
95
96/* NK record macros */
97
98#define NK_TYPE_LINKKEY         0x0010
99#define NK_TYPE_NORMALKEY       0x0020
100#define NK_TYPE_ROOTKEY         0x002c
101  /* TODO: Unknown type that shows up in Vista registries */
102#define NK_TYPE_UNKNOWN1         0x1020
103
104#define HBIN_STORE_REF(x, y) { x->hbin = y; y->ref_count++ };
105/* if the count == 0; we can clean up */
106#define HBIN_REMOVE_REF(x, y){ x->hbin = NULL; y->ref_count-- };
107
108
109/* HBIN block */
110struct regf_hbin;
111typedef struct regf_hbin
112{
113  struct regf_hbin* prev;
114  struct regf_hbin* next;
115  uint32 file_off;       /* my offset in the registry file */
116  uint32 ref_count;      /* how many active records are pointing to this
117                          * block (not used currently)
118                          */
119 
120  uint32 first_hbin_off; /* offset from first hbin block */
121  uint32 block_size;     /* block size of this block
122                          * Should be a multiple of 4096 (0x1000)
123                          */
124  uint32 next_block;     /* relative offset to next block. 
125                          * NOTE: This value may be unreliable!
126                          */
127
128  uint8 magic[HBIN_MAGIC_SIZE]; /* "hbin" */
129  prs_struct ps;         /* data */
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  uint8 keycheck[4];
138} REGF_HASH_REC;
139
140
141typedef struct 
142{
143  REGF_HBIN* hbin;       /* pointer to HBIN record (in memory) containing
144                          * this nk record
145                          */
146  REGF_HASH_REC* hashes;
147  uint32 hbin_off;       /* offset from beginning of this hbin block */
148  uint32 cell_size;      /* ((start_offset - end_offset) & 0xfffffff8) */
149 
150  uint8 header[REC_HDR_SIZE];
151  uint16 num_keys;
152} REGF_LF_REC;
153
154
155/* Key Value */
156typedef struct 
157{
158  uint32 offset;        /* Real offset of this record's cell in the file */
159  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
160
161  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
162                         * this nk record
163                         */
164  uint8* data;
165  uint16 name_length;
166  char*  valuename;
167  uint32 hbin_off;      /* offset from beginning of this hbin block */
168 
169  uint32 data_size;
170  uint32 data_off;      /* offset of data cell (virtual) */
171  uint32 type;
172  uint8  magic[REC_HDR_SIZE];
173  uint16 flag;
174  uint16 unknown1;
175} REGF_VK_REC;
176
177
178/* Key Security */
179struct _regf_sk_rec;
180
181typedef struct _regf_sk_rec
182{
183  struct _regf_sk_rec* next;
184  struct _regf_sk_rec* prev;
185  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
186                         * this nk record
187                         */
188  SEC_DESC* sec_desc;
189  uint32 hbin_off;      /* offset from beginning of this hbin block */
190  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
191  uint32 offset;        /* Real file offset of this record */
192 
193  uint32 sk_off;        /* offset parsed from NK record used as a key
194                         * to lookup reference to this SK record
195                         */
196 
197  uint32 prev_sk_off;
198  uint32 next_sk_off;
199  uint32 ref_count;
200  uint32 desc_size;     /* size of security descriptor */
201  uint16 unknown_tag;
202  uint8  magic[REC_HDR_SIZE];
203} REGF_SK_REC;
204
205
206/* Key Name */ 
207typedef struct 
208{
209  uint32 offset;        /* Real offset of this record's cell in the file */
210  uint32 cell_size;     /* Actual or estimated length of the cell. 
211                         * Always in multiples of 8.
212                         */
213
214  /* link in the other records here */
215  REGF_VK_REC** values;
216  REGF_SK_REC* sec_desc;
217  REGF_LF_REC subkeys;
218 
219  /* header information */
220  /* XXX: should we be looking for types other than the root key type? */
221  uint16 key_type;     
222  uint8  magic[REC_HDR_SIZE];
223  NTTIME mtime;
224  uint16 name_length;
225  uint16 classname_length;
226  char* classname;
227  char* keyname;
228  uint32 parent_off;    /* back pointer in registry hive */
229  uint32 classname_off; 
230 
231  /* max lengths */
232  uint32 max_bytes_subkeyname;      /* max subkey name * 2 */
233  uint32 max_bytes_subkeyclassname; /* max subkey classname length (as if) */
234  uint32 max_bytes_valuename;       /* max valuename * 2 */
235  uint32 max_bytes_value;           /* max value data size */
236 
237  /* unknowns */
238  uint32 unknown1;
239  uint32 unknown2;
240  uint32 unknown3;
241  uint32 unk_index;                 /* nigel says run time index ? */
242 
243  /* children */
244  uint32 num_subkeys;
245  uint32 subkeys_off;   /* hash records that point to NK records */     
246  uint32 num_values;
247  uint32 values_off;    /* value lists which point to VK records */
248  uint32 sk_off;        /* offset to SK record */ 
249} REGF_NK_REC;
250
251
252
253/* REGF block */
254typedef struct 
255{
256  /* run time information */
257  int fd;         /* file descriptor */
258  /* For sanity checking (not part of the registry header) */
259  uint32 file_length;
260  void* mem_ctx;  /* memory context for run-time file access information */
261  REGF_HBIN* block_list; /* list of open hbin blocks */
262
263  /* Experimental hbin lists */
264  range_list* hbins;
265  range_list* unalloc_cells;
266
267  /* file format information */
268  REGF_SK_REC* sec_desc_list;   /* list of security descriptors referenced
269                                 * by NK records
270                                 */
271 
272  uint8  magic[REGF_MAGIC_SIZE];/* "regf" */
273  NTTIME mtime;
274  uint32 data_offset;           /* offset to record in the first (or any?)
275                                 * hbin block
276                                 */
277  uint32 last_block;            /* offset to last hbin block in file */
278
279  uint32 checksum;              /* Stored checksum. */
280  uint32 computed_checksum;     /* Our own calculation of the checksum.
281                                 * (XOR of bytes 0x0000 - 0x01FB)
282                                 */
283 
284  /* unknown data structure values */
285  uint32 unknown1;
286  uint32 unknown2;
287  uint32 unknown3;
288  uint32 unknown4;
289  uint32 unknown5;
290  uint32 unknown6;
291  uint32 unknown7;
292} REGF_FILE;
293
294
295
296typedef struct 
297{
298  REGF_FILE* f;
299  void_stack* key_positions;
300  REGF_NK_REC* cur_key;
301  uint32 cur_subkey;
302  uint32 cur_value;
303} REGFI_ITERATOR;
304
305
306typedef struct 
307{
308  REGF_NK_REC* nk;
309  uint32 cur_subkey;
310  /* We could store a cur_value here as well, but didn't see
311   * the use in it right now.
312   */
313} REGFI_ITER_POSITION;
314
315
316/******************************************************************************/
317/* Function Declarations */
318/*  Main API */
319const char*           regfi_type_val2str(unsigned int val);
320int                   regfi_type_str2val(const char* str);
321
322char*                 regfi_get_sacl(SEC_DESC* sec_desc);
323char*                 regfi_get_dacl(SEC_DESC* sec_desc);
324char*                 regfi_get_owner(SEC_DESC* sec_desc);
325char*                 regfi_get_group(SEC_DESC* sec_desc);
326
327REGF_FILE*            regfi_open(const char* filename);
328int                   regfi_close(REGF_FILE* r);
329
330REGFI_ITERATOR*       regfi_iterator_new(REGF_FILE* fh);
331void                  regfi_iterator_free(REGFI_ITERATOR* i);
332bool                  regfi_iterator_down(REGFI_ITERATOR* i);
333bool                  regfi_iterator_up(REGFI_ITERATOR* i);
334bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
335
336bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i, 
337                                                 const char* subkey_name);
338bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i, 
339                                               const char** path);
340const REGF_NK_REC*    regfi_iterator_cur_key(REGFI_ITERATOR* i);
341const REGF_NK_REC*    regfi_iterator_first_subkey(REGFI_ITERATOR* i);
342const REGF_NK_REC*    regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
343const REGF_NK_REC*    regfi_iterator_next_subkey(REGFI_ITERATOR* i);
344
345bool                  regfi_iterator_find_value(REGFI_ITERATOR* i, 
346                                                const char* value_name);
347const REGF_VK_REC*    regfi_iterator_first_value(REGFI_ITERATOR* i);
348const REGF_VK_REC*    regfi_iterator_cur_value(REGFI_ITERATOR* i);
349const REGF_VK_REC*    regfi_iterator_next_value(REGFI_ITERATOR* i);
350
351/************************************/
352/*  Low-layer data structure access */
353/************************************/
354REGF_FILE*            regfi_parse_regf(int fd, bool strict);
355REGF_HBIN*            regfi_parse_hbin(REGF_FILE* file, uint32 offset, 
356                                       bool strict, bool save_unalloc);
357
358
359/* regfi_parse_nk: Parses an NK record.
360 *
361 * Arguments:
362 *   f        -- the registry file structure
363 *   offset   -- the offset of the cell (not the record) to be parsed.
364 *   max_size -- the maximum size the NK cell could be. (for validation)
365 *   strict   -- if true, rejects any malformed records.  Otherwise,
366 *               tries to minimally validate integrity.
367 * Returns:
368 *   A newly allocated NK record structure, or NULL on failure.
369 */
370REGF_NK_REC*          regfi_parse_nk(REGF_FILE* file, uint32 offset, 
371                                     uint32 max_size, bool strict);
372
373
374/* Private Functions */
375REGF_NK_REC*          regfi_rootkey(REGF_FILE* file);
376void                  regfi_key_free(REGF_NK_REC* nk);
377uint32                regfi_read(int fd, uint8* buf, uint32* length);
378
379
380
381/****************/
382/* Experimental */
383/****************/
384
385REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset, 
386                            uint32 max_size, bool strict);
387uint8* regfi_parse_data(REGF_FILE* file, uint32 offset, 
388                        uint32 length, bool strict);
389
390
391#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.