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