16be753b3c404c9a498f91a656021847b4634251
[libguestfs.git] / hivex / hivex.c
1 /* hivex - Windows Registry "hive" extraction library.
2  * Copyright (C) 2009 Red Hat Inc.
3  * Derived from code by Petter Nordahl-Hagen under a compatible license:
4  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
5  * Derived from code by Markus Stephany under a compatible license:
6  *   Copyright (c) 2000-2004, Markus Stephany.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation;
11  * version 2.1 of the License.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * See file LICENSE for the full license.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <endian.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <iconv.h>
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <assert.h>
33
34 #include "hivex.h"
35
36 struct hive_h {
37   int fd;
38   size_t size;
39   int msglvl;
40
41   /* Memory-mapped (readonly) registry file. */
42   union {
43     char *addr;
44     struct ntreg_header *hdr;
45   };
46
47   /* Use a bitmap to store which file offsets are valid (point to a
48    * used block).  We only need to store 1 bit per 32 bits of the file
49    * (because blocks are 4-byte aligned).  We found that the average
50    * block size in a registry file is ~50 bytes.  So roughly 1 in 12
51    * bits in the bitmap will be set, making it likely a more efficient
52    * structure than a hash table.
53    */
54   char *bitmap;
55 #define BITMAP_SET(bitmap,off) (bitmap[(off)>>5] |= 1 << (((off)>>2)&7))
56 #define BITMAP_CLR(bitmap,off) (bitmap[(off)>>5] &= ~ (1 << (((off)>>2)&7)))
57 #define BITMAP_TST(bitmap,off) (bitmap[(off)>>5] & (1 << (((off)>>2)&7)))
58 #define IS_VALID_BLOCK(h,off)                 \
59   (((off) & 3) == 0 &&                      \
60    (off) >= 0x1000 &&                       \
61    (off) < (h)->size &&                     \
62    BITMAP_TST((h)->bitmap,(off)))
63
64   /* Fields from the header, extracted from little-endianness. */
65   size_t rootoffs;              /* Root key offset (always an nk-block). */
66
67   /* Stats. */
68   size_t pages;                 /* Number of hbin pages read. */
69   size_t blocks;                /* Total number of blocks found. */
70   size_t used_blocks;           /* Total number of used blocks found. */
71   size_t used_size;             /* Total size (bytes) of used blocks. */
72 };
73
74 /* NB. All fields are little endian. */
75 struct ntreg_header {
76   char magic[4];                /* "regf" */
77   uint32_t unknown1;
78   uint32_t unknown2;
79   char last_modified[8];
80   uint32_t unknown3;            /* 1 */
81   uint32_t unknown4;            /* 3 */
82   uint32_t unknown5;            /* 0 */
83   uint32_t unknown6;            /* 1 */
84   uint32_t offset;              /* offset of root key record - 4KB */
85   uint32_t blocks;              /* size in bytes of data (filesize - 4KB) */
86   uint32_t unknown7;            /* 1 */
87   char name[0x1fc-0x2c];
88   uint32_t csum;                /* checksum: sum of 32 bit words 0-0x1fb. */
89 } __attribute__((__packed__));
90
91 struct ntreg_hbin_page {
92   char magic[4];                /* "hbin" */
93   uint32_t offset_first;        /* offset from 1st block */
94   uint32_t offset_next;         /* offset of next (relative to this) */
95   char unknown[20];
96   /* Linked list of blocks follows here. */
97 } __attribute__((__packed__));
98
99 struct ntreg_hbin_block {
100   int32_t seg_len;              /* length of this block (-ve for used block) */
101   char id[2];                   /* the block type (eg. "nk" for nk record) */
102   /* Block data follows here. */
103 } __attribute__((__packed__));
104
105 #define BLOCK_ID_EQ(h,offs,eqid) \
106   (strncmp (((struct ntreg_hbin_block *)((h)->addr + (offs)))->id, (eqid), 2) == 0)
107
108 static size_t
109 block_len (hive_h *h, size_t blkoff, int *used)
110 {
111   struct ntreg_hbin_block *block;
112   block = (struct ntreg_hbin_block *) (h->addr + blkoff);
113
114   int32_t len = le32toh (block->seg_len);
115   if (len < 0) {
116     if (used) *used = 1;
117     len = -len;
118   } else {
119     if (used) *used = 0;
120   }
121
122   return (size_t) len;
123 }
124
125 struct ntreg_nk_record {
126   int32_t seg_len;              /* length (always -ve because used) */
127   char id[2];                   /* "nk" */
128   uint16_t flags;
129   char timestamp[12];
130   uint32_t parent;              /* offset of owner/parent */
131   uint32_t nr_subkeys;          /* number of subkeys */
132   uint32_t unknown1;
133   uint32_t subkey_lf;           /* lf record containing list of subkeys */
134   uint32_t unknown2;
135   uint32_t nr_values;           /* number of values */
136   uint32_t vallist;             /* value-list record */
137   uint32_t sk;                  /* offset of sk-record */
138   uint32_t classname;           /* offset of classname record */
139   char unknown3[16];
140   uint32_t unknown4;
141   uint16_t name_len;            /* length of name */
142   uint16_t classname_len;       /* length of classname */
143   char name[1];                 /* name follows here */
144 } __attribute__((__packed__));
145
146 struct ntreg_lf_record {
147   int32_t seg_len;
148   char id[2];                   /* "lf" */
149   uint16_t nr_keys;             /* number of keys in this record */
150   struct {
151     uint32_t offset;            /* offset of nk-record for this subkey */
152     char name[4];               /* first 4 characters of subkey name */
153   } keys[1];
154 } __attribute__((__packed__));
155
156 struct ntreg_ri_record {
157   int32_t seg_len;
158   char id[2];                   /* "ri" */
159   uint16_t nr_offsets;          /* number of pointers to lh records */
160   uint32_t offset[1];           /* list of pointers to lh records */
161 } __attribute__((__packed__));
162
163 /* This has no ID header. */
164 struct ntreg_value_list {
165   int32_t seg_len;
166   uint32_t offset[1];           /* list of pointers to vk records */
167 } __attribute__((__packed__));
168
169 struct ntreg_vk_record {
170   int32_t seg_len;              /* length (always -ve because used) */
171   char id[2];                   /* "vk" */
172   uint16_t name_len;            /* length of name */
173   /* length of the data:
174    * If data_len is <= 4, then it's stored inline.
175    * If data_len is 0x80000000, then it's an inline dword.
176    * Top bit may be set or not set at random.
177    */
178   uint32_t data_len;
179   uint32_t data_offset;         /* pointer to the data (or data if inline) */
180   hive_type data_type;          /* type of the data */
181   uint16_t unknown1;            /* possibly always 1 */
182   uint16_t unknown2;
183   char name[1];                 /* key name follows here */
184 } __attribute__((__packed__));
185
186 hive_h *
187 hivex_open (const char *filename, int flags)
188 {
189   hive_h *h = NULL;
190
191   h = calloc (1, sizeof *h);
192   if (h == NULL)
193     goto error;
194
195   h->msglvl = flags & HIVEX_OPEN_MSGLVL_MASK;
196
197   const char *debug = getenv ("HIVEX_DEBUG");
198   if (debug && strcmp (debug, "1") == 0)
199     h->msglvl = 2;
200
201   if (h->msglvl >= 2)
202     printf ("hivex_open: created handle %p\n", h);
203
204   h->fd = open (filename, O_RDONLY);
205   if (h->fd == -1)
206     goto error;
207
208   struct stat statbuf;
209   if (fstat (h->fd, &statbuf) == -1)
210     goto error;
211
212   h->size = statbuf.st_size;
213
214   h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
215   if (h->addr == MAP_FAILED)
216     goto error;
217
218   if (h->msglvl >= 2)
219     printf ("hivex_open: mapped file at %p\n", h->addr);
220
221   /* Check header. */
222   if (h->hdr->magic[0] != 'r' ||
223       h->hdr->magic[1] != 'e' ||
224       h->hdr->magic[2] != 'g' ||
225       h->hdr->magic[3] != 'f') {
226     fprintf (stderr, "hivex: %s: not a Windows NT Registry hive file\n",
227              filename);
228     errno = ENOTSUP;
229     goto error;
230   }
231
232   h->bitmap = calloc (1 + h->size / 32, 1);
233
234 #if 0                           /* Doesn't work. */
235   /* Header checksum. */
236   uint32_t *daddr = h->addr;
237   size_t i;
238   uint32_t sum = 0;
239   for (i = 0; i < 0x1fc / 4; ++i) {
240     sum += le32toh (*daddr);
241     daddr++;
242   }
243   if (sum != le32toh (h->hdr->csum)) {
244     fprintf (stderr, "hivex: %s: bad checksum in hive header\n", filename);
245     errno = EINVAL;
246     goto error;
247   }
248 #endif
249
250   h->rootoffs = le32toh (h->hdr->offset) + 0x1000;
251
252   if (h->msglvl >= 2)
253     printf ("hivex_open: root offset = %zu\n", h->rootoffs);
254
255   /* We'll set this flag when we see a block with the root offset (ie.
256    * the root block).
257    */
258   int seen_root_block = 0, bad_root_block = 0;
259
260   /* Read the pages and blocks.  The aim here is to be robust against
261    * corrupt or malicious registries.  So we make sure the loops
262    * always make forward progress.  We add the address of each block
263    * we read to a hash table so pointers will only reference the start
264    * of valid blocks.
265    */
266   size_t off;
267   struct ntreg_hbin_page *page;
268   for (off = 0x1000; off < h->size; off += le32toh (page->offset_next)) {
269     h->pages++;
270
271     page = (struct ntreg_hbin_page *) (h->addr + off);
272     if (page->magic[0] != 'h' ||
273         page->magic[1] != 'b' ||
274         page->magic[2] != 'i' ||
275         page->magic[3] != 'n') {
276       /* This error is seemingly common in uncorrupt registry files. */
277       /*
278       fprintf (stderr, "hivex: %s: ignoring trailing garbage at end of file (at %zu, after %zu pages)\n",
279                filename, off, h->pages);
280       */
281       break;
282     }
283
284     if (h->msglvl >= 2)
285       printf ("hivex_open: page at %zu\n", off);
286
287     if (le32toh (page->offset_next) <= sizeof (struct ntreg_hbin_page) ||
288         (le32toh (page->offset_next) & 3) != 0) {
289       fprintf (stderr, "hivex: %s: pagesize %d at %zu, bad registry\n",
290                filename, le32toh (page->offset_next), off);
291       errno = ENOTSUP;
292       goto error;
293     }
294
295     /* Read the blocks in this page. */
296     size_t blkoff;
297     struct ntreg_hbin_block *block;
298     int32_t seg_len;
299     for (blkoff = off + 0x20;
300          blkoff < off + le32toh (page->offset_next);
301          blkoff += seg_len) {
302       h->blocks++;
303
304       int is_root = blkoff == h->rootoffs;
305       if (is_root)
306         seen_root_block = 1;
307
308       block = (struct ntreg_hbin_block *) (h->addr + blkoff);
309       int used;
310       seg_len = block_len (h, blkoff, &used);
311       if (seg_len <= 4 || (seg_len & 3) != 0) {
312         fprintf (stderr, "hivex: %s: block size %d at %zu, bad registry\n",
313                  filename, le32toh (block->seg_len), blkoff);
314         errno = ENOTSUP;
315         goto error;
316       }
317
318       if (h->msglvl >= 2)
319         printf ("hivex_open: %s block id %d,%d at %zu%s\n",
320                 used ? "used" : "free", block->id[0], block->id[1], blkoff,
321                 is_root ? " (root)" : "");
322
323       if (is_root && !used)
324         bad_root_block = 1;
325
326       if (used) {
327         h->used_blocks++;
328         h->used_size += seg_len;
329
330         /* Root block must be an nk-block. */
331         if (is_root && (block->id[0] != 'n' || block->id[1] != 'k'))
332           bad_root_block = 1;
333
334         /* Note this blkoff is a valid address. */
335         BITMAP_SET (h->bitmap, blkoff);
336       }
337     }
338   }
339
340   if (!seen_root_block) {
341     fprintf (stderr, "hivex: %s: no root block found\n", filename);
342     errno = ENOTSUP;
343     goto error;
344   }
345
346   if (bad_root_block) {
347     fprintf (stderr, "hivex: %s: bad root block (free or not nk)\n", filename);
348     errno = ENOTSUP;
349     goto error;
350   }
351
352   if (h->msglvl >= 1)
353     printf ("hivex_open: successfully read Windows Registry hive file:\n"
354             "  pages:                  %zu\n"
355             "  blocks:                 %zu\n"
356             "  blocks used:            %zu\n"
357             "  bytes used:             %zu\n",
358             h->pages, h->blocks, h->used_blocks, h->used_size);
359
360   return h;
361
362  error:;
363   int err = errno;
364   if (h) {
365     free (h->bitmap);
366     if (h->addr && h->size && h->addr != MAP_FAILED)
367       munmap (h->addr, h->size);
368     if (h->fd >= 0)
369       close (h->fd);
370     free (h);
371   }
372   errno = err;
373   return NULL;
374 }
375
376 int
377 hivex_close (hive_h *h)
378 {
379   int r;
380
381   free (h->bitmap);
382   munmap (h->addr, h->size);
383   r = close (h->fd);
384   free (h);
385
386   return r;
387 }
388
389 hive_node_h
390 hivex_root (hive_h *h)
391 {
392   hive_node_h ret = h->rootoffs;
393   if (!IS_VALID_BLOCK (h, ret)) {
394     errno = ENOKEY;
395     return 0;
396   }
397   return ret;
398 }
399
400 char *
401 hivex_node_name (hive_h *h, hive_node_h node)
402 {
403   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
404     errno = EINVAL;
405     return NULL;
406   }
407
408   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
409
410   /* AFAIK the node name is always plain ASCII, so no conversion
411    * to UTF-8 is necessary.  However we do need to nul-terminate
412    * the string.
413    */
414
415   /* nk->name_len is unsigned, 16 bit, so this is safe ...  However
416    * we have to make sure the length doesn't exceed the block length.
417    */
418   size_t len = le16toh (nk->name_len);
419   size_t seg_len = block_len (h, node, NULL);
420   if (sizeof (struct ntreg_nk_record) + len - 1 > seg_len) {
421     if (h->msglvl >= 2)
422       printf ("hivex_node_name: returning EFAULT because node name is too long (%zu, %zu)\n",
423               len, seg_len);
424     errno = EFAULT;
425     return NULL;
426   }
427
428   char *ret = malloc (len + 1);
429   if (ret == NULL)
430     return NULL;
431   memcpy (ret, nk->name, len);
432   ret[len] = '\0';
433   return ret;
434 }
435
436 #if 0
437 /* I think the documentation for the sk and classname fields in the nk
438  * record is wrong, or else the offset field is in the wrong place.
439  * Otherwise this makes no sense.  Disabled this for now -- it's not
440  * useful for reading the registry anyway.
441  */
442
443 hive_security_h
444 hivex_node_security (hive_h *h, hive_node_h node)
445 {
446   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
447     errno = EINVAL;
448     return 0;
449   }
450
451   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
452
453   hive_node_h ret = le32toh (nk->sk);
454   ret += 0x1000;
455   if (!IS_VALID_BLOCK (h, ret)) {
456     errno = EFAULT;
457     return 0;
458   }
459   return ret;
460 }
461
462 hive_classname_h
463 hivex_node_classname (hive_h *h, hive_node_h node)
464 {
465   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
466     errno = EINVAL;
467     return 0;
468   }
469
470   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
471
472   hive_node_h ret = le32toh (nk->classname);
473   ret += 0x1000;
474   if (!IS_VALID_BLOCK (h, ret)) {
475     errno = EFAULT;
476     return 0;
477   }
478   return ret;
479 }
480 #endif
481
482 hive_node_h *
483 hivex_node_children (hive_h *h, hive_node_h node)
484 {
485   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
486     errno = EINVAL;
487     return NULL;
488   }
489
490   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
491
492   size_t nr_subkeys_in_nk = le32toh (nk->nr_subkeys);
493
494   /* Deal with the common "no subkeys" case quickly. */
495   hive_node_h *ret;
496   if (nr_subkeys_in_nk == 0) {
497     ret = malloc (sizeof (hive_node_h));
498     if (ret == NULL)
499       return NULL;
500     ret[0] = 0;
501     return ret;
502   }
503
504   /* Arbitrarily limit the number of subkeys we will ever deal with. */
505   if (nr_subkeys_in_nk > 1000000) {
506     errno = ERANGE;
507     return NULL;
508   }
509
510   /* The subkey_lf field can point either to an lf-record, which is
511    * the common case, or if there are lots of subkeys, to an
512    * ri-record.
513    */
514   size_t subkey_lf = le32toh (nk->subkey_lf);
515   subkey_lf += 0x1000;
516   if (!IS_VALID_BLOCK (h, subkey_lf)) {
517     if (h->msglvl >= 2)
518       printf ("hivex_node_children: returning EFAULT because subkey_lf is not a valid block (%zu)\n",
519               subkey_lf);
520     errno = EFAULT;
521     return NULL;
522   }
523
524   struct ntreg_hbin_block *block =
525     (struct ntreg_hbin_block *) (h->addr + subkey_lf);
526
527   /* Points to lf-record?  (Note, also "lh" but that is basically the
528    * same as "lf" as far as we are concerned here).
529    */
530   if (block->id[0] == 'l' && (block->id[1] == 'f' || block->id[1] == 'h')) {
531     struct ntreg_lf_record *lf = (struct ntreg_lf_record *) block;
532
533     /* Check number of subkeys in the nk-record matches number of subkeys
534      * in the lf-record.
535      */
536     size_t nr_subkeys_in_lf = le16toh (lf->nr_keys);
537
538     if (h->msglvl >= 2)
539       printf ("hivex_node_children: nr_subkeys_in_nk = %zu, nr_subkeys_in_lf = %zu\n",
540               nr_subkeys_in_nk, nr_subkeys_in_lf);
541
542     if (nr_subkeys_in_nk != nr_subkeys_in_lf) {
543       errno = ENOTSUP;
544       return NULL;
545     }
546
547     size_t len = block_len (h, subkey_lf, NULL);
548     if (8 + nr_subkeys_in_lf * 8 > len) {
549       if (h->msglvl >= 2)
550         printf ("hivex_node_children: returning EFAULT because too many subkeys (%zu, %zu)\n",
551                 nr_subkeys_in_lf, len);
552       errno = EFAULT;
553       return NULL;
554     }
555
556     /* Allocate space for the returned values.  Note that
557      * nr_subkeys_in_lf is limited to a 16 bit value.
558      */
559     ret = malloc ((1 + nr_subkeys_in_lf) * sizeof (hive_node_h));
560     if (ret == NULL)
561       return NULL;
562
563     size_t i;
564     for (i = 0; i < nr_subkeys_in_lf; ++i) {
565       hive_node_h subkey = lf->keys[i].offset;
566       subkey += 0x1000;
567       if (!IS_VALID_BLOCK (h, subkey)) {
568         if (h->msglvl >= 2)
569           printf ("hivex_node_children: returning EFAULT because subkey is not a valid block (%zu)\n",
570                   subkey);
571         errno = EFAULT;
572         free (ret);
573         return NULL;
574       }
575       ret[i] = subkey;
576     }
577     ret[i] = 0;
578     return ret;
579   }
580   /* Points to ri-record? */
581   else if (block->id[0] == 'r' && block->id[1] == 'i') {
582     struct ntreg_ri_record *ri = (struct ntreg_ri_record *) block;
583
584     size_t nr_offsets = le16toh (ri->nr_offsets);
585
586     /* Count total number of children. */
587     size_t i, count = 0;
588     for (i = 0; i < nr_offsets; ++i) {
589       hive_node_h offset = ri->offset[i];
590       offset += 0x1000;
591       if (!IS_VALID_BLOCK (h, offset)) {
592         if (h->msglvl >= 2)
593           printf ("hivex_node_children: returning EFAULT because ri-offset is not a valid block (%zu)\n",
594                   offset);
595         errno = EFAULT;
596         return NULL;
597       }
598       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
599         errno = ENOTSUP;
600         return NULL;
601       }
602
603       struct ntreg_lf_record *lf =
604         (struct ntreg_lf_record *) (h->addr + offset);
605
606       count += le16toh (lf->nr_keys);
607     }
608
609     if (h->msglvl >= 2)
610       printf ("hivex_node_children: nr_subkeys_in_nk = %zu, counted = %zu\n",
611               nr_subkeys_in_nk, count);
612
613     if (nr_subkeys_in_nk != count) {
614       errno = ENOTSUP;
615       return NULL;
616     }
617
618     /* Copy list of children.  Note nr_subkeys_in_nk is limited to
619      * something reasonable above.
620      */
621     ret = malloc ((1 + nr_subkeys_in_nk) * sizeof (hive_node_h));
622     if (ret == NULL)
623       return NULL;
624
625     count = 0;
626     for (i = 0; i < nr_offsets; ++i) {
627       hive_node_h offset = ri->offset[i];
628       offset += 0x1000;
629       if (!IS_VALID_BLOCK (h, offset)) {
630         if (h->msglvl >= 2)
631           printf ("hivex_node_children: returning EFAULT because ri-offset is not a valid block (%zu)\n",
632                   offset);
633         errno = EFAULT;
634         return NULL;
635       }
636       if (!BLOCK_ID_EQ (h, offset, "lf") && !BLOCK_ID_EQ (h, offset, "lh")) {
637         errno = ENOTSUP;
638         return NULL;
639       }
640
641       struct ntreg_lf_record *lf =
642         (struct ntreg_lf_record *) (h->addr + offset);
643
644       size_t j;
645       for (j = 0; j < le16toh (lf->nr_keys); ++j) {
646         hive_node_h subkey = lf->keys[j].offset;
647         subkey += 0x1000;
648         if (!IS_VALID_BLOCK (h, subkey)) {
649           if (h->msglvl >= 2)
650             printf ("hivex_node_children: returning EFAULT because indirect subkey is not a valid block (%zu)\n",
651                     subkey);
652           errno = EFAULT;
653           free (ret);
654           return NULL;
655         }
656         ret[count++] = subkey;
657       }
658     }
659     ret[count] = 0;
660
661     return ret;
662   }
663   else {
664     errno = ENOTSUP;
665     return NULL;
666   }
667 }
668
669 /* Very inefficient, but at least having a separate API call
670  * allows us to make it more efficient in future.
671  */
672 hive_node_h
673 hivex_node_get_child (hive_h *h, hive_node_h node, const char *nname)
674 {
675   hive_node_h *children = NULL;
676   char *name = NULL;
677   hive_node_h ret = 0;
678
679   children = hivex_node_children (h, node);
680   if (!children) goto error;
681
682   size_t i;
683   for (i = 0; children[i] != 0; ++i) {
684     name = hivex_node_name (h, children[i]);
685     if (!name) goto error;
686     if (strcasecmp (name, nname) == 0) {
687       ret = children[i];
688       break;
689     }
690     free (name); name = NULL;
691   }
692
693  error:
694   free (children);
695   free (name);
696   return ret;
697 }
698
699 hive_node_h
700 hivex_node_parent (hive_h *h, hive_node_h node)
701 {
702   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
703     errno = EINVAL;
704     return 0;
705   }
706
707   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
708
709   hive_node_h ret = le32toh (nk->parent);
710   ret += 0x1000;
711   printf ("parent = %zu\n", ret);
712   if (!IS_VALID_BLOCK (h, ret)) {
713     if (h->msglvl >= 2)
714       printf ("hivex_node_parent: returning EFAULT because parent is not a valid block (%zu)\n",
715               ret);
716     errno = EFAULT;
717     return 0;
718   }
719   return ret;
720 }
721
722 hive_value_h *
723 hivex_node_values (hive_h *h, hive_node_h node)
724 {
725   if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
726     errno = EINVAL;
727     return 0;
728   }
729
730   struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node);
731
732   size_t nr_values = le32toh (nk->nr_values);
733
734   if (h->msglvl >= 2)
735     printf ("hivex_node_values: nr_values = %zu\n", nr_values);
736
737   /* Deal with the common "no values" case quickly. */
738   hive_node_h *ret;
739   if (nr_values == 0) {
740     ret = malloc (sizeof (hive_node_h));
741     if (ret == NULL)
742       return NULL;
743     ret[0] = 0;
744     return ret;
745   }
746
747   /* Arbitrarily limit the number of values we will ever deal with. */
748   if (nr_values > 100000) {
749     errno = ERANGE;
750     return NULL;
751   }
752
753   /* Get the value list and check it looks reasonable. */
754   size_t vlist_offset = le32toh (nk->vallist);
755   vlist_offset += 0x1000;
756   if (!IS_VALID_BLOCK (h, vlist_offset)) {
757     if (h->msglvl >= 2)
758       printf ("hivex_node_values: returning EFAULT because value list is not a valid block (%zu)\n",
759               vlist_offset);
760     errno = EFAULT;
761     return NULL;
762   }
763
764   struct ntreg_value_list *vlist =
765     (struct ntreg_value_list *) (h->addr + vlist_offset);
766
767   size_t len = block_len (h, vlist_offset, NULL);
768   if (4 + nr_values * 4 > len) {
769     if (h->msglvl >= 2)
770       printf ("hivex_node_values: returning EFAULT because value list is too long (%zu, %zu)\n",
771               nr_values, len);
772     errno = EFAULT;
773     return NULL;
774   }
775
776   /* Allocate return array and copy values in. */
777   ret = malloc ((1 + nr_values) * sizeof (hive_node_h));
778   if (ret == NULL)
779     return NULL;
780
781   size_t i;
782   for (i = 0; i < nr_values; ++i) {
783     hive_node_h value = vlist->offset[i];
784     value += 0x1000;
785     if (!IS_VALID_BLOCK (h, value)) {
786       if (h->msglvl >= 2)
787         printf ("hivex_node_values: returning EFAULT because value is not a valid block (%zu)\n",
788                 value);
789       errno = EFAULT;
790       free (ret);
791       return NULL;
792     }
793     ret[i] = value;
794   }
795
796   ret[i] = 0;
797   return ret;
798 }
799
800 /* Very inefficient, but at least having a separate API call
801  * allows us to make it more efficient in future.
802  */
803 hive_value_h
804 hivex_node_get_value (hive_h *h, hive_node_h node, const char *key)
805 {
806   hive_value_h *values = NULL;
807   char *name = NULL;
808   hive_value_h ret = 0;
809
810   values = hivex_node_values (h, node);
811   if (!values) goto error;
812
813   size_t i;
814   for (i = 0; values[i] != 0; ++i) {
815     name = hivex_value_key (h, values[i]);
816     if (!name) goto error;
817     if (strcasecmp (name, key) == 0) {
818       ret = values[i];
819       break;
820     }
821     free (name); name = NULL;
822   }
823
824  error:
825   free (values);
826   free (name);
827   return ret;
828 }
829
830 char *
831 hivex_value_key (hive_h *h, hive_value_h value)
832 {
833   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
834     errno = EINVAL;
835     return 0;
836   }
837
838   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
839
840   /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is
841    * necessary.  However we do need to nul-terminate the string.
842    */
843
844   /* vk->name_len is unsigned, 16 bit, so this is safe ...  However
845    * we have to make sure the length doesn't exceed the block length.
846    */
847   size_t len = le16toh (vk->name_len);
848   size_t seg_len = block_len (h, value, NULL);
849   if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) {
850     if (h->msglvl >= 2)
851       printf ("hivex_value_key: returning EFAULT because key length is too long (%zu, %zu)\n",
852               len, seg_len);
853     errno = EFAULT;
854     return NULL;
855   }
856
857   char *ret = malloc (len + 1);
858   if (ret == NULL)
859     return NULL;
860   memcpy (ret, vk->name, len);
861   ret[len] = '\0';
862   return ret;
863 }
864
865 int
866 hivex_value_type (hive_h *h, hive_value_h value, hive_type *t, size_t *len)
867 {
868   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
869     errno = EINVAL;
870     return -1;
871   }
872
873   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
874
875   if (t)
876     *t = le32toh (vk->data_type);
877
878   if (len) {
879     *len = le32toh (vk->data_len);
880     if (*len == 0x80000000) {   /* special case */
881       *len = 4;
882       if (t) *t = hive_t_dword;
883     }
884     *len &= 0x7fffffff;
885   }
886
887   return 0;
888 }
889
890 char *
891 hivex_value_value (hive_h *h, hive_value_h value,
892                    hive_type *t_rtn, size_t *len_rtn)
893 {
894   if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) {
895     errno = EINVAL;
896     return NULL;
897   }
898
899   struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value);
900
901   hive_type t;
902   size_t len;
903
904   t = le32toh (vk->data_type);
905
906   len = le32toh (vk->data_len);
907   if (len == 0x80000000) {      /* special case */
908     len = 4;
909     t = hive_t_dword;
910   }
911   len &= 0x7fffffff;
912
913   if (h->msglvl >= 2)
914     printf ("hivex_value_value: value=%zu, t=%d, len=%zu\n",
915             value, t, len);
916
917   if (t_rtn)
918     *t_rtn = t;
919   if (len_rtn)
920     *len_rtn = len;
921
922   /* Arbitrarily limit the length that we will read. */
923   if (len > 1000000) {
924     errno = ERANGE;
925     return NULL;
926   }
927
928   char *ret = malloc (len);
929   if (ret == NULL)
930     return NULL;
931
932   /* If length is <= 4 it's always stored inline. */
933   if (len <= 4) {
934     memcpy (ret, (char *) &vk->data_offset, len);
935     return ret;
936   }
937
938   size_t data_offset = vk->data_offset;
939   data_offset += 0x1000;
940   if (!IS_VALID_BLOCK (h, data_offset)) {
941     if (h->msglvl >= 2)
942       printf ("hivex_value_value: returning EFAULT because data offset is not a valid block (%zu)\n",
943               data_offset);
944     errno = EFAULT;
945     free (ret);
946     return NULL;
947   }
948
949   /* Check that the declared size isn't larger than the block its in. */
950   size_t blen = block_len (h, data_offset, NULL);
951   if (blen < len) {
952     if (h->msglvl >= 2)
953       printf ("hivex_value_value: returning EFAULT because data is longer than its block (%zu, %zu)\n",
954               blen, len);
955     errno = EFAULT;
956     free (ret);
957     return NULL;
958   }
959
960   char *data = h->addr + data_offset + 4;
961   memcpy (ret, data, len);
962   return ret;
963 }
964
965 static char *
966 windows_utf16_to_utf8 (/* const */ char *input, size_t len)
967 {
968   iconv_t ic = iconv_open ("UTF-8", "UTF-16");
969   if (ic == (iconv_t) -1)
970     return NULL;
971
972   /* iconv(3) has an insane interface ... */
973
974   /* Mostly UTF-8 will be smaller, so this is a good initial guess. */
975   size_t outalloc = len;
976
977  again:;
978   size_t inlen = len;
979   size_t outlen = outalloc;
980   char *out = malloc (outlen + 1);
981   if (out == NULL) {
982     int err = errno;
983     iconv_close (ic);
984     errno = err;
985     return NULL;
986   }
987   char *inp = input;
988   char *outp = out;
989
990   size_t r = iconv (ic, &inp, &inlen, &outp, &outlen);
991   if (r == (size_t) -1) {
992     if (errno == E2BIG) {
993       /* Try again with a larger output buffer. */
994       free (out);
995       outalloc *= 2;
996       goto again;
997     }
998     else {
999       /* Else some conversion failure, eg. EILSEQ, EINVAL. */
1000       int err = errno;
1001       iconv_close (ic);
1002       free (out);
1003       errno = err;
1004       return NULL;
1005     }
1006   }
1007
1008   *outp = '\0';
1009   iconv_close (ic);
1010
1011   return out;
1012 }
1013
1014 char *
1015 hivex_value_string (hive_h *h, hive_value_h value)
1016 {
1017   hive_type t;
1018   size_t len;
1019   char *data = hivex_value_value (h, value, &t, &len);
1020
1021   if (data == NULL)
1022     return NULL;
1023
1024   if (t != hive_t_string && t != hive_t_expand_string && t != hive_t_link) {
1025     free (data);
1026     errno = EINVAL;
1027     return NULL;
1028   }
1029
1030   char *ret = windows_utf16_to_utf8 (data, len);
1031   free (data);
1032   if (ret == NULL)
1033     return NULL;
1034
1035   return ret;
1036 }
1037
1038 static void
1039 free_strings (char **argv)
1040 {
1041   if (argv) {
1042     size_t i;
1043
1044     for (i = 0; argv[i] != NULL; ++i)
1045       free (argv[i]);
1046     free (argv);
1047   }
1048 }
1049
1050 /* Get the length of a UTF-16 format string.  Handle the string as
1051  * pairs of bytes, looking for the first \0\0 pair.
1052  */
1053 static size_t
1054 utf16_string_len_in_bytes (const char *str)
1055 {
1056   size_t ret = 0;
1057
1058   while (str[0] || str[1]) {
1059     str += 2;
1060     ret += 2;
1061   }
1062
1063   return ret;
1064 }
1065
1066 /* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx */
1067 char **
1068 hivex_value_multiple_strings (hive_h *h, hive_value_h value)
1069 {
1070   hive_type t;
1071   size_t len;
1072   char *data = hivex_value_value (h, value, &t, &len);
1073
1074   if (data == NULL)
1075     return NULL;
1076
1077   if (t != hive_t_multiple_strings) {
1078     free (data);
1079     errno = EINVAL;
1080     return NULL;
1081   }
1082
1083   size_t nr_strings = 0;
1084   char **ret = malloc ((1 + nr_strings) * sizeof (char *));
1085   if (ret == NULL) {
1086     free (data);
1087     return NULL;
1088   }
1089   ret[0] = NULL;
1090
1091   char *p = data;
1092   size_t plen;
1093
1094   while (p < data + len && (plen = utf16_string_len_in_bytes (p)) > 0) {
1095     nr_strings++;
1096     char **ret2 = realloc (ret, (1 + nr_strings) * sizeof (char *));
1097     if (ret2 == NULL) {
1098       free_strings (ret);
1099       free (data);
1100       return NULL;
1101     }
1102     ret = ret2;
1103
1104     ret[nr_strings-1] = windows_utf16_to_utf8 (p, plen);
1105     ret[nr_strings] = NULL;
1106     if (ret[nr_strings-1] == NULL) {
1107       free_strings (ret);
1108       free (data);
1109       return NULL;
1110     }
1111
1112     p += plen + 2 /* skip over UTF-16 \0\0 at the end of this string */;
1113   }
1114
1115   free (data);
1116   return ret;
1117 }
1118
1119 int32_t
1120 hivex_value_dword (hive_h *h, hive_value_h value)
1121 {
1122   hive_type t;
1123   size_t len;
1124   char *data = hivex_value_value (h, value, &t, &len);
1125
1126   if (data == NULL)
1127     return -1;
1128
1129   if ((t != hive_t_dword && t != hive_t_dword_be) || len != 4) {
1130     free (data);
1131     errno = EINVAL;
1132     return -1;
1133   }
1134
1135   int32_t ret = *(int32_t*)data;
1136   free (data);
1137   if (t == hive_t_dword)        /* little endian */
1138     ret = le32toh (ret);
1139   else
1140     ret = be32toh (ret);
1141
1142   return ret;
1143 }
1144
1145 int64_t
1146 hivex_value_qword (hive_h *h, hive_value_h value)
1147 {
1148   hive_type t;
1149   size_t len;
1150   char *data = hivex_value_value (h, value, &t, &len);
1151
1152   if (data == NULL)
1153     return -1;
1154
1155   if (t != hive_t_qword || len != 8) {
1156     free (data);
1157     errno = EINVAL;
1158     return -1;
1159   }
1160
1161   int64_t ret = *(int64_t*)data;
1162   free (data);
1163   ret = le64toh (ret);          /* always little endian */
1164
1165   return ret;
1166 }
1167
1168 int
1169 hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len,
1170              void *opaque, int flags)
1171 {
1172   return hivex_visit_node (h, hivex_root (h), visitor, len, opaque, flags);
1173 }
1174
1175 static int hivex__visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *vtor, char *unvisited, void *opaque, int flags);
1176
1177 int
1178 hivex_visit_node (hive_h *h, hive_node_h node,
1179                   const struct hivex_visitor *visitor, size_t len, void *opaque,
1180                   int flags)
1181 {
1182   struct hivex_visitor vtor;
1183   memset (&vtor, 0, sizeof vtor);
1184
1185   /* Note that len might be larger *or smaller* than the expected size. */
1186   size_t copysize = len <= sizeof vtor ? len : sizeof vtor;
1187   memcpy (&vtor, visitor, copysize);
1188
1189   /* This bitmap records unvisited nodes, so we don't loop if the
1190    * registry contains cycles.
1191    */
1192   char *unvisited = malloc (1 + h->size / 32);
1193   if (unvisited == NULL)
1194     return -1;
1195   memcpy (unvisited, h->bitmap, 1 + h->size / 32);
1196
1197   int r = hivex__visit_node (h, node, &vtor, unvisited, opaque, flags);
1198   free (unvisited);
1199   return r;
1200 }
1201
1202 static int
1203 hivex__visit_node (hive_h *h, hive_node_h node,
1204                    const struct hivex_visitor *vtor, char *unvisited,
1205                    void *opaque, int flags)
1206 {
1207   int skip_bad = flags & HIVEX_VISIT_SKIP_BAD;
1208   char *name = NULL;
1209   hive_value_h *values = NULL;
1210   hive_node_h *children = NULL;
1211   char *key = NULL;
1212   char *str = NULL;
1213   char **strs = NULL;
1214   int i;
1215
1216   /* Return -1 on all callback errors.  However on internal errors,
1217    * check if skip_bad is set and suppress those errors if so.
1218    */
1219   int ret = -1;
1220
1221   if (!BITMAP_TST (unvisited, node)) {
1222     if (h->msglvl >= 2)
1223       printf ("hivex__visit_node: contains cycle: visited node %zu already\n",
1224               node);
1225
1226     errno = ELOOP;
1227     return skip_bad ? 0 : -1;
1228   }
1229   BITMAP_CLR (unvisited, node);
1230
1231   name = hivex_node_name (h, node);
1232   if (!name) return skip_bad ? 0 : -1;
1233   if (vtor->node_start && vtor->node_start (h, opaque, node, name) == -1)
1234     goto error;
1235
1236   values = hivex_node_values (h, node);
1237   if (!values) {
1238     ret = skip_bad ? 0 : -1;
1239     goto error;
1240   }
1241
1242   for (i = 0; values[i] != 0; ++i) {
1243     hive_type t;
1244     size_t len;
1245
1246     if (hivex_value_type (h, values[i], &t, &len) == -1) {
1247       ret = skip_bad ? 0 : -1;
1248       goto error;
1249     }
1250
1251     key = hivex_value_key (h, values[i]);
1252     if (key == NULL) {
1253       ret = skip_bad ? 0 : -1;
1254       goto error;
1255     }
1256
1257     switch (t) {
1258     case hive_t_none:
1259       str = hivex_value_value (h, values[i], &t, &len);
1260       if (str == NULL) {
1261         ret = skip_bad ? 0 : -1;
1262         goto error;
1263       }
1264       if (t != hive_t_none) {
1265         ret = skip_bad ? 0 : -1;
1266         goto error;
1267       }
1268       if (vtor->value_none &&
1269           vtor->value_none (h, opaque, node, values[i], t, len, key, str) == -1)
1270         goto error;
1271       free (str); str = NULL;
1272       break;
1273
1274     case hive_t_string:
1275     case hive_t_expand_string:
1276     case hive_t_link:
1277       str = hivex_value_string (h, values[i]);
1278       if (str == NULL) {
1279         if (errno != EILSEQ && errno != EINVAL) {
1280           ret = skip_bad ? 0 : -1;
1281           goto error;
1282         }
1283         if (vtor->value_string_invalid_utf16) {
1284           str = hivex_value_value (h, values[i], &t, &len);
1285           if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1286             goto error;
1287           free (str); str = NULL;
1288         }
1289         break;
1290       }
1291       if (vtor->value_string &&
1292           vtor->value_string (h, opaque, node, values[i], t, len, key, str) == -1)
1293         goto error;
1294       free (str); str = NULL;
1295       break;
1296
1297     case hive_t_dword:
1298     case hive_t_dword_be: {
1299       int32_t i32 = hivex_value_dword (h, values[i]);
1300       if (vtor->value_dword &&
1301           vtor->value_dword (h, opaque, node, values[i], t, len, key, i32) == -1)
1302         goto error;
1303       break;
1304     }
1305
1306     case hive_t_qword: {
1307       int64_t i64 = hivex_value_qword (h, values[i]);
1308       if (vtor->value_qword &&
1309           vtor->value_qword (h, opaque, node, values[i], t, len, key, i64) == -1)
1310         goto error;
1311       break;
1312     }
1313
1314     case hive_t_binary:
1315       str = hivex_value_value (h, values[i], &t, &len);
1316       if (str == NULL) {
1317         ret = skip_bad ? 0 : -1;
1318         goto error;
1319       }
1320       if (t != hive_t_binary) {
1321         ret = skip_bad ? 0 : -1;
1322         goto error;
1323       }
1324       if (vtor->value_binary &&
1325           vtor->value_binary (h, opaque, node, values[i], t, len, key, str) == -1)
1326         goto error;
1327       free (str); str = NULL;
1328       break;
1329
1330     case hive_t_multiple_strings:
1331       strs = hivex_value_multiple_strings (h, values[i]);
1332       if (strs == NULL) {
1333         if (errno != EILSEQ && errno != EINVAL) {
1334           ret = skip_bad ? 0 : -1;
1335           goto error;
1336         }
1337         if (vtor->value_string_invalid_utf16) {
1338           str = hivex_value_value (h, values[i], &t, &len);
1339           if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1340             goto error;
1341           free (str); str = NULL;
1342         }
1343         break;
1344       }
1345       if (vtor->value_multiple_strings &&
1346           vtor->value_multiple_strings (h, opaque, node, values[i], t, len, key, strs) == -1)
1347         goto error;
1348       free_strings (strs); strs = NULL;
1349       break;
1350
1351     case hive_t_resource_list:
1352     case hive_t_full_resource_description:
1353     case hive_t_resource_requirements_list:
1354     default:
1355       str = hivex_value_value (h, values[i], &t, &len);
1356       if (str == NULL) {
1357         ret = skip_bad ? 0 : -1;
1358         goto error;
1359       }
1360       if (vtor->value_other &&
1361           vtor->value_other (h, opaque, node, values[i], t, len, key, str) == -1)
1362         goto error;
1363       free (str); str = NULL;
1364       break;
1365     }
1366
1367     free (key); key = NULL;
1368   }
1369
1370   children = hivex_node_children (h, node);
1371   if (children == NULL) {
1372     ret = skip_bad ? 0 : -1;
1373     goto error;
1374   }
1375
1376   for (i = 0; children[i] != 0; ++i) {
1377     if (h->msglvl >= 2)
1378       printf ("hivex__visit_node: %s: visiting subkey %d (%zu)\n",
1379               name, i, children[i]);
1380
1381     if (hivex__visit_node (h, children[i], vtor, unvisited, opaque, flags) == -1)
1382       goto error;
1383   }
1384
1385   if (vtor->node_end && vtor->node_end (h, opaque, node, name) == -1)
1386     goto error;
1387
1388   ret = 0;
1389
1390  error:
1391   free (name);
1392   free (values);
1393   free (children);
1394   free (key);
1395   free (str);
1396   free_strings (strs);
1397   return ret;
1398 }