4fa3b301608e8ddbfe6e13fa90b445329827336e
[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       /* Try again with a larger output buffer. */
1037       free (out);
1038       outalloc *= 2;
1039       goto again;
1040     }
1041     else {
1042       /* Else some conversion failure, eg. EILSEQ, EINVAL. */
1043       int err = errno;
1044       iconv_close (ic);
1045       free (out);
1046       errno = err;
1047       return NULL;
1048     }
1049   }
1050
1051   *outp = '\0';
1052   iconv_close (ic);
1053
1054   return out;
1055 }
1056
1057 char *
1058 hivex_value_string (hive_h *h, hive_value_h value)
1059 {
1060   hive_type t;
1061   size_t len;
1062   char *data = hivex_value_value (h, value, &t, &len);
1063
1064   if (data == NULL)
1065     return NULL;
1066
1067   if (t != hive_t_string && t != hive_t_expand_string && t != hive_t_link) {
1068     free (data);
1069     errno = EINVAL;
1070     return NULL;
1071   }
1072
1073   char *ret = windows_utf16_to_utf8 (data, len);
1074   free (data);
1075   if (ret == NULL)
1076     return NULL;
1077
1078   return ret;
1079 }
1080
1081 static void
1082 free_strings (char **argv)
1083 {
1084   if (argv) {
1085     size_t i;
1086
1087     for (i = 0; argv[i] != NULL; ++i)
1088       free (argv[i]);
1089     free (argv);
1090   }
1091 }
1092
1093 /* Get the length of a UTF-16 format string.  Handle the string as
1094  * pairs of bytes, looking for the first \0\0 pair.
1095  */
1096 static size_t
1097 utf16_string_len_in_bytes (const char *str)
1098 {
1099   size_t ret = 0;
1100
1101   while (str[0] || str[1]) {
1102     str += 2;
1103     ret += 2;
1104   }
1105
1106   return ret;
1107 }
1108
1109 /* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx */
1110 char **
1111 hivex_value_multiple_strings (hive_h *h, hive_value_h value)
1112 {
1113   hive_type t;
1114   size_t len;
1115   char *data = hivex_value_value (h, value, &t, &len);
1116
1117   if (data == NULL)
1118     return NULL;
1119
1120   if (t != hive_t_multiple_strings) {
1121     free (data);
1122     errno = EINVAL;
1123     return NULL;
1124   }
1125
1126   size_t nr_strings = 0;
1127   char **ret = malloc ((1 + nr_strings) * sizeof (char *));
1128   if (ret == NULL) {
1129     free (data);
1130     return NULL;
1131   }
1132   ret[0] = NULL;
1133
1134   char *p = data;
1135   size_t plen;
1136
1137   while (p < data + len && (plen = utf16_string_len_in_bytes (p)) > 0) {
1138     nr_strings++;
1139     char **ret2 = realloc (ret, (1 + nr_strings) * sizeof (char *));
1140     if (ret2 == NULL) {
1141       free_strings (ret);
1142       free (data);
1143       return NULL;
1144     }
1145     ret = ret2;
1146
1147     ret[nr_strings-1] = windows_utf16_to_utf8 (p, plen);
1148     ret[nr_strings] = NULL;
1149     if (ret[nr_strings-1] == NULL) {
1150       free_strings (ret);
1151       free (data);
1152       return NULL;
1153     }
1154
1155     p += plen + 2 /* skip over UTF-16 \0\0 at the end of this string */;
1156   }
1157
1158   free (data);
1159   return ret;
1160 }
1161
1162 int32_t
1163 hivex_value_dword (hive_h *h, hive_value_h value)
1164 {
1165   hive_type t;
1166   size_t len;
1167   char *data = hivex_value_value (h, value, &t, &len);
1168
1169   if (data == NULL)
1170     return -1;
1171
1172   if ((t != hive_t_dword && t != hive_t_dword_be) || len != 4) {
1173     free (data);
1174     errno = EINVAL;
1175     return -1;
1176   }
1177
1178   int32_t ret = *(int32_t*)data;
1179   free (data);
1180   if (t == hive_t_dword)        /* little endian */
1181     ret = le32toh (ret);
1182   else
1183     ret = be32toh (ret);
1184
1185   return ret;
1186 }
1187
1188 int64_t
1189 hivex_value_qword (hive_h *h, hive_value_h value)
1190 {
1191   hive_type t;
1192   size_t len;
1193   char *data = hivex_value_value (h, value, &t, &len);
1194
1195   if (data == NULL)
1196     return -1;
1197
1198   if (t != hive_t_qword || len != 8) {
1199     free (data);
1200     errno = EINVAL;
1201     return -1;
1202   }
1203
1204   int64_t ret = *(int64_t*)data;
1205   free (data);
1206   ret = le64toh (ret);          /* always little endian */
1207
1208   return ret;
1209 }
1210
1211 int
1212 hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len,
1213              void *opaque, int flags)
1214 {
1215   return hivex_visit_node (h, hivex_root (h), visitor, len, opaque, flags);
1216 }
1217
1218 static int hivex__visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *vtor, char *unvisited, void *opaque, int flags);
1219
1220 int
1221 hivex_visit_node (hive_h *h, hive_node_h node,
1222                   const struct hivex_visitor *visitor, size_t len, void *opaque,
1223                   int flags)
1224 {
1225   struct hivex_visitor vtor;
1226   memset (&vtor, 0, sizeof vtor);
1227
1228   /* Note that len might be larger *or smaller* than the expected size. */
1229   size_t copysize = len <= sizeof vtor ? len : sizeof vtor;
1230   memcpy (&vtor, visitor, copysize);
1231
1232   /* This bitmap records unvisited nodes, so we don't loop if the
1233    * registry contains cycles.
1234    */
1235   char *unvisited = malloc (1 + h->size / 32);
1236   if (unvisited == NULL)
1237     return -1;
1238   memcpy (unvisited, h->bitmap, 1 + h->size / 32);
1239
1240   int r = hivex__visit_node (h, node, &vtor, unvisited, opaque, flags);
1241   free (unvisited);
1242   return r;
1243 }
1244
1245 static int
1246 hivex__visit_node (hive_h *h, hive_node_h node,
1247                    const struct hivex_visitor *vtor, char *unvisited,
1248                    void *opaque, int flags)
1249 {
1250   int skip_bad = flags & HIVEX_VISIT_SKIP_BAD;
1251   char *name = NULL;
1252   hive_value_h *values = NULL;
1253   hive_node_h *children = NULL;
1254   char *key = NULL;
1255   char *str = NULL;
1256   char **strs = NULL;
1257   int i;
1258
1259   /* Return -1 on all callback errors.  However on internal errors,
1260    * check if skip_bad is set and suppress those errors if so.
1261    */
1262   int ret = -1;
1263
1264   if (!BITMAP_TST (unvisited, node)) {
1265     if (h->msglvl >= 2)
1266       printf ("hivex__visit_node: contains cycle: visited node %zu already\n",
1267               node);
1268
1269     errno = ELOOP;
1270     return skip_bad ? 0 : -1;
1271   }
1272   BITMAP_CLR (unvisited, node);
1273
1274   name = hivex_node_name (h, node);
1275   if (!name) return skip_bad ? 0 : -1;
1276   if (vtor->node_start && vtor->node_start (h, opaque, node, name) == -1)
1277     goto error;
1278
1279   values = hivex_node_values (h, node);
1280   if (!values) {
1281     ret = skip_bad ? 0 : -1;
1282     goto error;
1283   }
1284
1285   for (i = 0; values[i] != 0; ++i) {
1286     hive_type t;
1287     size_t len;
1288
1289     if (hivex_value_type (h, values[i], &t, &len) == -1) {
1290       ret = skip_bad ? 0 : -1;
1291       goto error;
1292     }
1293
1294     key = hivex_value_key (h, values[i]);
1295     if (key == NULL) {
1296       ret = skip_bad ? 0 : -1;
1297       goto error;
1298     }
1299
1300     switch (t) {
1301     case hive_t_none:
1302       str = hivex_value_value (h, values[i], &t, &len);
1303       if (str == NULL) {
1304         ret = skip_bad ? 0 : -1;
1305         goto error;
1306       }
1307       if (t != hive_t_none) {
1308         ret = skip_bad ? 0 : -1;
1309         goto error;
1310       }
1311       if (vtor->value_none &&
1312           vtor->value_none (h, opaque, node, values[i], t, len, key, str) == -1)
1313         goto error;
1314       free (str); str = NULL;
1315       break;
1316
1317     case hive_t_string:
1318     case hive_t_expand_string:
1319     case hive_t_link:
1320       str = hivex_value_string (h, values[i]);
1321       if (str == NULL) {
1322         if (errno != EILSEQ && errno != EINVAL) {
1323           ret = skip_bad ? 0 : -1;
1324           goto error;
1325         }
1326         if (vtor->value_string_invalid_utf16) {
1327           str = hivex_value_value (h, values[i], &t, &len);
1328           if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1329             goto error;
1330           free (str); str = NULL;
1331         }
1332         break;
1333       }
1334       if (vtor->value_string &&
1335           vtor->value_string (h, opaque, node, values[i], t, len, key, str) == -1)
1336         goto error;
1337       free (str); str = NULL;
1338       break;
1339
1340     case hive_t_dword:
1341     case hive_t_dword_be: {
1342       int32_t i32 = hivex_value_dword (h, values[i]);
1343       if (vtor->value_dword &&
1344           vtor->value_dword (h, opaque, node, values[i], t, len, key, i32) == -1)
1345         goto error;
1346       break;
1347     }
1348
1349     case hive_t_qword: {
1350       int64_t i64 = hivex_value_qword (h, values[i]);
1351       if (vtor->value_qword &&
1352           vtor->value_qword (h, opaque, node, values[i], t, len, key, i64) == -1)
1353         goto error;
1354       break;
1355     }
1356
1357     case hive_t_binary:
1358       str = hivex_value_value (h, values[i], &t, &len);
1359       if (str == NULL) {
1360         ret = skip_bad ? 0 : -1;
1361         goto error;
1362       }
1363       if (t != hive_t_binary) {
1364         ret = skip_bad ? 0 : -1;
1365         goto error;
1366       }
1367       if (vtor->value_binary &&
1368           vtor->value_binary (h, opaque, node, values[i], t, len, key, str) == -1)
1369         goto error;
1370       free (str); str = NULL;
1371       break;
1372
1373     case hive_t_multiple_strings:
1374       strs = hivex_value_multiple_strings (h, values[i]);
1375       if (strs == NULL) {
1376         if (errno != EILSEQ && errno != EINVAL) {
1377           ret = skip_bad ? 0 : -1;
1378           goto error;
1379         }
1380         if (vtor->value_string_invalid_utf16) {
1381           str = hivex_value_value (h, values[i], &t, &len);
1382           if (vtor->value_string_invalid_utf16 (h, opaque, node, values[i], t, len, key, str) == -1)
1383             goto error;
1384           free (str); str = NULL;
1385         }
1386         break;
1387       }
1388       if (vtor->value_multiple_strings &&
1389           vtor->value_multiple_strings (h, opaque, node, values[i], t, len, key, strs) == -1)
1390         goto error;
1391       free_strings (strs); strs = NULL;
1392       break;
1393
1394     case hive_t_resource_list:
1395     case hive_t_full_resource_description:
1396     case hive_t_resource_requirements_list:
1397     default:
1398       str = hivex_value_value (h, values[i], &t, &len);
1399       if (str == NULL) {
1400         ret = skip_bad ? 0 : -1;
1401         goto error;
1402       }
1403       if (vtor->value_other &&
1404           vtor->value_other (h, opaque, node, values[i], t, len, key, str) == -1)
1405         goto error;
1406       free (str); str = NULL;
1407       break;
1408     }
1409
1410     free (key); key = NULL;
1411   }
1412
1413   children = hivex_node_children (h, node);
1414   if (children == NULL) {
1415     ret = skip_bad ? 0 : -1;
1416     goto error;
1417   }
1418
1419   for (i = 0; children[i] != 0; ++i) {
1420     if (h->msglvl >= 2)
1421       printf ("hivex__visit_node: %s: visiting subkey %d (%zu)\n",
1422               name, i, children[i]);
1423
1424     if (hivex__visit_node (h, children[i], vtor, unvisited, opaque, flags) == -1)
1425       goto error;
1426   }
1427
1428   if (vtor->node_end && vtor->node_end (h, opaque, node, name) == -1)
1429     goto error;
1430
1431   ret = 0;
1432
1433  error:
1434   free (name);
1435   free (values);
1436   free (children);
1437   free (key);
1438   free (str);
1439   free_strings (strs);
1440   return ret;
1441 }