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