source: trunk/src/reglookup.c @ 43

Last change on this file since 43 was 43, checked in by tim, 19 years ago

Fixed memory allocation and string issues in ACL code.

Fixed bug with filtered keys and value printing.

Cleaned up tree traversal routines.

  • Property svn:keywords set to Id
File size: 20.7 KB
Line 
1/*
2 * A utility to read a Windows NT/2K/XP/2K3 registry file, using
3 * Gerald Carter''s regfio interface.
4 *
5 * Copyright (C) 2005 Timothy D. Morgan
6 * Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
20 *
21 * $Id: reglookup.c 43 2005-08-06 00:47:37Z tim $
22 */
23
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28#include <strings.h>
29#include <time.h>
30#include "../include/regfio.h"
31#include "../include/void_stack.h"
32
33/* Globals, influenced by command line parameters */
34bool print_verbose = false;
35bool print_security = false;
36bool print_header = true;
37bool path_filter_enabled = false;
38bool type_filter_enabled = false;
39char* path_filter = NULL;
40int type_filter;
41char* registry_file = NULL;
42
43/* Other globals */
44const char* special_chars = ",\"\\";
45
46void bailOut(int code, char* message)
47{
48  fprintf(stderr, message);
49  exit(code);
50}
51
52
53/* Returns a newly malloc()ed string which contains original buffer,
54 * except for non-printable or special characters are quoted in hex
55 * with the syntax '\xQQ' where QQ is the hex ascii value of the quoted
56 * character.  A null terminator is added, as only ascii, not binary,
57 * is returned.
58 */
59static char* quote_buffer(const unsigned char* str, 
60                          unsigned int len, char* special)
61{
62  unsigned int i;
63  unsigned int num_written=0;
64  unsigned int out_len = sizeof(char)*len+1;
65  char* ret_val = malloc(out_len);
66
67  if(ret_val == NULL)
68    return NULL;
69
70  for(i=0; i<len; i++)
71  {
72    if(str[i] < 32 || str[i] > 126 || strchr(special, str[i]) != NULL)
73    {
74      out_len += 3;
75      /* XXX: may not be the most efficient way of getting enough memory. */
76      ret_val = realloc(ret_val, out_len);
77      if(ret_val == NULL)
78        break;
79      num_written += snprintf(ret_val+num_written, (out_len)-num_written,
80                              "\\x%.2X", str[i]);
81    }
82    else
83      ret_val[num_written++] = str[i];
84  }
85  ret_val[num_written] = '\0';
86
87  return ret_val;
88}
89
90
91/* Returns a newly malloc()ed string which contains original string,
92 * except for non-printable or special characters are quoted in hex
93 * with the syntax '\xQQ' where QQ is the hex ascii value of the quoted
94 * character.
95 */
96static char* quote_string(const char* str, char* special)
97{
98  unsigned int len;
99
100  if(str == NULL)
101    return NULL;
102
103  len = strlen(str);
104  return quote_buffer((const unsigned char*)str, len, special);
105}
106
107
108/*
109 * Convert from UniCode to Ascii ... Does not take into account other lang
110 * Restrict by ascii_max if > 0
111 */
112static int uni_to_ascii(unsigned char *uni, unsigned char *ascii, 
113                        int ascii_max, int uni_max)
114{
115  int i = 0; 
116
117  while (i < ascii_max && (uni[i*2] || uni[i*2+1]))
118  {
119    if (uni_max > 0 && (i*2) >= uni_max) break;
120    ascii[i] = uni[i*2];
121    i++;
122  }
123  ascii[i] = '\0';
124
125  return i;
126}
127
128
129/*
130 * Convert a data value to a string for display
131 */
132static unsigned char* data_to_ascii(unsigned char *datap, int len, int type)
133{
134  unsigned char *asciip;
135  unsigned int i;
136  unsigned short num_nulls;
137  unsigned char* ascii;
138  unsigned char* cur_str;
139  unsigned char* cur_ascii;
140  char* cur_quoted;
141  unsigned int cur_str_len;
142  unsigned int ascii_max, cur_str_max;
143  unsigned int str_rem, cur_str_rem, alen;
144
145  switch (type) 
146  {
147  case REG_SZ:
148    if (print_verbose)
149      fprintf(stderr, "Len: %d\n", len);
150   
151    ascii_max = sizeof(char)*len;
152    ascii = malloc(ascii_max+4);
153    if(ascii == NULL)
154      return NULL;
155   
156    /* XXX: This has to be fixed. It has to be UNICODE */
157    uni_to_ascii(datap, ascii, len, ascii_max);
158    cur_quoted = quote_string((char*)ascii, special_chars);
159    free(ascii);
160    return (unsigned char*)cur_quoted;
161    break;
162
163  case REG_EXPAND_SZ:
164    ascii_max = sizeof(char)*len;
165    ascii = malloc(ascii_max+2);
166    if(ascii == NULL)
167      return NULL;
168
169    uni_to_ascii(datap, ascii, len, ascii_max);
170    cur_quoted = quote_string((char*)ascii, special_chars);
171    free(ascii);
172    return (unsigned char*)cur_quoted;
173    break;
174
175  case REG_DWORD:
176    ascii_max = sizeof(char)*10;
177    ascii = malloc(ascii_max+1);
178    if(ascii == NULL)
179      return NULL;
180
181    if (*(int *)datap == 0)
182      snprintf((char*)ascii, ascii_max, "0");
183    else
184      snprintf((char*)ascii, ascii_max, "0x%x", *(int *)datap);
185    return ascii;
186    break;
187
188  /* XXX: this MULTI_SZ parser is pretty inefficient.  Should be
189   *      redone with fewer malloc and better string concatenation.
190   */
191  case REG_MULTI_SZ:
192    ascii_max = sizeof(char)*len*4;
193    cur_str_max = sizeof(char)*len+1;
194    cur_str = malloc(cur_str_max);
195    cur_ascii = malloc(cur_str_max);
196    ascii = malloc(ascii_max+4);
197    if(ascii == NULL || cur_str == NULL || cur_ascii == NULL)
198      return NULL;
199
200    /* Reads until it reaches 4 consecutive NULLs,
201     * which is two nulls in unicode, or until it reaches len, or until we
202     * run out of buffer.  The latter should never happen, but we shouldn't
203     * trust our file to have the right lengths/delimiters.
204     */
205    asciip = ascii;
206    num_nulls = 0;
207    str_rem = ascii_max;
208    cur_str_rem = cur_str_max;
209    cur_str_len = 0;
210
211    for(i=0; (i < len) && str_rem > 0; i++)
212    {
213      *(cur_str+cur_str_len) = *(datap+i);
214      if(*(cur_str+cur_str_len) == 0)
215        num_nulls++;
216      else
217        num_nulls = 0;
218      cur_str_len++;
219
220      if(num_nulls == 2)
221      {
222        uni_to_ascii(cur_str, cur_ascii, cur_str_max, 0);
223        cur_quoted = quote_string((char*)cur_ascii, ",|\"\\");
224        alen = snprintf((char*)asciip, str_rem, "%s", cur_quoted);
225        asciip += alen;
226        str_rem -= alen;
227        free(cur_quoted);
228
229        if(*(datap+i+1) == 0 && *(datap+i+2) == 0)
230          break;
231        else
232        {
233          alen = snprintf((char*)asciip, str_rem, "%c", '|');
234          asciip += alen;
235          str_rem -= alen;
236          memset(cur_str, 0, cur_str_max);
237          cur_str_len = 0;
238          num_nulls = 0;
239          /* To eliminate leading nulls in subsequent strings. */
240          i++;
241        }
242      }
243    }
244    *asciip = 0;
245    free(cur_str);
246    free(cur_ascii);
247    return ascii;
248    break;
249
250  /* XXX: Dont know what to do with these yet, just print as binary... */
251  case REG_RESOURCE_LIST:
252  case REG_FULL_RESOURCE_DESCRIPTOR:
253  case REG_RESOURCE_REQUIREMENTS_LIST:
254
255  case REG_BINARY:
256    return (unsigned char*)quote_buffer(datap, len, special_chars);
257    break;
258
259  default:
260    return NULL;
261    break;
262  } 
263
264  return NULL;
265}
266
267
268/* Security descriptor print functions  */
269/* XXX: these functions should be moved out into regfio library */
270const char* ace_type2str(uint8 type)
271{
272  static const char* map[7] 
273    = {"ALLOW", "DENY", "AUDIT", "ALARM", 
274       "ALLOW CPD", "OBJ ALLOW", "OBJ DENY"};
275  if(type < 7)
276    return map[type];
277  else
278    return "UNKNOWN";
279}
280
281
282char* ace_flags2str(uint8 flags)
283{
284  char* flg_output = malloc(21*sizeof(char));
285  int some = 0;
286
287  if(flg_output == NULL)
288    return NULL;
289
290  flg_output[0] = '\0';
291  if (!flags)
292    return flg_output;
293
294  if (flags & 0x01) {
295    if (some) strcat(flg_output, " ");
296    some = 1;
297    strcat(flg_output, "OI");
298  }
299  if (flags & 0x02) {
300    if (some) strcat(flg_output, " ");
301    some = 1;
302    strcat(flg_output, "CI");
303  }
304  if (flags & 0x04) {
305    if (some) strcat(flg_output, " ");
306    some = 1;
307    strcat(flg_output, "NP");
308  }
309  if (flags & 0x08) {
310    if (some) strcat(flg_output, " ");
311    some = 1;
312    strcat(flg_output, "IO");
313  }
314  if (flags & 0x10) {
315    if (some) strcat(flg_output, " ");
316    some = 1;
317    strcat(flg_output, "IA");
318  }
319  if (flags == 0xF) {
320    if (some) strcat(flg_output, " ");
321    some = 1;
322    strcat(flg_output, "VI");
323  }
324
325  return flg_output;
326}
327
328
329char* ace_perms2str(uint32 perms)
330{
331  char* ret_val = malloc(9*sizeof(char));
332  sprintf(ret_val, "%.8X", perms);
333
334  return ret_val;
335}
336
337
338char* sid2str(DOM_SID* sid)
339{
340  uint32 i, size = MAXSUBAUTHS*11 + 24;
341  uint32 left = size;
342  uint8 comps = sid->num_auths;
343  char* ret_val = malloc(size);
344 
345  if(ret_val == NULL)
346    return NULL;
347
348  if(comps > MAXSUBAUTHS)
349    comps = MAXSUBAUTHS;
350
351  left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
352
353  for (i = 0; i < comps; i++) 
354    left -= snprintf(ret_val+(size-left), left, "-%u", sid->sub_auths[i]);
355
356  return ret_val;
357}
358
359
360char* get_acl(SEC_ACL* acl)
361{
362  uint32 i, extra, size = 0;
363  const char* type_str;
364  char* flags_str;
365  char* perms_str;
366  char* sid_str;
367  char* ret_val = NULL;
368  char* ace_delim = "";
369  char field_delim = ':';
370
371printf("acl: %.8X\n", (uint32)acl);
372
373  for (i = 0; i < acl->num_aces; i++)
374  {
375    /* XXX: check for NULL */
376    sid_str = sid2str(&acl->ace[i].trustee);
377    type_str = ace_type2str(acl->ace[i].type);
378    perms_str = ace_perms2str(acl->ace[i].info.mask);
379    flags_str = ace_flags2str(acl->ace[i].flags);
380
381    /* XXX: this is slow */
382    extra = strlen(sid_str) + strlen(type_str) 
383          + strlen(perms_str) + strlen(flags_str)+5;
384    ret_val = realloc(ret_val, size+extra);
385    if(ret_val == NULL)
386      return NULL;
387    size += snprintf(ret_val+size, extra, "%s%s%c%s%c%s%c%s",
388                     ace_delim,sid_str,
389                     field_delim,type_str,
390                     field_delim,perms_str,
391                     field_delim,flags_str);
392    ace_delim = "|";
393    free(sid_str);
394    free(perms_str);
395    free(flags_str);
396  }
397
398  return ret_val;
399}
400
401
402char* get_sacl(SEC_DESC *sec_desc)
403{
404  if (sec_desc->sacl)
405    return get_acl(sec_desc->sacl);
406  else
407    return NULL;
408}
409
410
411char* get_dacl(SEC_DESC *sec_desc)
412{
413  if (sec_desc->dacl)
414    return get_acl(sec_desc->dacl);
415  else
416    return NULL;
417}
418
419
420char* get_owner(SEC_DESC *sec_desc)
421{
422  return sid2str(sec_desc->owner_sid);
423}
424
425
426char* get_group(SEC_DESC *sec_desc)
427{
428  return sid2str(sec_desc->grp_sid);
429}
430
431
432void_stack* path2Stack(const char* s)
433{
434  void_stack* ret_val;
435  void_stack* rev_ret = void_stack_new(1024);
436  const char* cur = s;
437  char* next = NULL;
438  char* copy;
439
440  if (rev_ret == NULL)
441    return NULL;
442  if (s == NULL)
443    return rev_ret;
444 
445  while((next = strchr(cur, '/')) != NULL)
446  {
447    if ((next-cur) > 0)
448    {
449      copy = (char*)malloc((next-cur+1)*sizeof(char));
450      if(copy == NULL)
451        bailOut(2, "ERROR: Memory allocation problem.\n");
452         
453      memcpy(copy, cur, next-cur);
454      copy[next-cur] = '\0';
455      void_stack_push(rev_ret, copy);
456    }
457    cur = next+1;
458  }
459  if(strlen(cur) > 0)
460  {
461    copy = strdup(cur);
462    void_stack_push(rev_ret, copy);
463  }
464
465  ret_val = void_stack_copy_reverse(rev_ret);
466  void_stack_destroy(rev_ret);
467
468  return ret_val;
469}
470
471
472char* stack2Path(void_stack* nk_stack)
473{
474  const REGF_NK_REC* cur;
475  uint32 buf_left = 127;
476  uint32 buf_len = buf_left+1;
477  uint32 name_len = 0;
478  uint32 grow_amt;
479  char* buf; 
480  char* new_buf;
481  void_stack_iterator* iter;
482 
483  buf = (char*)malloc((buf_len)*sizeof(char));
484  if (buf == NULL)
485    return NULL;
486  buf[0] = '/';
487  buf[1] = '\0';
488
489  iter = void_stack_iterator_new(nk_stack);
490  if (iter == NULL)
491  {
492    free(buf);
493    return NULL;
494  }
495
496  /* skip root element */
497  cur = void_stack_iterator_next(iter);
498
499  while((cur = void_stack_iterator_next(iter)) != NULL)
500  {
501    buf[buf_len-buf_left-1] = '/';
502    buf_left -= 1;
503    name_len = strlen(cur->keyname);
504    if(name_len+1 > buf_left)
505    {
506      grow_amt = (uint32)(buf_len/2);
507      buf_len += name_len+1+grow_amt-buf_left;
508      if((new_buf = realloc(buf, buf_len)) == NULL)
509      {
510        free(buf);
511        free(iter);
512        return NULL;
513      }
514      buf = new_buf;
515      buf_left = grow_amt + name_len + 1;
516    }
517    strncpy(buf+(buf_len-buf_left-1), cur->keyname, name_len);
518    buf_left -= name_len;
519    buf[buf_len-buf_left-1] = '\0';
520  }
521
522  return buf;
523}
524
525
526void printValue(REGF_VK_REC* vk, char* prefix)
527{
528  uint32 size;
529  uint8 tmp_buf[4];
530  unsigned char* quoted_value;
531  char* quoted_prefix;
532  char* quoted_name;
533
534  /* Thanks Microsoft for making this process so straight-forward!!! */
535  size = (vk->data_size & ~VK_DATA_IN_OFFSET);
536  if(vk->data_size & VK_DATA_IN_OFFSET)
537  {
538    tmp_buf[0] = (uint8)((vk->data_off >> 3) & 0xFF);
539    tmp_buf[1] = (uint8)((vk->data_off >> 2) & 0xFF);
540    tmp_buf[2] = (uint8)((vk->data_off >> 1) & 0xFF);
541    tmp_buf[3] = (uint8)(vk->data_off & 0xFF);
542    if(size > 4)
543      size = 4;
544    quoted_value = data_to_ascii(tmp_buf, 4, vk->type);
545  }
546  else
547  {
548    /* XXX: This is a safety hack.  No data fields have yet been found
549     * larger, but length limits are probably better got from fields
550     * in the registry itself, within reason.
551     */
552    if(size > 16384)
553    {
554      fprintf(stderr, "WARNING: key size %d larger than "
555              "16384, truncating...\n", size);
556      size = 16384;
557    }
558    quoted_value = data_to_ascii(vk->data, vk->data_size, vk->type);
559  }
560 
561  /* XXX: Sometimes value names can be NULL in registry.  Need to
562   *      figure out why and when, and generate the appropriate output
563   *      for that condition.
564   */
565  quoted_prefix = quote_string(prefix, special_chars);
566  quoted_name = quote_string(vk->valuename, special_chars);
567 
568  if(print_security)
569    printf("%s/%s,%s,%s,,,,,\n", quoted_prefix, quoted_name,
570           regfio_type_val2str(vk->type), quoted_value);
571  else
572    printf("%s/%s,%s,%s,\n", quoted_prefix, quoted_name,
573           regfio_type_val2str(vk->type), quoted_value);
574 
575  if(quoted_value != NULL)
576    free(quoted_value);
577  if(quoted_prefix != NULL)
578    free(quoted_prefix);
579  if(quoted_name != NULL)
580    free(quoted_name);
581}
582
583
584void printValueList(REGF_NK_REC* nk, char* prefix)
585{
586  uint32 i;
587 
588  for(i=0; i < nk->num_values; i++)
589    if(!type_filter_enabled || (nk->values[i].type == type_filter))
590      printValue(&nk->values[i], prefix);
591}
592
593
594void printKey(REGF_NK_REC* k, char* full_path)
595{
596  static char empty_str[1] = "";
597  char* owner = NULL;
598  char* group = NULL;
599  char* sacl = NULL;
600  char* dacl = NULL;
601  char mtime[20];
602  time_t tmp_time[1];
603  struct tm* tmp_time_s = NULL;
604
605  *tmp_time = nt_time_to_unix(&k->mtime);
606  tmp_time_s = gmtime(tmp_time);
607  strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
608
609  if(print_security)
610  {
611    owner = get_owner(k->sec_desc->sec_desc);
612    group = get_group(k->sec_desc->sec_desc);
613    sacl = get_sacl(k->sec_desc->sec_desc);
614    dacl = get_dacl(k->sec_desc->sec_desc);
615    if(owner == NULL)
616      owner = empty_str;
617    if(group == NULL)
618      group = empty_str;
619    if(sacl == NULL)
620      sacl = empty_str;
621    if(dacl == NULL)
622      dacl = empty_str;
623
624    printf("%s,KEY,,%s,%s,%s,%s,%s\n", full_path, mtime, 
625           owner, group, sacl, dacl);
626
627    if(owner != empty_str)
628      free(owner);
629    if(group != empty_str)
630      free(group);
631    if(sacl != empty_str)
632      free(sacl);
633    if(dacl != empty_str)
634      free(dacl);
635  }
636  else
637    printf("%s,KEY,,%s\n", full_path, mtime);
638}
639
640
641/* XXX: this function is god-awful.  Needs to be re-designed. */
642void printKeyTree(REGF_FILE* f, void_stack* nk_stack, char* prefix)
643{
644  REGF_NK_REC* cur;
645  REGF_NK_REC* sub;
646  char* path = NULL;
647  char* val_path = NULL;
648
649  int key_type = regfio_type_str2val("KEY");
650 
651  if((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
652  {
653    cur->subkey_index = 0;
654    path = stack2Path(nk_stack);
655   
656
657    val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
658    sprintf(val_path, "%s%s", prefix, path);
659    if(!type_filter_enabled || (key_type == type_filter))
660      printKey(cur, val_path);
661
662    if(!type_filter_enabled || (key_type != type_filter))
663      printValueList(cur, val_path);
664    if(val_path != NULL)
665      free(val_path);
666    while((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
667    {
668      if((sub = regfio_fetch_subkey(f, cur)) != NULL)
669      {
670        sub->subkey_index = 0;
671        void_stack_push(nk_stack, sub);
672        path = stack2Path(nk_stack);
673        if(path != NULL)
674        {
675          val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
676          sprintf(val_path, "%s%s", prefix, path);
677          if(!type_filter_enabled || (key_type == type_filter))
678            printKey(sub, val_path);
679          if(!type_filter_enabled || (key_type != type_filter))
680            printValueList(sub, val_path);
681          if(val_path != NULL)
682            free(val_path);
683        }
684      }
685      else
686      {
687        cur = void_stack_pop(nk_stack);
688        /* XXX: This is just a shallow free.  Need to write deep free
689         * routines to replace the Samba code for this.
690         */ 
691        if(cur != NULL)
692          free(cur);
693      }
694    }
695  }
696}
697
698
699/*
700 * Returns 0 if path was found.
701 * Returns 1 if path was not found.
702 * Returns less than 0 on other error.
703 */
704int retrievePath(REGF_FILE* f, void_stack* nk_stack,
705                 void_stack* path_stack)
706{
707  REGF_NK_REC* sub; 
708  REGF_NK_REC* cur;
709  void_stack* sub_nk_stack;
710  char* prefix;
711  char* cur_str = NULL;
712  bool found_cur = true;
713  uint32 i;
714  uint16 path_depth;
715  if(path_stack == NULL)
716    return -1;
717
718  path_depth = void_stack_size(path_stack);
719  if(path_depth < 1)
720    return -2;
721
722  if(void_stack_size(nk_stack) < 1)
723    return -3;
724  cur = (REGF_NK_REC*)void_stack_cur(nk_stack);
725
726  while(void_stack_size(path_stack) > 1)
727  {
728    /* Search key records only */
729    cur_str = (char*)void_stack_pop(path_stack);
730
731    found_cur = false;
732    while(!found_cur &&
733          (sub = regfio_fetch_subkey(f, cur)) != NULL)
734    {
735      if(strcasecmp(sub->keyname, cur_str) == 0)
736      {
737        cur = sub;
738        void_stack_push(nk_stack, sub);
739        found_cur = true;
740      }
741    }
742    free(cur_str);
743
744    if(!found_cur)
745      return 1;
746  }
747
748  /* Last round, search value and key records */
749  cur_str = (char*)void_stack_pop(path_stack);
750
751  for(i=0; (i < cur->num_values); i++)
752  {
753    if(strcasecmp(sub->values[i].valuename, cur_str) == 0)
754    {
755      /* XXX: fix mem leak with stack2Path return value */
756      printValue(&sub->values[i], stack2Path(nk_stack));
757      return 0;
758    }
759  }
760
761  while((sub = regfio_fetch_subkey(f, cur)) != NULL)
762  {
763    if(strcasecmp(sub->keyname, cur_str) == 0)
764    {
765      sub_nk_stack = void_stack_new(1024);
766      void_stack_push(sub_nk_stack, sub);
767      void_stack_push(nk_stack, sub);
768      prefix = stack2Path(nk_stack);
769      printKeyTree(f, sub_nk_stack, prefix);
770      return 0;
771    }
772  }
773
774  return 1;
775}
776
777
778static void usage(void)
779{
780  fprintf(stderr, "Usage: readreg [-v] [-s]"
781          " [-p <PATH_FILTER>] [-t <TYPE_FILTER>]"
782          " <REGISTRY_FILE>\n");
783  /* XXX: replace version string with Subversion property? */
784  fprintf(stderr, "Version: 0.2\n");
785  fprintf(stderr, "Options:\n");
786  fprintf(stderr, "\t-v\t sets verbose mode.\n");
787  fprintf(stderr, "\t-s\t prints security descriptors.\n");
788  fprintf(stderr, "\t-p\t restrict output to elements below this path.\n");
789  fprintf(stderr, "\t-t\t restrict results to this specific data type.\n");
790  fprintf(stderr, "\n");
791}
792
793
794int main(int argc, char** argv)
795{
796  void_stack* nk_stack;
797  void_stack* path_stack;
798  REGF_FILE* f;
799  REGF_NK_REC* root;
800  int retr_path_ret;
801  uint32 argi;
802
803  /* Process command line arguments */
804  if(argc < 2)
805  {
806    usage();
807    bailOut(1, "ERROR: Requires 1 argument.\n");
808  }
809 
810  for(argi = 1; argi < argc; argi++)
811  {
812    if (strcmp("-p", argv[argi]) == 0)
813    {
814      if(++argi > argc)
815      {
816        usage();
817        bailOut(1, "ERROR: '-p' option requires parameter.\n");
818      }
819      if((path_filter = strdup(argv[argi])) == NULL)
820        bailOut(2, "ERROR: Memory allocation problem.\n");
821
822      path_filter_enabled = true;
823    }
824    else if (strcmp("-t", argv[argi]) == 0)
825    {
826      if(++argi > argc)
827      {
828        usage();
829        bailOut(1, "ERROR: '-t' option requires parameter.\n");
830      }
831      if((type_filter = regfio_type_str2val(argv[argi])) == 0)
832      {
833        fprintf(stderr, "ERROR: Invalid type specified: %s.\n", argv[argi]);
834        bailOut(1, "");
835      }
836
837      type_filter_enabled = true;
838    }
839    else if (strcmp("-s", argv[argi]) == 0)
840      print_security = true;
841    else if (strcmp("-v", argv[argi]) == 0)
842      print_verbose = true;
843    else if (argv[argi][0] == '-')
844    {
845      usage();
846      fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
847      bailOut(1, "");
848    }
849    else
850    {
851      if((registry_file = strdup(argv[argi])) == NULL)
852        bailOut(2, "ERROR: Memory allocation problem.\n");
853    }
854  }
855
856  f = regfio_open(registry_file);
857  if(f == NULL)
858  {
859    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
860    bailOut(3, "");
861  }
862
863  root = regfio_rootkey(f);
864  nk_stack = void_stack_new(1024);
865
866  if(void_stack_push(nk_stack, root))
867  {
868    if(print_header)
869    {
870      if(print_security)
871        printf("PATH,TYPE,VALUE,MTIME,OWNER,GROUP,SACL,DACL\n");
872      else
873        printf("PATH,TYPE,VALUE,MTIME\n");
874    }
875
876    path_stack = path2Stack(path_filter);
877    if(void_stack_size(path_stack) < 1)
878      printKeyTree(f, nk_stack, "");
879    else
880    {
881      retr_path_ret = retrievePath(f, nk_stack, path_stack);
882      if(retr_path_ret == 1)
883        fprintf(stderr, "WARNING: specified path not found.\n");
884      else if(retr_path_ret != 0)
885        bailOut(4, "ERROR:\n");
886    }
887  }
888  else
889    bailOut(2, "ERROR: Memory allocation problem.\n");
890
891  void_stack_destroy_deep(nk_stack);
892  regfio_close(f);
893
894  return 0;
895}
Note: See TracBrowser for help on using the repository browser.