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