source: trunk/src/sh_registry.c@ 350

Last change on this file since 350 was 335, checked in by katerina, 14 years ago

Module cleanup/thread restart at configuration reload.

File size: 23.2 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2010 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/***************************************************************************
21 *
22 * This file provides a module for samhain to check the MS Windows registry.
23 *
24 */
25
26#include "config_xor.h"
27
28#ifdef USE_REGISTRY_CHECK
29
30#include <windows.h>
31#include <stdio.h>
32#include <time.h>
33
34#define FIL__ _("sh_registry.c")
35
36/* We don't want to build this into yule
37 */
38#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
39
40#include <sys/types.h>
41#include <regex.h>
42
43#include "samhain.h"
44#include "sh_pthread.h"
45#include "sh_utils.h"
46#include "sh_unix.h"
47#include "sh_modules.h"
48#include "sh_hash.h"
49#include "sh_tiger.h"
50
51static int check_key (char * name, int isSingle);
52
53static int sh_reg_set_active (const char *s);
54static int sh_reg_set_interval (const char * c);
55static int sh_reg_set_severity (const char *s);
56static int sh_reg_add_key (const char *s);
57static int sh_reg_add_hierarchy (const char *s);
58static int sh_reg_add_stop (const char *s);
59static int sh_reg_add_ign (const char *s);
60
61#define STOP_FALSE 0
62#define STOP_CHECK 1
63#define STOP_IGN 2
64
65sh_rconf sh_reg_check_table[] = {
66 {
67 N_("severitychange"),
68 sh_reg_set_severity,
69 },
70 {
71 N_("registrycheckactive"),
72 sh_reg_set_active,
73 },
74 {
75 N_("registrycheckinterval"),
76 sh_reg_set_interval,
77 },
78 {
79 N_("singlekey"),
80 sh_reg_add_key,
81 },
82 {
83 N_("hierarchy"),
84 sh_reg_add_hierarchy,
85 },
86 {
87 N_("stopatkey"),
88 sh_reg_add_stop,
89 },
90 {
91 N_("ignorekey"),
92 sh_reg_add_ign,
93 },
94 {
95 NULL,
96 NULL
97 }
98};
99
100/* Runtime configuration */
101
102#define SH_REGISTRY_INTERVAL 300
103
104static int ShRegCheckActive = S_FALSE;
105static time_t sh_reg_check_interval = SH_REGISTRY_INTERVAL;
106static int sh_reg_check_severity = SH_ERR_SEVERE;
107
108struct regkeylist {
109 char * name;
110 int stop;
111 int single;
112#ifdef HAVE_REGEX_H
113 regex_t preg;
114#endif
115
116 struct regkeylist *next;
117};
118
119static struct regkeylist * keylist = NULL;
120
121static int sh_reg_set_active(const char *s)
122{
123 int value;
124
125 SL_ENTER(_("sh_reg_set_active"));
126
127 value = sh_util_flagval(s, &ShRegCheckActive);
128
129 SL_RETURN((value), _("sh_reg_set_active"));
130}
131
132static int sh_reg_set_interval (const char * c)
133{
134 int retval = 0;
135 long val;
136
137 SL_ENTER(_("sh_reg_set_interval"));
138 val = strtol (c, (char **)NULL, 10);
139 if (val <= 0)
140 {
141 SH_MUTEX_LOCK(mutex_thread_nolog);
142 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
143 _("registry check interval"), c);
144 SH_MUTEX_UNLOCK(mutex_thread_nolog);
145 retval = -1;
146 }
147
148 sh_reg_check_interval = (time_t) val;
149 SL_RETURN(0, _("sh_reg_set_interval"));
150}
151
152static int sh_reg_set_severity (const char *s)
153{
154 char tmp[32];
155 tmp[0] = '='; tmp[1] = '\0';
156 sl_strlcat (tmp, s, 32);
157 return sh_error_set_level (tmp, &sh_reg_check_severity);
158}
159
160static int sh_reg_add_key_int (const char *s, int isSingle, int isStop)
161{
162 struct regkeylist * newkey;
163 size_t len = sl_strlen(s);
164
165 if (len > 0)
166 {
167 newkey = SH_ALLOC(sizeof(struct regkeylist));
168 newkey->single = isSingle;
169 newkey->stop = isStop;
170 newkey->name = NULL;
171
172 if (STOP_FALSE == isStop)
173 {
174 newkey->name = SH_ALLOC(len + 1);
175 sl_strlcpy(newkey->name, s, len+1);
176 }
177 else
178 {
179#ifdef HAVE_REGEX_H
180 int status = regcomp(&(newkey->preg), s, REG_NOSUB|REG_EXTENDED);
181 if (status != 0)
182 {
183 char errbuf[256];
184 regerror(status, &(newkey->preg), errbuf, sizeof(errbuf));
185 SH_MUTEX_LOCK(mutex_thread_nolog);
186 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
187 errbuf, _("sh_reg_add_key_int"));
188 SH_MUTEX_UNLOCK(mutex_thread_nolog);
189 SH_FREE(newkey);
190 return -1;
191 }
192#else
193 newkey->name = SH_ALLOC(len + 1);
194 sl_strlcpy(newkey->name, s, len+1);
195#endif
196 }
197 newkey->next = keylist;
198 keylist = newkey;
199 return 0;
200 }
201 return -1;
202}
203
204static int sh_reg_add_key (const char *s)
205{
206 return sh_reg_add_key_int (s, S_TRUE, STOP_FALSE);
207}
208static int sh_reg_add_hierarchy (const char *s)
209{
210 return sh_reg_add_key_int (s, S_FALSE, STOP_FALSE);
211}
212static int sh_reg_add_stop (const char *s)
213{
214 return sh_reg_add_key_int (s, S_FALSE, STOP_CHECK);
215}
216static int sh_reg_add_ign (const char *s)
217{
218 return sh_reg_add_key_int (s, S_FALSE, STOP_IGN);
219}
220
221/* Module functions */
222
223int sh_reg_check_init(struct mod_type * arg)
224{
225#ifndef HAVE_PTHREAD
226 (void) arg;
227#endif
228
229 if (ShRegCheckActive == S_FALSE)
230 return SH_MOD_FAILED;
231#ifdef HAVE_PTHREAD
232 if (arg != NULL && arg->initval < 0 &&
233 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
234 {
235 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
236 return SH_MOD_THREAD;
237 else
238 return SH_MOD_FAILED;
239 }
240 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
241 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
242 {
243 return SH_MOD_THREAD;
244 }
245#endif
246 return 0;
247}
248
249int sh_reg_check_timer(time_t tcurrent)
250{
251 static time_t lastcheck = 0;
252
253 SL_ENTER(_("sh_reg_check_timer"));
254 if ((time_t) (tcurrent - lastcheck) >= sh_reg_check_interval)
255 {
256 lastcheck = tcurrent;
257 SL_RETURN((-1), _("sh_reg_check_timer"));
258 }
259 SL_RETURN(0, _("sh_reg_check_timer"));
260}
261
262#define SH_REGFORM_NEW 1
263#define SH_REGFORM_OLD 2
264
265static char * format_changes(int flag, char * buf, size_t len,
266 time_t time_old, unsigned long size_old,
267 unsigned long keys_old, unsigned long values_old,
268 char * hash_old,
269 time_t time_new, unsigned long size_new,
270 unsigned long keys_new, unsigned long values_new,
271 char * hash_new)
272{
273 char timestr1[32];
274 char timestr2[32];
275 char timestr3[32];
276
277 char buf_old[512] = "";
278 char buf_new[512] = "";
279
280 if ((0 != (flag & SH_REGFORM_NEW)) && (NULL != hash_new))
281 {
282 (void) sh_unix_gmttime (time_new, timestr1, sizeof(timestr1));
283 (void) sh_unix_gmttime (keys_new, timestr2, sizeof(timestr2));
284 (void) sh_unix_gmttime (values_new, timestr3, sizeof(timestr3));
285
286#ifdef SH_USE_XML
287 sl_snprintf(buf_new, sizeof(buf_new),
288 "size_new=\"%lu\" mtime_new=\"%s\" ctime_new=\"%s\" atime_new=\"%s\" chksum_new=\"%s\"",
289 size_new, timestr1, timestr2, timestr3, hash_new);
290#else
291 sl_snprintf(buf_new, sizeof(buf_new),
292 "size_new=<%lu>, mtime_new=<%s>, ctime_new=<%s>, atime_new=<%s>, chksum_new=<%s>",
293 size_new, timestr1, timestr2, timestr3, hash_new);
294#endif
295 }
296
297 if ((0 != (flag & SH_REGFORM_OLD)) && (NULL != hash_old))
298 {
299 (void) sh_unix_gmttime (time_old, timestr1, sizeof(timestr1));
300 (void) sh_unix_gmttime (keys_old, timestr2, sizeof(timestr2));
301 (void) sh_unix_gmttime (values_old, timestr3, sizeof(timestr3));
302
303#ifdef SH_USE_XML
304 sl_snprintf(buf_old, sizeof(buf_old),
305 " size_old=\"%lu\" mtime_old=\"%s\" ctime_old=\"%s\" atime_old=\"%s\" chksum_old=\"%s\"",
306 size_old, timestr1, timestr2, timestr3, hash_old);
307#else
308 sl_snprintf(buf_old, sizeof(buf_old),
309 " size_old=<%lu>, mtime_old=<%s>, ctime_old=<%s>, atime_old=<%s>, chksum_old=<%s>",
310 size_old, timestr1, timestr2, timestr3, hash_old);
311#endif
312 }
313
314 sl_strlcpy(buf, buf_new, len);
315 sl_strlcat(buf, buf_old, len);
316
317 return buf;
318}
319
320static void report_missing_entry(const char * path)
321{
322 char * infobuf = SH_ALLOC(1024);
323 char * errbuf = SH_ALLOC(1024);
324 char * tmp = sh_util_safe_name (path);
325 char timestr[32];
326 struct store2db save;
327
328 memset(&save, '\0', sizeof(struct store2db));
329 sh_hash_db2pop (path, &save);
330
331 (void) sh_unix_gmttime (save.val1, timestr, sizeof(timestr));
332
333 sl_snprintf(infobuf, 1024, _("mtime=%s size=%lu subkeys=%lu values=%lu"),
334 timestr,
335 (unsigned long) save.val0,
336 (unsigned long) save.val2,
337 (unsigned long) save.val3);
338
339 (void) format_changes (SH_REGFORM_OLD, errbuf, 1024,
340 save.val1, save.val0, save.val2, save.val3, save.checksum,
341 0, 0, 0, 0, NULL);
342
343 SH_MUTEX_LOCK(mutex_thread_nolog);
344 sh_error_handle(sh_reg_check_severity, FIL__, __LINE__, 0, MSG_REG_MISS,
345 infobuf, tmp, errbuf);
346 SH_MUTEX_UNLOCK(mutex_thread_nolog);
347
348 SH_FREE(tmp);
349 SH_FREE(errbuf);
350 SH_FREE(infobuf);
351 return;
352}
353
354int sh_reg_check_run(void)
355{
356 struct regkeylist *this = keylist;
357
358 if (this)
359 {
360 SH_MUTEX_LOCK(mutex_thread_nolog);
361 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
362 _("Checking the registry"),
363 _("sh_reg_check_run"));
364 SH_MUTEX_UNLOCK(mutex_thread_nolog);
365
366 while (this)
367 {
368 if (STOP_FALSE == this->stop)
369 {
370 /*
371 * -- Check key --
372 */
373 check_key (this->name, this->single);
374 }
375 this = this->next;
376 }
377 }
378 sh_hash_unvisited_custom ('H', report_missing_entry);
379
380 return 0;
381}
382
383int sh_reg_check_reconf(void)
384{
385 struct regkeylist *this;
386
387 while (keylist)
388 {
389 this = keylist;
390 keylist = keylist->next;
391
392 if (this->name)
393 SH_FREE(this->name);
394#ifdef HAVE_REGEX_H
395 if (STOP_FALSE != this->stop)
396 regfree(&(this->preg));
397#endif
398 SH_FREE(this);
399 }
400
401 sh_reg_check_interval = SH_REGISTRY_INTERVAL;
402
403 return 0;
404}
405
406int sh_reg_check_cleanup(void)
407{
408 sh_reg_check_reconf();
409 return 0;
410}
411
412/* >>>>>>>>>>>> Main check function <<<<<<<<<<<< */
413
414
415#include <windows.h>
416
417#define MAX_KEY_LENGTH (2*256)
418#define MAX_VALUE_NAME (2*16384)
419
420CHAR achValue[MAX_VALUE_NAME];
421
422unsigned long nKeys = 0;
423unsigned long nVals = 0;
424
425static int CheckThisSubkey (HKEY key, char * subkey, char * path,
426 int isSingle, int view);
427
428static time_t convertTime(FILETIME * ft)
429{
430 time_t result;
431
432 /* Shift high part up by 2^32
433 */
434 UINT64 date = ((UINT64)ft->dwHighDateTime) << 32;
435
436 /* Add low part
437 */
438 date |= (UINT64)ft->dwLowDateTime;
439
440 /* Subtract difference between Jan 1, 1601 and Jan 1, 1970
441 */
442 date -= ((UINT64)116444736) * ((UINT64)100) * ((UINT64)10000000);
443
444 /* Divide by number of 100-nanosecond intervals per second
445 */
446 date /= ((UINT64)10000000);
447
448 /* Convert to a time_t
449 */
450 result = (time_t) date;
451
452 return result;
453}
454
455#if !defined(KEY_WOW64_64KEY)
456#define KEY_WOW64_64KEY 0x0100;
457#endif
458#if !defined(KEY_WOW64_32KEY)
459#define KEY_WOW64_32KEY 0x0200;
460#endif
461
462
463#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
464
465int QueryKey(HKEY hKey, char * path, size_t pathlen, int isSingle)
466{
467 CHAR achKey[MAX_KEY_LENGTH]; /* buffer for subkey name */
468 DWORD cbName; /* size of name string */
469 /* CHAR achClass[MAX_PATH] = ""; *//* buffer for class name */
470 /* DWORD cchClassName = MAX_PATH/2;*//* size of class string */
471 DWORD cSubKeys=0; /* number of subkeys */
472 DWORD cbMaxSubKey; /* longest subkey size */
473 DWORD cchMaxClass; /* longest class string */
474 DWORD cValues; /* number of values for key */
475 DWORD cchMaxValue; /* longest value name */
476 DWORD cbMaxValueData; /* longest value data */
477 DWORD cbSecurityDescriptor; /* size of security descriptor */
478 FILETIME ftLastWriteTime; /* last write time */
479 DWORD lpType; /* type of data stored in value */
480 BYTE lpData[256]; /* buffer for data in value */
481 DWORD lpcbData; /* size of lpData buffer */
482 DWORD i, retCode;
483 DWORD cchValue = MAX_VALUE_NAME/2;
484
485 char hashbuf[KEYBUF_SIZE];
486 unsigned long totalSize = 0;
487 time_t fTime = 0;
488
489 char * tPath = NULL;
490 int doUpdate = S_FALSE;
491
492 retCode = RegQueryInfoKey(
493 hKey, /* key handle */
494 NULL /* achClass */, /* buffer for class name */
495 NULL /* &cchClassName */,/* size of class string */
496 NULL, /* reserved */
497 &cSubKeys, /* number of subkeys */
498 &cbMaxSubKey, /* longest subkey size */
499 &cchMaxClass, /* longest class string */
500 &cValues, /* number of values for this key */
501 &cchMaxValue, /* longest value name */
502 &cbMaxValueData, /* longest value data */
503 &cbSecurityDescriptor, /* security descriptor */
504 &ftLastWriteTime); /* last write time */
505
506 if (retCode != ERROR_SUCCESS)
507 {
508 return -1;
509 }
510
511 ++nKeys;
512
513 fTime = convertTime (&ftLastWriteTime);
514
515 /* Enumerate the subkeys, until RegEnumKeyEx fails. */
516
517 if (cSubKeys)
518 {
519 /*
520 * printf( "\nNumber of subkeys: %lu\n", (unsigned long) cSubKeys);
521 */
522
523 for (i=0; i<cSubKeys; i++)
524 {
525 cbName = MAX_KEY_LENGTH/2;
526 retCode = RegEnumKeyEx(hKey, i,
527 achKey,
528 &cbName,
529 NULL,
530 NULL,
531 NULL,
532 &ftLastWriteTime);
533
534 if (retCode == ERROR_SUCCESS && S_TRUE != isSingle)
535 {
536 /*
537 * _tprintf(TEXT("(%lu) %s\\%s\n"), (unsigned long) i+1,
538 * path, achKey);
539 */
540 CheckThisSubkey (hKey, achKey, path, isSingle, 0);
541 }
542 }
543 }
544
545 /* Enumerate the key values. */
546
547 if (cValues)
548 {
549 char hashtmp[3][KEYBUF_SIZE];
550
551 memset(hashbuf, '0', sizeof(hashbuf));
552
553 /* Loop over values and build checksum */
554
555 for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)
556 {
557 LPBYTE lpDataAlloc = NULL;
558
559 cchValue = MAX_VALUE_NAME/2;
560 achValue[0] = '\0';
561 lpcbData = sizeof(lpData);
562 retCode = RegEnumValue(hKey, i,
563 achValue,
564 &cchValue,
565 NULL,
566 &lpType,
567 lpData,
568 &lpcbData);
569
570 if (retCode == ERROR_MORE_DATA)
571 {
572 lpDataAlloc = SH_ALLOC(lpcbData);
573
574 retCode = RegEnumValue(hKey, i,
575 achValue,
576 &cchValue,
577 NULL,
578 &lpType,
579 lpDataAlloc,
580 &lpcbData);
581 }
582
583 if (retCode == ERROR_SUCCESS)
584 {
585 totalSize += lpcbData;
586
587 /* checksum(valuename) */
588 sh_tiger_hash (achValue, TIGER_DATA, cchValue,
589 hashtmp[0], KEYBUF_SIZE);
590
591 /* checksum(valuedata) */
592 if (NULL == lpDataAlloc)
593 {
594 sh_tiger_hash ((char*) lpData, TIGER_DATA, lpcbData,
595 hashtmp[1], KEYBUF_SIZE);
596 }
597 else
598 {
599 sh_tiger_hash ((char*) lpDataAlloc, TIGER_DATA, lpcbData,
600 hashtmp[1], KEYBUF_SIZE);
601 }
602
603 /* old_checksum */
604 memcpy(hashtmp[2], hashbuf, KEYBUF_SIZE);
605
606 /* hash(hash(valuename)+hash(valuedata)+old_hash) */
607 sh_tiger_hash ((char*) hashtmp, TIGER_DATA,
608 sizeof(hashtmp), hashbuf, sizeof(hashbuf));
609
610 ++nVals;
611 }
612
613 if (lpDataAlloc)
614 {
615 SH_FREE(lpDataAlloc);
616 }
617 }
618 }
619 else
620 {
621 /* no values */
622 sl_strlcpy(hashbuf, SH_KEY_NULL, sizeof(hashbuf));
623 }
624
625 /* Here we have:
626 * hashbuf [checksum over values],
627 * fTime [last write time],
628 * totalSize [size of all value data],
629 * cSubKeys [number of subkeys],
630 * cValues [number of values],
631 * path, pathlen [which may be up to 131072 (256*512) bytes]
632 */
633
634 if (pathlen > (PATH_MAX-1))
635 {
636 char hashbuf2[KEYBUF_SIZE];
637 char * p = strchr(path, '\\');
638
639 if (p)
640 {
641 char *q = p;
642
643 ++p;
644
645 tPath = SH_ALLOC(256 + KEYBUF_SIZE);
646 *q = '\0';
647 sl_strlcpy(tPath, path, 256); /* truncates */
648 *q = '\\';
649 sl_strlcat(tPath, "\\", 257);
650 (void) sh_tiger_hash(p, TIGER_DATA, sl_strlen(p),
651 hashbuf2, sizeof(hashbuf2));
652 sl_strlcat(tPath, hashbuf2, 256 + KEYBUF_SIZE);
653 }
654 }
655
656 if (sh.flag.checkSum == SH_CHECK_CHECK || sh.flag.update == S_TRUE)
657 {
658 struct store2db save;
659
660 memset(&save, '\0', sizeof(struct store2db));
661
662 if (tPath)
663 {
664 sh_hash_db2pop (tPath, &save);
665 }
666 else
667 {
668 sh_hash_db2pop (path, &save);
669 }
670
671 if (save.size == -1)
672 {
673 /* Not in database */
674
675 char * infobuf = SH_ALLOC(1024);
676 char * errbuf = SH_ALLOC(1024);
677 char * tmp = sh_util_safe_name ((tPath == NULL) ? path : tPath);
678 char timestr[32];
679
680 (void) sh_unix_gmttime (fTime, timestr, sizeof(timestr));
681
682 sl_snprintf(infobuf, 1024,
683 _("mtime=%s size=%lu subkeys=%lu values=%lu"),
684 timestr,
685 (unsigned long) totalSize,
686 (unsigned long) cSubKeys,
687 (unsigned long) cValues);
688
689 (void) format_changes (SH_REGFORM_NEW, errbuf, 1024,
690 0, 0, 0, 0, NULL,
691 fTime, totalSize, cSubKeys, cValues, hashbuf);
692
693 SH_MUTEX_LOCK(mutex_thread_nolog);
694 sh_error_handle(sh_reg_check_severity, FIL__, __LINE__,
695 0, MSG_REG_NEW,
696 infobuf, tmp, errbuf);
697 SH_MUTEX_UNLOCK(mutex_thread_nolog);
698
699 SH_FREE(tmp);
700 SH_FREE(errbuf);
701 SH_FREE(infobuf);
702
703 doUpdate = S_TRUE;
704 }
705 else if (save.val0 != totalSize ||
706 ((time_t) save.val1) != fTime ||
707 save.val2 != cSubKeys ||
708 save.val3 != cValues ||
709 0 != strcmp(save.checksum, hashbuf))
710 {
711 /* Change detected */
712 char * infobuf = SH_ALLOC(1024);
713 char * errbuf = SH_ALLOC(1024);
714 char * tmp = sh_util_safe_name ((tPath == NULL) ? path : tPath);
715 char timestr_new[32];
716
717 (void) sh_unix_gmttime (fTime, timestr_new, sizeof(timestr_new));
718
719 sl_snprintf(infobuf, 1024,
720 _("mtime=%s size %lu->%lu subkeys %lu->%lu values %lu->%lu checksum %s"),
721 timestr_new,
722 (unsigned long) save.val0, (unsigned long) totalSize,
723 (unsigned long) save.val2, (unsigned long) cSubKeys,
724 (unsigned long) save.val3, (unsigned long) cValues,
725 (0 == strcmp(save.checksum, hashbuf)) ? _("good") : _("bad"));
726
727 (void) format_changes (SH_REGFORM_OLD|SH_REGFORM_NEW, errbuf, 1024,
728 save.val1, save.val0,
729 save.val2, save.val3, save.checksum,
730 fTime, totalSize,
731 cSubKeys, cValues, hashbuf);
732
733 SH_MUTEX_LOCK(mutex_thread_nolog);
734 sh_error_handle(sh_reg_check_severity, FIL__, __LINE__,
735 0, MSG_REG_CHANGE,
736 infobuf, tmp, errbuf);
737 SH_MUTEX_UNLOCK(mutex_thread_nolog);
738
739 SH_FREE(tmp);
740 SH_FREE(errbuf);
741 SH_FREE(infobuf);
742
743 doUpdate = S_TRUE;
744 }
745 }
746
747 if ( sh.flag.checkSum == SH_CHECK_INIT || doUpdate == S_TRUE )
748 {
749 struct store2db save;
750
751 memset(&save, '\0', sizeof(struct store2db));
752
753 save.val0 = totalSize;
754 save.val1 = fTime;
755 save.val2 = cSubKeys;
756 save.val3 = cValues;
757 sl_strlcpy(save.checksum, hashbuf, KEY_LEN+1);
758
759 if (tPath)
760 {
761 sh_hash_push2db (tPath, &save);
762 }
763 else
764 {
765 sh_hash_push2db (path, &save);
766 }
767 }
768
769 if (tPath)
770 sh_hash_set_visited (tPath);
771 else
772 sh_hash_set_visited (path);
773
774 if (tPath)
775 {
776 SH_FREE(tPath);
777 }
778
779 return 0;
780}
781
782static int check_for_stop (char * name)
783{
784 struct regkeylist *this = keylist;
785
786 while (this)
787 {
788 if (STOP_FALSE != this->stop)
789 {
790#ifdef HAVE_REGEX_H
791 if (0 == regexec(&(this->preg), name, 0, NULL, 0))
792 return this->stop;
793#else
794 if (0 == strcmp(this->name, name))
795 return this->stop;
796#endif
797 }
798 this = this->next;
799 }
800 return STOP_FALSE;
801}
802
803
804int CheckThisSubkey (HKEY key, char * subkey, char * path, int isSingle,
805 int view)
806{
807 HKEY hTestKey;
808 char * newpath;
809 size_t len;
810 int retval = -1;
811
812 len = strlen(path) + 1 + strlen(subkey) + 1;
813 newpath = SH_ALLOC(len);
814 snprintf(newpath, len, "%s\\%s", path, subkey);
815
816 /* Check for stop condition, if not single key.
817 * Set flag to isSingle = S_TRUE if we should stop here.
818 */
819 if (S_TRUE != isSingle)
820 {
821 int isStop = check_for_stop(newpath);
822
823 if (STOP_CHECK == isStop)
824 {
825 isSingle = S_TRUE;
826 }
827 else if (STOP_IGN == isStop)
828 {
829 SH_FREE(newpath);
830 return 0;
831 }
832 }
833
834 len = strlen(path) + 1 + strlen(subkey) + 1;
835 newpath = SH_ALLOC(len);
836 snprintf(newpath, len, "%s\\%s", path, subkey);
837
838 if( RegOpenKeyEx( key,
839 subkey,
840 0,
841 (KEY_READ | view),
842 &hTestKey) == ERROR_SUCCESS
843 )
844 {
845 QueryKey(hTestKey, newpath, len-1, isSingle);
846 RegCloseKey(hTestKey);
847 retval = 0;
848 }
849 else
850 {
851 /* Error message */
852 char * tmp = sh_util_safe_name (newpath);
853 size_t tlen = sl_strlen(tmp);
854
855 if (SL_TRUE == sl_ok_adds(64, tlen))
856 {
857 char * errbuf = SH_ALLOC(64 + tlen);
858 sl_snprintf(errbuf, 64+tlen, _("Failed to open key %s"), tmp);
859
860 SH_MUTEX_LOCK(mutex_thread_nolog);
861 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
862 errbuf, _("CheckThisSubkey"));
863 SH_MUTEX_UNLOCK(mutex_thread_nolog);
864
865 SH_FREE(errbuf);
866 }
867 sh_reg_add_ign (tmp);
868 SH_FREE(tmp);
869 }
870
871 SH_FREE(newpath);
872 return retval;
873}
874
875
876int check_key (char * key, int isSingle)
877{
878 HKEY topKey;
879 char * subkey;
880 char path[20] = "";
881 int pos = 0;
882 int retval = -1;
883
884 if (0 == strncmp(key, _("HKEY_CLASSES_ROOT"), 17))
885 {
886 topKey = HKEY_CLASSES_ROOT;
887 pos = 17;
888 strncpy(path, _("HKEY_CLASSES_ROOT"), sizeof(path));
889 }
890 else if (0 == strncmp(key, _("HKEY_CURRENT_USER"), 17))
891 {
892 topKey = HKEY_CURRENT_USER;
893 pos = 17;
894 strncpy(path, _("HKEY_CURRENT_USER"), sizeof(path));
895 }
896 else if (0 == strncmp(key, _("HKEY_LOCAL_MACHINE"), 18))
897 {
898 topKey = HKEY_LOCAL_MACHINE;
899 pos = 18;
900 strncpy(path, _("HKEY_LOCAL_MACHINE"), sizeof(path));
901 }
902 else if (0 == strncmp(key, _("HKEY_USERS"), 10))
903 {
904 topKey = HKEY_USERS;
905 pos = 10;
906 strncpy(path, _("HKEY_USERS"), sizeof(path));
907 }
908
909
910 if (pos > 0)
911 {
912 if (key[pos] == '\\')
913 {
914 ++pos;
915 subkey = &key[pos];
916 }
917 }
918 else
919 {
920
921 char * tmp = sh_util_safe_name_keepspace(key);
922 size_t tlen = sl_strlen(tmp);
923
924 if (SL_TRUE == sl_ok_adds(64, tlen))
925 {
926 char * errbuf = SH_ALLOC(64 + tlen);
927
928 sl_snprintf(errbuf, 64+tlen, _("Invalid key %s"), tmp);
929
930 SH_MUTEX_LOCK(mutex_thread_nolog);
931 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
932 errbuf, _("check_key"));
933 SH_MUTEX_UNLOCK(mutex_thread_nolog);
934
935 SH_FREE(errbuf);
936 }
937 SH_FREE(tmp);
938 return -1;
939 }
940
941 /************************
942 if (ShCheckBothViews)
943 {
944 CheckThisSubkey (topKey, subkey, path, isSingle, KEY_WOW64_32KEY);
945 return CheckThisSubkey (topKey, subkey, path, isSingle, KEY_WOW64_64KEY);
946 }
947 *************************/
948
949 return CheckThisSubkey (topKey, subkey, path, isSingle, 0);
950}
951
952/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
953#endif
954
955/* #ifdef USE_REGISTRY_CHECK */
956#endif
957
Note: See TracBrowser for help on using the repository browser.