source: releases/0.11.0/include/regfi.h@ 209

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

preliminary support for big data records

switched to using key flags rather than incorrect key types

  • Property svn:keywords set to Id
File size: 19.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 152 2009-06-02 20:00:38Z 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 "talloc.h"
49#include "smb_deps.h"
50#include "winsec.h"
51#include "void_stack.h"
52#include "range_list.h"
53#include "lru_cache.h"
54
55/******************************************************************************/
56
57/* regfi library error message types */
58#define REGFI_MSG_INFO 0x0001
59#define REGFI_MSG_WARN 0x0004
60#define REGFI_MSG_ERROR 0x0010
61
62/* Windows is lame */
63#ifdef O_BINARY
64#define REGFI_OPEN_FLAGS O_RDONLY|O_BINARY
65#else
66#define REGFI_OPEN_FLAGS O_RDONLY
67#endif
68
69/* Registry data types */
70#define REG_NONE 0
71#define REG_SZ 1
72#define REG_EXPAND_SZ 2
73#define REG_BINARY 3
74#define REG_DWORD 4
75#define REG_DWORD_LE 4 /* DWORD, little endian */
76#define REG_DWORD_BE 5 /* DWORD, big endian */
77#define REG_LINK 6
78#define REG_MULTI_SZ 7
79#define REG_RESOURCE_LIST 8
80#define REG_FULL_RESOURCE_DESCRIPTOR 9
81#define REG_RESOURCE_REQUIREMENTS_LIST 10
82#define REG_QWORD 11 /* 64-bit little endian */
83/* XXX: Has MS defined a REG_QWORD_BE? */
84/* Not a real type in the registry */
85#define REG_KEY 0x7FFFFFFF
86
87#define REGFI_MAX_DEPTH 512
88#define REGFI_OFFSET_NONE 0xffffffff
89
90/* XXX: This is totally arbitrary right now. */
91#define REGFI_MAX_SUBKEY_DEPTH 255
92
93/* Header sizes and magic number lengths for various records */
94#define REGFI_HBIN_ALLOC 0x1000 /* Minimum allocation unit for HBINs */
95#define REGFI_REGF_SIZE 0x1000 /* "regf" header block size */
96#define REGFI_REGF_MAGIC_SIZE 4
97#define REGFI_REGF_NAME_SIZE 64
98#define REGFI_REGF_RESERVED1_SIZE 340
99#define REGFI_REGF_RESERVED2_SIZE 3528
100#define REGFI_HBIN_MAGIC_SIZE 4
101#define REGFI_CELL_MAGIC_SIZE 2
102#define REGFI_HBIN_HEADER_SIZE 0x20
103#define REGFI_NK_MIN_LENGTH 0x4C
104#define REGFI_VK_MIN_LENGTH 0x14
105#define REGFI_SK_MIN_LENGTH 0x14
106#define REGFI_SUBKEY_LIST_MIN_LEN 0x4
107
108
109/* Constants used for validation */
110/* XXX: Can we add clock resolution validation as well as range? It has
111 * been reported that Windows timestamps are never more than a
112 * certain granularity (250ms?), which could be used to help
113 * eliminate false positives. Would need to verify this and
114 * perhaps conservatively implement a check.
115 */
116 /* Minimum time is Jan 1, 1990 00:00:00 */
117#define REGFI_MTIME_MIN_HIGH 0x01B41E6D
118#define REGFI_MTIME_MIN_LOW 0x26F98000
119 /* Maximum time is Jan 1, 2290 00:00:00
120 * (We hope no one is using Windows by then...)
121 */
122#define REGFI_MTIME_MAX_HIGH 0x03047543
123#define REGFI_MTIME_MAX_LOW 0xC80A4000
124
125
126/* Flags for the vk records */
127/* XXX: This next flag may be incorrect. According to Jeffrey Muir,
128* this may actually indicate that the value name is stored in
129* UTF-16LE.
130*/
131#define REGFI_VK_FLAG_NAME_PRESENT 0x0001
132#define REGFI_VK_DATA_IN_OFFSET 0x80000000
133#define REGFI_VK_MAX_DATA_LENGTH 1024*1024 /* XXX: This is arbitrary */
134
135
136/* Known key flags */
137/*******************/
138/* These next two show up on normal-seeming keys in Vista and W2K3 registries */
139#define REGFI_NK_FLAG_UNKNOWN1 0x4000
140#define REGFI_NK_FLAG_UNKNOWN2 0x1000
141
142/* This next one shows up on root keys in some Vista "software" registries */
143#define REGFI_NK_FLAG_UNKNOWN3 0x0080
144
145/* Predefined handle. Rumor has it that the valuelist count for this key is
146 * where the handle is stored.
147 * http://msdn.microsoft.com/en-us/library/ms724836(VS.85).aspx
148 */
149#define REGFI_NK_FLAG_PREDEF_KEY 0x0040
150
151/* The name will be in ASCII if this next bit is set, otherwise UTF-16LE */
152#define REGFI_NK_FLAG_ASCIINAME 0x0020
153
154/* Symlink key.
155 * See: http://www.codeproject.com/KB/system/regsymlink.aspx
156 */
157#define REGFI_NK_FLAG_LINK 0x0010
158
159/* This key cannot be deleted */
160#define REGFI_NK_FLAG_NO_RM 0x0008
161
162/* Root of a hive */
163#define REGFI_NK_FLAG_ROOT 0x0004
164
165/* Mount point of another hive. NULL/(default) value indicates which hive
166 * and where in the hive it points to.
167 */
168#define REGFI_NK_FLAG_HIVE_LINK 0x0002
169
170/* These keys shouldn't be stored on disk, according to:
171 * http://geekswithblogs.net/sdorman/archive/2007/12/24/volatile-registry-keys.aspx
172 */
173#define REGFI_NK_FLAG_VOLATILE 0x0001
174
175/* Useful for identifying unknown flag types */
176#define REGFI_NK_KNOWN_FLAGS (REGFI_NK_FLAG_PREDEF_KEY\
177 | REGFI_NK_FLAG_ASCIINAME\
178 | REGFI_NK_FLAG_LINK\
179 | REGFI_NK_FLAG_NO_RM\
180 | REGFI_NK_FLAG_ROOT\
181 | REGFI_NK_FLAG_HIVE_LINK\
182 | REGFI_NK_FLAG_VOLATILE\
183 | REGFI_NK_FLAG_UNKNOWN1\
184 | REGFI_NK_FLAG_UNKNOWN2)
185
186/* HBIN block */
187typedef struct _regfi_hbin
188{
189 uint32 file_off; /* my offset in the registry file */
190 uint32 ref_count; /* how many active records are pointing to this
191 * block (not used currently)
192 */
193
194 uint32 first_hbin_off; /* offset from first hbin block */
195 uint32 block_size; /* block size of this block
196 * Should be a multiple of 4096 (0x1000)
197 */
198 uint32 next_block; /* relative offset to next block.
199 * NOTE: This value may be unreliable!
200 */
201
202 uint8 magic[REGFI_HBIN_MAGIC_SIZE]; /* "hbin" */
203} REGFI_HBIN;
204
205
206/* Subkey List -- list of key offsets and hashed names for consistency */
207typedef struct
208{
209 /* Virtual offset of NK record or additional subkey list,
210 * depending on this list's type.
211 */
212 uint32 offset;
213
214 uint32 hash;
215} REGFI_SUBKEY_LIST_ELEM;
216
217
218typedef struct _regfi_subkey_list
219{
220 /* Real offset of this record's cell in the file */
221 uint32 offset;
222
223 uint32 cell_size;
224
225 /* Number of immediate children */
226 uint32 num_children;
227
228 /* Total number of keys referenced by this list and it's children */
229 uint32 num_keys;
230
231 REGFI_SUBKEY_LIST_ELEM* elements;
232 uint8 magic[REGFI_CELL_MAGIC_SIZE];
233
234 /* Set if the magic indicates this subkey list points to child subkey lists */
235 bool recursive_type;
236} REGFI_SUBKEY_LIST;
237
238
239typedef uint32 REGFI_VALUE_LIST_ELEM;
240typedef struct _regfi_value_list
241{
242 /* Actual number of values referenced by this list.
243 * May differ from parent key's num_values if there were parsing errors.
244 */
245 uint32 num_values;
246
247 REGFI_VALUE_LIST_ELEM* elements;
248} REGFI_VALUE_LIST;
249
250
251/* Value record */
252typedef struct
253{
254 uint32 offset; /* Real offset of this record's cell in the file */
255 uint32 cell_size; /* ((start_offset - end_offset) & 0xfffffff8) */
256
257 uint8* data;
258 char* valuename;
259 uint16 name_length;
260 uint32 hbin_off; /* offset from beginning of this hbin block */
261
262 uint32 data_size;
263 uint32 data_off; /* offset of data cell (virtual) */
264 uint32 type;
265 uint8 magic[REGFI_CELL_MAGIC_SIZE];
266 uint16 flag;
267 uint16 unknown1;
268 bool data_in_offset;
269} REGFI_VK_REC;
270
271
272/* Key Security */
273struct _regfi_sk_rec;
274
275typedef struct _regfi_sk_rec
276{
277 uint32 offset; /* Real file offset of this record */
278 uint32 cell_size; /* ((start_offset - end_offset) & 0xfffffff8) */
279
280 WINSEC_DESC* sec_desc;
281 uint32 hbin_off; /* offset from beginning of this hbin block */
282
283 uint32 prev_sk_off;
284 uint32 next_sk_off;
285 uint32 ref_count;
286 uint32 desc_size; /* size of security descriptor */
287 uint16 unknown_tag;
288 uint8 magic[REGFI_CELL_MAGIC_SIZE];
289} REGFI_SK_REC;
290
291
292/* Key Name */
293typedef struct
294{
295 uint32 offset; /* Real offset of this record's cell in the file */
296 uint32 cell_size; /* Actual or estimated length of the cell.
297 * Always in multiples of 8.
298 */
299
300 /* link in the other records here */
301 REGFI_VALUE_LIST* values;
302 REGFI_SUBKEY_LIST* subkeys;
303
304 /* header information */
305 uint16 key_type;
306 uint8 magic[REGFI_CELL_MAGIC_SIZE];
307 NTTIME mtime;
308 uint16 name_length;
309 uint16 classname_length;
310 char* classname;
311 char* keyname;
312 uint32 parent_off; /* pointer to parent key */
313 uint32 classname_off;
314
315 /* max lengths */
316 uint32 max_bytes_subkeyname; /* max subkey name * 2 */
317 uint32 max_bytes_subkeyclassname; /* max subkey classname length (as if) */
318 uint32 max_bytes_valuename; /* max valuename * 2 */
319 uint32 max_bytes_value; /* max value data size */
320
321 /* unknowns */
322 uint32 unknown1;
323 uint32 unknown2;
324 uint32 unknown3;
325 uint32 unk_index; /* nigel says run time index ? */
326
327 /* children */
328 uint32 num_subkeys;
329 uint32 subkeys_off; /* offset of subkey list that points to NK records */
330 uint32 num_values;
331 uint32 values_off; /* value lists which point to VK records */
332 uint32 sk_off; /* offset to SK record */
333} REGFI_NK_REC;
334
335
336
337/* REGF block */
338typedef struct
339{
340 /* Run-time information */
341 /************************/
342 /* file descriptor */
343 int fd;
344
345 /* For sanity checking (not part of the registry header) */
346 uint32 file_length;
347
348 /* Metadata about hbins */
349 range_list* hbins;
350
351 /* SK record cached since they're repeatedly reused */
352 lru_cache* sk_cache;
353
354 /* Error/warning/info messages returned by lower layer functions */
355 char* last_message;
356
357 /* Mask for error message types that will be stored. */
358 uint16 msg_mask;
359
360
361 /* Data parsed from file header */
362 /********************************/
363 uint8 magic[REGFI_REGF_MAGIC_SIZE];/* "regf" */
364
365 /* These sequence numbers should match if
366 * the hive was properly synced to disk.
367 */
368 uint32 sequence1;
369 uint32 sequence2;
370
371 NTTIME mtime;
372 uint32 major_version; /* Set to 1 in all known hives */
373 uint32 minor_version; /* Set to 3 or 5 in all known hives */
374 uint32 type; /* XXX: Unverified. Set to 0 in all known hives */
375 uint32 format; /* XXX: Unverified. Set to 1 in all known hives */
376
377 uint32 root_cell; /* Offset to root cell in the first (or any?) hbin block */
378 uint32 last_block; /* Offset to last hbin block in file */
379
380 uint32 cluster; /* XXX: Unverified. Set to 1 in all known hives */
381
382 /* Matches hive's base file name. Stored in UTF-16LE */
383 uint8 file_name[REGFI_REGF_NAME_SIZE];
384
385 WINSEC_UUID* rm_id; /* XXX: Unverified. */
386 WINSEC_UUID* log_id; /* XXX: Unverified. */
387 WINSEC_UUID* tm_id; /* XXX: Unverified. */
388 uint32 flags; /* XXX: Unverified. */
389 uint32 guid_signature; /* XXX: Unverified. */
390
391 uint32 checksum; /* Stored checksum from file */
392 uint32 computed_checksum; /* Our own calculation of the checksum.
393 * (XOR of bytes 0x0000 - 0x01FB) */
394
395 WINSEC_UUID* thaw_tm_id; /* XXX: Unverified. */
396 WINSEC_UUID* thaw_rm_id; /* XXX: Unverified. */
397 WINSEC_UUID* thaw_log_id; /* XXX: Unverified. */
398 uint32 boot_type; /* XXX: Unverified. */
399 uint32 boot_recover; /* XXX: Unverified. */
400
401 /* This seems to include random junk. Possibly unsanitized memory left over
402 * from when header block was written. For instance, chunks of nk records
403 * can be found, though often it's all 0s. */
404 uint8 reserved1[REGFI_REGF_RESERVED1_SIZE];
405
406 /* This is likely reserved and unusued currently. (Should be all 0s.)
407 * Included here for easier access in looking for hidden data
408 * or doing research. */
409 uint8 reserved2[REGFI_REGF_RESERVED2_SIZE];
410
411} REGFI_FILE;
412
413
414/* XXX: Should move all caching (SK records, HBINs, NKs, etc) to a single
415 * structure, probably REGFI_FILE. Once key caching is in place,
416 * convert key_positions stack to store just key offsets rather than
417 * whole keys.
418 */
419typedef struct _regfi_iterator
420{
421 REGFI_FILE* f;
422 void_stack* key_positions;
423 REGFI_NK_REC* cur_key;
424 uint32 cur_subkey;
425 uint32 cur_value;
426} REGFI_ITERATOR;
427
428
429typedef struct _regfi_iter_position
430{
431 REGFI_NK_REC* nk;
432 uint32 cur_subkey;
433 /* We could store a cur_value here as well, but didn't see
434 * the use in it right now.
435 */
436} REGFI_ITER_POSITION;
437
438
439typedef struct _regfi_buffer
440{
441 uint8* buf;
442 uint32_t len;
443} REGFI_BUFFER;
444
445
446/******************************************************************************/
447/* Main iterator API */
448/******************************************************************************/
449REGFI_FILE* regfi_open(const char* filename);
450int regfi_close(REGFI_FILE* r);
451
452/* regfi_get_messages: Get errors, warnings, and/or verbose information
453 * relating to processing of the given registry file.
454 *
455 * Arguments:
456 * file -- the structure for the registry file
457 *
458 * Returns:
459 * A newly allocated char* which must be free()d by the caller.
460 */
461char* regfi_get_messages(REGFI_FILE* file);
462void regfi_set_message_mask(REGFI_FILE* file, uint16 mask);
463
464REGFI_ITERATOR* regfi_iterator_new(REGFI_FILE* fh);
465void regfi_iterator_free(REGFI_ITERATOR* i);
466bool regfi_iterator_down(REGFI_ITERATOR* i);
467bool regfi_iterator_up(REGFI_ITERATOR* i);
468bool regfi_iterator_to_root(REGFI_ITERATOR* i);
469
470bool regfi_iterator_find_subkey(REGFI_ITERATOR* i,
471 const char* subkey_name);
472bool regfi_iterator_walk_path(REGFI_ITERATOR* i,
473 const char** path);
474const REGFI_NK_REC* regfi_iterator_cur_key(REGFI_ITERATOR* i);
475const REGFI_SK_REC* regfi_iterator_cur_sk(REGFI_ITERATOR* i);
476
477REGFI_NK_REC* regfi_iterator_first_subkey(REGFI_ITERATOR* i);
478REGFI_NK_REC* regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
479REGFI_NK_REC* regfi_iterator_next_subkey(REGFI_ITERATOR* i);
480
481bool regfi_iterator_find_value(REGFI_ITERATOR* i,
482 const char* value_name);
483REGFI_VK_REC* regfi_iterator_first_value(REGFI_ITERATOR* i);
484REGFI_VK_REC* regfi_iterator_cur_value(REGFI_ITERATOR* i);
485REGFI_VK_REC* regfi_iterator_next_value(REGFI_ITERATOR* i);
486
487
488/********************************************************/
489/* Middle-layer structure loading, linking, and caching */
490/********************************************************/
491REGFI_NK_REC* regfi_load_key(REGFI_FILE* file, uint32 offset,
492 bool strict);
493REGFI_VK_REC* regfi_load_value(REGFI_FILE* file, uint32 offset,
494 bool strict);
495REGFI_SUBKEY_LIST* regfi_load_subkeylist(REGFI_FILE* file, uint32 offset,
496 uint32 num_keys, uint32 max_size,
497 bool strict);
498REGFI_VALUE_LIST* regfi_load_valuelist(REGFI_FILE* file, uint32 offset,
499 uint32 num_values, uint32 max_size,
500 bool strict);
501
502/* These are cached so return values don't need to be freed. */
503const REGFI_SK_REC* regfi_load_sk(REGFI_FILE* file, uint32 offset,
504 bool strict);
505const REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset);
506
507
508
509/************************************/
510/* Low-layer data structure access */
511/************************************/
512REGFI_FILE* regfi_parse_regf(int fd, bool strict);
513REGFI_HBIN* regfi_parse_hbin(REGFI_FILE* file, uint32 offset,
514 bool strict);
515
516
517/* regfi_parse_nk: Parses an NK record.
518 *
519 * Arguments:
520 * f -- the registry file structure
521 * offset -- the offset of the cell (not the record) to be parsed.
522 * max_size -- the maximum size the NK cell could be. (for validation)
523 * strict -- if true, rejects any malformed records. Otherwise,
524 * tries to minimally validate integrity.
525 * Returns:
526 * A newly allocated NK record structure, or NULL on failure.
527 */
528REGFI_NK_REC* regfi_parse_nk(REGFI_FILE* file, uint32 offset,
529 uint32 max_size, bool strict);
530
531REGFI_SUBKEY_LIST* regfi_parse_subkeylist(REGFI_FILE* file, uint32 offset,
532 uint32 max_size, bool strict);
533
534REGFI_VK_REC* regfi_parse_vk(REGFI_FILE* file, uint32 offset,
535 uint32 max_size, bool strict);
536
537REGFI_BUFFER regfi_load_data(REGFI_FILE* file,
538 uint32 data_type, uint32 offset,
539 uint32 length, uint32 max_size,
540 bool data_in_offset, bool strict);
541
542REGFI_BUFFER regfi_load_big_data(REGFI_FILE* file,
543 uint32 offset, uint32 data_length,
544 uint32 cell_length, bool strict);
545
546REGFI_SK_REC* regfi_parse_sk(REGFI_FILE* file, uint32 offset,
547 uint32 max_size, bool strict);
548
549range_list* regfi_parse_unalloc_cells(REGFI_FILE* file);
550
551bool regfi_parse_cell(int fd, uint32 offset,
552 uint8* hdr, uint32 hdr_len,
553 uint32* cell_length, bool* unalloc);
554
555char* regfi_parse_classname(REGFI_FILE* file, uint32 offset,
556 uint16* name_length,
557 uint32 max_size, bool strict);
558
559/* Dispose of previously parsed records */
560void regfi_free_key(REGFI_NK_REC* nk);
561void regfi_free_value(REGFI_VK_REC* vk);
562
563
564
565/************************************/
566/* Private Functions */
567/************************************/
568REGFI_NK_REC* regfi_rootkey(REGFI_FILE* file);
569void regfi_subkeylist_free(REGFI_SUBKEY_LIST* list);
570uint32 regfi_read(int fd, uint8* buf, uint32* length);
571
572const char* regfi_type_val2str(unsigned int val);
573int regfi_type_str2val(const char* str);
574
575char* regfi_get_sacl(WINSEC_DESC* sec_desc);
576char* regfi_get_dacl(WINSEC_DESC* sec_desc);
577char* regfi_get_owner(WINSEC_DESC* sec_desc);
578char* regfi_get_group(WINSEC_DESC* sec_desc);
579
580REGFI_SUBKEY_LIST* regfi_merge_subkeylists(uint16 num_lists,
581 REGFI_SUBKEY_LIST** lists,
582 bool strict);
583REGFI_SUBKEY_LIST* regfi_load_subkeylist_aux(REGFI_FILE* file, uint32 offset,
584 uint32 max_size, bool strict,
585 uint8 depth_left);
586void regfi_add_message(REGFI_FILE* file, uint16 msg_type,
587 const char* fmt, ...);
588REGFI_NK_REC* regfi_copy_nk(const REGFI_NK_REC* nk);
589REGFI_VK_REC* regfi_copy_vk(const REGFI_VK_REC* vk);
590
591#endif /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.