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