source: trunk/include/regfi.h @ 131

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

fixed an hbin length validation related to vk records
added hbin length validation for class names and data cells

  • Property svn:keywords set to Id
File size: 12.7 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 131 2009-01-11 20:14:20Z 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#include "lru_cache.h"
52
53/******************************************************************************/
54/* Macros */
55 
56/* Registry data types */
57#define REG_NONE                       0
58#define REG_SZ                         1
59#define REG_EXPAND_SZ                  2
60#define REG_BINARY                     3
61#define REG_DWORD                      4
62#define REG_DWORD_LE                   4  /* DWORD, little endian */
63#define REG_DWORD_BE                   5  /* DWORD, big endian */
64#define REG_LINK                       6
65#define REG_MULTI_SZ                   7
66#define REG_RESOURCE_LIST              8
67#define REG_FULL_RESOURCE_DESCRIPTOR   9
68#define REG_RESOURCE_REQUIREMENTS_LIST 10
69#define REG_QWORD                      11 /* 64-bit little endian */
70/* XXX: Has MS defined a REG_QWORD_BE? */
71/* Not a real type in the registry */
72#define REG_KEY                        0x7FFFFFFF
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#define REGF_MAGIC_SIZE            4
80#define HBIN_MAGIC_SIZE            4
81#define HBIN_HEADER_REC_SIZE       0x20
82#define REC_HDR_SIZE               2
83
84#define REGF_OFFSET_NONE           0xffffffff
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/* Constants used for validation */
91/* XXX: Can we add clock resolution validation as well as range?  It has
92 *      been reported that Windows timestamps are never more than a
93 *      certain granularity (250ms?), which could be used to help
94 *      eliminate false positives.  Would need to validate this and
95 *      perhaps conservatively implement a check.
96 */
97 /* Minimum time is Jan 1, 1990 00:00:00 */
98#define REGFI_MTIME_MIN_HIGH       0x01B41E6D
99#define REGFI_MTIME_MIN_LOW        0x26F98000
100 /* Maximum time is Jan 1, 2290 00:00:00
101  * (We hope no one is using Windows by then...)
102  */
103#define REGFI_MTIME_MAX_HIGH       0x03047543
104#define REGFI_MTIME_MAX_LOW        0xC80A4000
105
106
107/* Flags for the vk records */
108#define VK_FLAG_NAME_PRESENT       0x0001
109#define VK_DATA_IN_OFFSET          0x80000000
110#define VK_MAX_DATA_LENGTH         1024*1024
111
112/* NK record types */
113#define NK_TYPE_LINKKEY            0x0010
114#define NK_TYPE_NORMALKEY          0x0020
115#define NK_TYPE_ROOTKEY1           0x002c
116#define NK_TYPE_ROOTKEY2           0x00ac
117 /* XXX: Unknown type that shows up in Vista registries */
118#define NK_TYPE_UNKNOWN1           0x1020
119
120
121/* HBIN block */
122typedef struct regf_hbin
123{
124  uint32 file_off;       /* my offset in the registry file */
125  uint32 ref_count;      /* how many active records are pointing to this
126                          * block (not used currently)
127                          */
128 
129  uint32 first_hbin_off; /* offset from first hbin block */
130  uint32 block_size;     /* block size of this block
131                          * Should be a multiple of 4096 (0x1000)
132                          */
133  uint32 next_block;     /* relative offset to next block. 
134                          * NOTE: This value may be unreliable!
135                          */
136
137  uint8 magic[HBIN_MAGIC_SIZE]; /* "hbin" */
138} REGF_HBIN;
139
140
141/* Subkey List -- list of key offsets and hashed names for consistency */
142typedef struct 
143{
144  uint32 nk_off;
145  uint32 hash;
146} REGF_SUBKEY_LIST_ELEM;
147
148
149typedef struct 
150{
151  uint32 offset;        /* Real offset of this record's cell in the file */
152  uint32 cell_size;      /* ((start_offset - end_offset) & 0xfffffff8) */
153  uint32 num_keys;
154  REGF_SUBKEY_LIST_ELEM* elements;
155 
156  uint8 magic[REC_HDR_SIZE];
157} REGF_SUBKEY_LIST;
158
159
160/* Key Value */
161typedef struct 
162{
163  uint32 offset;        /* Real offset of this record's cell in the file */
164  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
165
166  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
167                         * this nk record
168                         */
169  uint8* data;
170  uint16 name_length;
171  char*  valuename;
172  uint32 hbin_off;      /* offset from beginning of this hbin block */
173 
174  uint32 data_size;
175  uint32 data_off;      /* offset of data cell (virtual) */
176  uint32 type;
177  uint8  magic[REC_HDR_SIZE];
178  uint16 flag;
179  uint16 unknown1;
180  bool data_in_offset;
181} REGF_VK_REC;
182
183
184/* Key Security */
185struct _regf_sk_rec;
186
187typedef struct _regf_sk_rec
188{
189  uint32 offset;        /* Real file offset of this record */
190  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
191
192  SEC_DESC* sec_desc;
193  uint32 hbin_off;      /* offset from beginning of this hbin block */
194 
195  uint32 sk_off;        /* offset parsed from NK record used as a key
196                         * to lookup reference to this SK record
197                         */
198 
199  uint32 prev_sk_off;
200  uint32 next_sk_off;
201  uint32 ref_count;
202  uint32 desc_size;     /* size of security descriptor */
203  uint16 unknown_tag;
204  uint8  magic[REC_HDR_SIZE];
205} REGF_SK_REC;
206
207
208/* Key Name */
209typedef struct
210{
211  uint32 offset;        /* Real offset of this record's cell in the file */
212  uint32 cell_size;     /* Actual or estimated length of the cell. 
213                         * Always in multiples of 8.
214                         */
215
216  /* link in the other records here */
217  REGF_VK_REC** values;
218  REGF_SUBKEY_LIST* subkeys;
219 
220  /* header information */
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;                /* pointer to parent key */
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;   /* offset of subkey list that points 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
262  /* Experimental hbin lists */
263  range_list* hbins;
264
265  /* file format information */ 
266  uint8  magic[REGF_MAGIC_SIZE];/* "regf" */
267  NTTIME mtime;
268  uint32 data_offset;           /* offset to record in the first (or any?)
269                                 * hbin block
270                                 */
271  uint32 last_block;            /* offset to last hbin block in file */
272
273  uint32 checksum;              /* Stored checksum. */
274  uint32 computed_checksum;     /* Our own calculation of the checksum.
275                                 * (XOR of bytes 0x0000 - 0x01FB)
276                                 */
277 
278  /* unknown data structure values */
279  uint32 unknown1;
280  uint32 unknown2;
281  uint32 unknown3;
282  uint32 unknown4;
283  uint32 unknown5;
284  uint32 unknown6;
285  uint32 unknown7;
286} REGF_FILE;
287
288
289
290typedef struct 
291{
292  REGF_FILE* f;
293  void_stack* key_positions;
294  lru_cache* sk_recs;
295  REGF_NK_REC* cur_key;
296  uint32 cur_subkey;
297  uint32 cur_value;
298} REGFI_ITERATOR;
299
300
301typedef struct 
302{
303  REGF_NK_REC* nk;
304  uint32 cur_subkey;
305  /* We could store a cur_value here as well, but didn't see
306   * the use in it right now.
307   */
308} REGFI_ITER_POSITION;
309
310
311/******************************************************************************/
312/* Function Declarations */
313/*  Main API */
314const char*           regfi_type_val2str(unsigned int val);
315int                   regfi_type_str2val(const char* str);
316
317char*                 regfi_get_sacl(SEC_DESC* sec_desc);
318char*                 regfi_get_dacl(SEC_DESC* sec_desc);
319char*                 regfi_get_owner(SEC_DESC* sec_desc);
320char*                 regfi_get_group(SEC_DESC* sec_desc);
321
322REGF_FILE*            regfi_open(const char* filename);
323int                   regfi_close(REGF_FILE* r);
324
325REGFI_ITERATOR*       regfi_iterator_new(REGF_FILE* fh);
326void                  regfi_iterator_free(REGFI_ITERATOR* i);
327bool                  regfi_iterator_down(REGFI_ITERATOR* i);
328bool                  regfi_iterator_up(REGFI_ITERATOR* i);
329bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
330
331bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i, 
332                                                 const char* subkey_name);
333bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i, 
334                                               const char** path);
335const REGF_NK_REC*    regfi_iterator_cur_key(REGFI_ITERATOR* i);
336const REGF_SK_REC*    regfi_iterator_cur_sk(REGFI_ITERATOR* i);
337const REGF_NK_REC*    regfi_iterator_first_subkey(REGFI_ITERATOR* i);
338const REGF_NK_REC*    regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
339const REGF_NK_REC*    regfi_iterator_next_subkey(REGFI_ITERATOR* i);
340
341bool                  regfi_iterator_find_value(REGFI_ITERATOR* i, 
342                                                const char* value_name);
343const REGF_VK_REC*    regfi_iterator_first_value(REGFI_ITERATOR* i);
344const REGF_VK_REC*    regfi_iterator_cur_value(REGFI_ITERATOR* i);
345const REGF_VK_REC*    regfi_iterator_next_value(REGFI_ITERATOR* i);
346
347
348/********************************************************/
349/* Middle-layer structure caching, loading, and linking */
350/********************************************************/
351REGF_HBIN* regfi_lookup_hbin(REGF_FILE* file, uint32 offset);
352
353REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict);
354
355REGF_SUBKEY_LIST* regfi_load_subkeylist(REGF_FILE* file, uint32 offset, 
356                                        uint32 num_keys, uint32 max_size, 
357                                        bool strict);
358
359REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset, 
360                                   uint32 num_values, uint32 max_size, 
361                                   bool strict);
362
363REGF_SUBKEY_LIST* regfi_merge_subkeylists(uint16 num_lists, 
364                                          REGF_SUBKEY_LIST** lists,
365                                          bool strict);
366
367/************************************/
368/*  Low-layer data structure access */
369/************************************/
370REGF_FILE*            regfi_parse_regf(int fd, bool strict);
371REGF_HBIN*            regfi_parse_hbin(REGF_FILE* file, uint32 offset, 
372                                       bool strict);
373
374
375/* regfi_parse_nk: Parses an NK record.
376 *
377 * Arguments:
378 *   f        -- the registry file structure
379 *   offset   -- the offset of the cell (not the record) to be parsed.
380 *   max_size -- the maximum size the NK cell could be. (for validation)
381 *   strict   -- if true, rejects any malformed records.  Otherwise,
382 *               tries to minimally validate integrity.
383 * Returns:
384 *   A newly allocated NK record structure, or NULL on failure.
385 */
386REGF_NK_REC*          regfi_parse_nk(REGF_FILE* file, uint32 offset, 
387                                     uint32 max_size, bool strict);
388
389REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset, 
390                            uint32 max_size, bool strict);
391
392uint8* regfi_parse_data(REGF_FILE* file, uint32 offset, 
393                        uint32 length, uint32 max_size, bool strict);
394
395REGF_SK_REC* regfi_parse_sk(REGF_FILE* file, uint32 offset, uint32 max_size, bool strict);
396
397range_list* regfi_parse_unalloc_cells(REGF_FILE* file);
398
399bool regfi_parse_cell(int fd, uint32 offset, uint8* hdr, uint32 hdr_len,
400                      uint32* cell_length, bool* unalloc);
401
402char* regfi_parse_classname(REGF_FILE* file, uint32 offset,
403                            uint16* name_length, uint32 max_size, bool strict);
404
405
406/* Private Functions */
407REGF_NK_REC*          regfi_rootkey(REGF_FILE* file);
408void                  regfi_key_free(REGF_NK_REC* nk);
409void                  regfi_subkeylist_free(REGF_SUBKEY_LIST* list);
410uint32                regfi_read(int fd, uint8* buf, uint32* length);
411
412
413#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.