source: releases/0.2/src/reglookup.c@ 286

Last change on this file since 286 was 48, checked in by tim, 20 years ago

fixed segfault when valuenames are NULL

  • Property svn:keywords set to Id
File size: 21.2 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 48 2005-08-06 22:05:18Z 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, const 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, const 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
371 for (i = 0; i < acl->num_aces; i++)
372 {
373 /* XXX: check for NULL */
374 sid_str = sid2str(&acl->ace[i].trustee);
375 type_str = ace_type2str(acl->ace[i].type);
376 perms_str = ace_perms2str(acl->ace[i].info.mask);
377 flags_str = ace_flags2str(acl->ace[i].flags);
378
379 /* XXX: this is slow */
380 extra = strlen(sid_str) + strlen(type_str)
381 + strlen(perms_str) + strlen(flags_str)+5;
382 ret_val = realloc(ret_val, size+extra);
383 if(ret_val == NULL)
384 return NULL;
385 size += snprintf(ret_val+size, extra, "%s%s%c%s%c%s%c%s",
386 ace_delim,sid_str,
387 field_delim,type_str,
388 field_delim,perms_str,
389 field_delim,flags_str);
390 ace_delim = "|";
391 free(sid_str);
392 free(perms_str);
393 free(flags_str);
394 }
395
396 return ret_val;
397}
398
399
400char* get_sacl(SEC_DESC *sec_desc)
401{
402 if (sec_desc->sacl)
403 return get_acl(sec_desc->sacl);
404 else
405 return NULL;
406}
407
408
409char* get_dacl(SEC_DESC *sec_desc)
410{
411 if (sec_desc->dacl)
412 return get_acl(sec_desc->dacl);
413 else
414 return NULL;
415}
416
417
418char* get_owner(SEC_DESC *sec_desc)
419{
420 return sid2str(sec_desc->owner_sid);
421}
422
423
424char* get_group(SEC_DESC *sec_desc)
425{
426 return sid2str(sec_desc->grp_sid);
427}
428
429
430void_stack* path2Stack(const char* s)
431{
432 void_stack* ret_val;
433 void_stack* rev_ret = void_stack_new(1024);
434 const char* cur = s;
435 char* next = NULL;
436 char* copy;
437
438 if (rev_ret == NULL)
439 return NULL;
440 if (s == NULL)
441 return rev_ret;
442
443 while((next = strchr(cur, '/')) != NULL)
444 {
445 if ((next-cur) > 0)
446 {
447 copy = (char*)malloc((next-cur+1)*sizeof(char));
448 if(copy == NULL)
449 bailOut(2, "ERROR: Memory allocation problem.\n");
450
451 memcpy(copy, cur, next-cur);
452 copy[next-cur] = '\0';
453 void_stack_push(rev_ret, copy);
454 }
455 cur = next+1;
456 }
457 if(strlen(cur) > 0)
458 {
459 copy = strdup(cur);
460 void_stack_push(rev_ret, copy);
461 }
462
463 ret_val = void_stack_copy_reverse(rev_ret);
464 void_stack_destroy(rev_ret);
465
466 return ret_val;
467}
468
469
470char* stack2Path(void_stack* nk_stack)
471{
472 const REGF_NK_REC* cur;
473 uint32 buf_left = 127;
474 uint32 buf_len = buf_left+1;
475 uint32 name_len = 0;
476 uint32 grow_amt;
477 char* buf;
478 char* new_buf;
479 void_stack_iterator* iter;
480
481 buf = (char*)malloc((buf_len)*sizeof(char));
482 if (buf == NULL)
483 return NULL;
484 buf[0] = '/';
485 buf[1] = '\0';
486
487 iter = void_stack_iterator_new(nk_stack);
488 if (iter == NULL)
489 {
490 free(buf);
491 return NULL;
492 }
493
494 /* skip root element */
495 cur = void_stack_iterator_next(iter);
496
497 while((cur = void_stack_iterator_next(iter)) != NULL)
498 {
499 buf[buf_len-buf_left-1] = '/';
500 buf_left -= 1;
501 name_len = strlen(cur->keyname);
502 if(name_len+1 > buf_left)
503 {
504 grow_amt = (uint32)(buf_len/2);
505 buf_len += name_len+1+grow_amt-buf_left;
506 if((new_buf = realloc(buf, buf_len)) == NULL)
507 {
508 free(buf);
509 free(iter);
510 return NULL;
511 }
512 buf = new_buf;
513 buf_left = grow_amt + name_len + 1;
514 }
515 strncpy(buf+(buf_len-buf_left-1), cur->keyname, name_len);
516 buf_left -= name_len;
517 buf[buf_len-buf_left-1] = '\0';
518 }
519
520 return buf;
521}
522
523
524void printValue(REGF_VK_REC* vk, char* prefix)
525{
526 uint32 size;
527 uint8 tmp_buf[4];
528 unsigned char* quoted_value;
529 char* quoted_prefix;
530 char* quoted_name;
531
532 /* Thanks Microsoft for making this process so straight-forward!!! */
533 size = (vk->data_size & ~VK_DATA_IN_OFFSET);
534 if(vk->data_size & VK_DATA_IN_OFFSET)
535 {
536 tmp_buf[0] = (uint8)((vk->data_off >> 3) & 0xFF);
537 tmp_buf[1] = (uint8)((vk->data_off >> 2) & 0xFF);
538 tmp_buf[2] = (uint8)((vk->data_off >> 1) & 0xFF);
539 tmp_buf[3] = (uint8)(vk->data_off & 0xFF);
540 if(size > 4)
541 size = 4;
542 quoted_value = data_to_ascii(tmp_buf, 4, vk->type);
543 }
544 else
545 {
546 /* XXX: This is a safety hack. No data fields have yet been found
547 * larger, but length limits are probably better got from fields
548 * in the registry itself, within reason.
549 */
550 if(size > 16384)
551 {
552 fprintf(stderr, "WARNING: key size %d larger than "
553 "16384, truncating...\n", size);
554 size = 16384;
555 }
556 quoted_value = data_to_ascii(vk->data, vk->data_size, vk->type);
557 }
558
559 /* XXX: Sometimes value names can be NULL in registry. Need to
560 * figure out why and when, and generate the appropriate output
561 * for that condition.
562 */
563 quoted_prefix = quote_string(prefix, special_chars);
564 quoted_name = quote_string(vk->valuename, special_chars);
565
566 if(print_security)
567 printf("%s/%s,%s,%s,,,,,\n", quoted_prefix, quoted_name,
568 regfio_type_val2str(vk->type), quoted_value);
569 else
570 printf("%s/%s,%s,%s,\n", quoted_prefix, quoted_name,
571 regfio_type_val2str(vk->type), quoted_value);
572
573 if(quoted_value != NULL)
574 free(quoted_value);
575 if(quoted_prefix != NULL)
576 free(quoted_prefix);
577 if(quoted_name != NULL)
578 free(quoted_name);
579}
580
581
582void printValueList(REGF_NK_REC* nk, char* prefix)
583{
584 uint32 i;
585
586 for(i=0; i < nk->num_values; i++)
587 if(!type_filter_enabled || (nk->values[i].type == type_filter))
588 printValue(&nk->values[i], prefix);
589}
590
591
592void printKey(REGF_NK_REC* k, char* full_path)
593{
594 static char empty_str[1] = "";
595 char* owner = NULL;
596 char* group = NULL;
597 char* sacl = NULL;
598 char* dacl = NULL;
599 char mtime[20];
600 time_t tmp_time[1];
601 struct tm* tmp_time_s = NULL;
602
603 *tmp_time = nt_time_to_unix(&k->mtime);
604 tmp_time_s = gmtime(tmp_time);
605 strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", tmp_time_s);
606
607 if(print_security)
608 {
609 owner = get_owner(k->sec_desc->sec_desc);
610 group = get_group(k->sec_desc->sec_desc);
611 sacl = get_sacl(k->sec_desc->sec_desc);
612 dacl = get_dacl(k->sec_desc->sec_desc);
613 if(owner == NULL)
614 owner = empty_str;
615 if(group == NULL)
616 group = empty_str;
617 if(sacl == NULL)
618 sacl = empty_str;
619 if(dacl == NULL)
620 dacl = empty_str;
621
622 printf("%s,KEY,,%s,%s,%s,%s,%s\n", full_path, mtime,
623 owner, group, sacl, dacl);
624
625 if(owner != empty_str)
626 free(owner);
627 if(group != empty_str)
628 free(group);
629 if(sacl != empty_str)
630 free(sacl);
631 if(dacl != empty_str)
632 free(dacl);
633 }
634 else
635 printf("%s,KEY,,%s\n", full_path, mtime);
636}
637
638
639/* XXX: this function is god-awful. Needs to be re-designed. */
640void printKeyTree(REGF_FILE* f, void_stack* nk_stack, char* prefix)
641{
642 REGF_NK_REC* cur;
643 REGF_NK_REC* sub;
644 char* path = NULL;
645 char* val_path = NULL;
646
647 int key_type = regfio_type_str2val("KEY");
648
649 if((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
650 {
651 cur->subkey_index = 0;
652 path = stack2Path(nk_stack);
653
654
655 val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
656 sprintf(val_path, "%s%s", prefix, path);
657 if(!type_filter_enabled || (key_type == type_filter))
658 printKey(cur, val_path);
659
660 if(!type_filter_enabled || (key_type != type_filter))
661 printValueList(cur, val_path);
662 if(val_path != NULL)
663 free(val_path);
664 while((cur = (REGF_NK_REC*)void_stack_cur(nk_stack)) != NULL)
665 {
666 if((sub = regfio_fetch_subkey(f, cur)) != NULL)
667 {
668 sub->subkey_index = 0;
669 void_stack_push(nk_stack, sub);
670 path = stack2Path(nk_stack);
671 if(path != NULL)
672 {
673 val_path = (char*)malloc(strlen(prefix)+strlen(path)+1);
674 sprintf(val_path, "%s%s", prefix, path);
675 if(!type_filter_enabled || (key_type == type_filter))
676 printKey(sub, val_path);
677 if(!type_filter_enabled || (key_type != type_filter))
678 printValueList(sub, val_path);
679 if(val_path != NULL)
680 free(val_path);
681 }
682 }
683 else
684 {
685 cur = void_stack_pop(nk_stack);
686 /* XXX: This is just a shallow free. Need to write deep free
687 * routines to replace the Samba code for this.
688 */
689 if(cur != NULL)
690 free(cur);
691 }
692 }
693 }
694}
695
696
697/*
698 * Returns 0 if path was found.
699 * Returns 1 if path was not found.
700 * Returns less than 0 on other error.
701 */
702int retrievePath(REGF_FILE* f, void_stack* nk_stack,
703 void_stack* path_stack)
704{
705 REGF_NK_REC* sub;
706 REGF_NK_REC* cur;
707 void_stack* sub_nk_stack;
708 char* prefix;
709 char* cur_str = NULL;
710 bool found_cur = true;
711 uint32 i;
712 uint16 path_depth;
713 if(path_stack == NULL)
714 return -1;
715
716 path_depth = void_stack_size(path_stack);
717 if(path_depth < 1)
718 return -2;
719
720 if(void_stack_size(nk_stack) < 1)
721 return -3;
722 cur = (REGF_NK_REC*)void_stack_cur(nk_stack);
723
724 while(void_stack_size(path_stack) > 1)
725 {
726 /* Search key records only */
727 cur_str = (char*)void_stack_pop(path_stack);
728
729 found_cur = false;
730 while(!found_cur &&
731 (sub = regfio_fetch_subkey(f, cur)) != NULL)
732 {
733 if(strcasecmp(sub->keyname, cur_str) == 0)
734 {
735 cur = sub;
736 void_stack_push(nk_stack, sub);
737 found_cur = true;
738 }
739 }
740 free(cur_str);
741
742 if(!found_cur)
743 return 1;
744 }
745
746 /* Last round, search value and key records */
747 cur_str = (char*)void_stack_pop(path_stack);
748
749 for(i=0; (i < cur->num_values); i++)
750 {
751 /* XXX: Not sure when/why this can be NULL, but it's happened. */
752 if(sub->values[i].valuename != NULL
753 && 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-h\t enables header row. (default)\n");
788 fprintf(stderr, "\t-H\t disables header row.\n");
789 fprintf(stderr, "\t-s\t enables security descriptor output.\n");
790 fprintf(stderr, "\t-S\t disables security descriptor output. (default)\n");
791 fprintf(stderr, "\t-p\t restrict output to elements below this path.\n");
792 fprintf(stderr, "\t-t\t restrict results to this specific data type.\n");
793 fprintf(stderr, "\n");
794}
795
796
797int main(int argc, char** argv)
798{
799 void_stack* nk_stack;
800 void_stack* path_stack;
801 REGF_FILE* f;
802 REGF_NK_REC* root;
803 int retr_path_ret;
804 uint32 argi, arge;
805
806 /* Process command line arguments */
807 if(argc < 2)
808 {
809 usage();
810 bailOut(1, "ERROR: Requires at least one argument.\n");
811 }
812
813 arge = argc-1;
814 for(argi = 1; argi < arge; argi++)
815 {
816 if (strcmp("-p", argv[argi]) == 0)
817 {
818 if(++argi >= arge)
819 {
820 usage();
821 bailOut(1, "ERROR: '-p' option requires parameter.\n");
822 }
823 if((path_filter = strdup(argv[argi])) == NULL)
824 bailOut(2, "ERROR: Memory allocation problem.\n");
825
826 path_filter_enabled = true;
827 }
828 else if (strcmp("-t", argv[argi]) == 0)
829 {
830 if(++argi >= arge)
831 {
832 usage();
833 bailOut(1, "ERROR: '-t' option requires parameter.\n");
834 }
835 if((type_filter = regfio_type_str2val(argv[argi])) == 0)
836 {
837 fprintf(stderr, "ERROR: Invalid type specified: %s.\n", argv[argi]);
838 bailOut(1, "");
839 }
840
841 type_filter_enabled = true;
842 }
843 else if (strcmp("-h", argv[argi]) == 0)
844 print_header = true;
845 else if (strcmp("-H", argv[argi]) == 0)
846 print_header = false;
847 else if (strcmp("-s", argv[argi]) == 0)
848 print_security = true;
849 else if (strcmp("-S", argv[argi]) == 0)
850 print_security = false;
851 else if (strcmp("-v", argv[argi]) == 0)
852 print_verbose = true;
853 else
854 {
855 usage();
856 fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
857 bailOut(1, "");
858 }
859 }
860 if((registry_file = strdup(argv[argi])) == NULL)
861 bailOut(2, "ERROR: Memory allocation problem.\n");
862
863 f = regfio_open(registry_file);
864 if(f == NULL)
865 {
866 fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
867 bailOut(3, "");
868 }
869
870 root = regfio_rootkey(f);
871 nk_stack = void_stack_new(1024);
872
873 if(void_stack_push(nk_stack, root))
874 {
875 if(print_header)
876 {
877 if(print_security)
878 printf("PATH,TYPE,VALUE,MTIME,OWNER,GROUP,SACL,DACL\n");
879 else
880 printf("PATH,TYPE,VALUE,MTIME\n");
881 }
882
883 path_stack = path2Stack(path_filter);
884 if(void_stack_size(path_stack) < 1)
885 printKeyTree(f, nk_stack, "");
886 else
887 {
888 retr_path_ret = retrievePath(f, nk_stack, path_stack);
889 if(retr_path_ret == 1)
890 fprintf(stderr, "WARNING: specified path not found.\n");
891 else if(retr_path_ret != 0)
892 bailOut(4, "ERROR:\n");
893 }
894 }
895 else
896 bailOut(2, "ERROR: Memory allocation problem.\n");
897
898 void_stack_destroy_deep(nk_stack);
899 regfio_close(f);
900
901 return 0;
902}
Note: See TracBrowser for help on using the repository browser.