source: trunk/src/sh_registry.c@ 420

Last change on this file since 420 was 403, checked in by katerina, 12 years ago

Fix for tickets #301 and #302 (problems with the windows registry check).

File size: 24.1 KB
RevLine 
[294]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 {
[403]183 char errbuf[512];
184 char *p;
[294]185 regerror(status, &(newkey->preg), errbuf, sizeof(errbuf));
[403]186
187 sl_strlcat(errbuf, ": ", sizeof(errbuf));
188 p = sh_util_safe_name_keepspace(s);
189 sl_strlcat(errbuf, p, sizeof(errbuf));
190 SH_FREE(p);
191
[294]192 SH_MUTEX_LOCK(mutex_thread_nolog);
193 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
194 errbuf, _("sh_reg_add_key_int"));
195 SH_MUTEX_UNLOCK(mutex_thread_nolog);
196 SH_FREE(newkey);
197 return -1;
198 }
199#else
200 newkey->name = SH_ALLOC(len + 1);
201 sl_strlcpy(newkey->name, s, len+1);
202#endif
203 }
204 newkey->next = keylist;
205 keylist = newkey;
206 return 0;
207 }
208 return -1;
209}
210
211static int sh_reg_add_key (const char *s)
212{
213 return sh_reg_add_key_int (s, S_TRUE, STOP_FALSE);
214}
215static int sh_reg_add_hierarchy (const char *s)
216{
217 return sh_reg_add_key_int (s, S_FALSE, STOP_FALSE);
218}
219static int sh_reg_add_stop (const char *s)
220{
221 return sh_reg_add_key_int (s, S_FALSE, STOP_CHECK);
222}
223static int sh_reg_add_ign (const char *s)
224{
225 return sh_reg_add_key_int (s, S_FALSE, STOP_IGN);
226}
227
228/* Module functions */
229
230int sh_reg_check_init(struct mod_type * arg)
231{
232#ifndef HAVE_PTHREAD
233 (void) arg;
234#endif
235
236 if (ShRegCheckActive == S_FALSE)
237 return SH_MOD_FAILED;
238#ifdef HAVE_PTHREAD
239 if (arg != NULL && arg->initval < 0 &&
240 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
241 {
242 if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
243 return SH_MOD_THREAD;
244 else
245 return SH_MOD_FAILED;
246 }
[335]247 else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
248 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
249 {
250 return SH_MOD_THREAD;
251 }
[294]252#endif
253 return 0;
254}
255
256int sh_reg_check_timer(time_t tcurrent)
257{
258 static time_t lastcheck = 0;
259
260 SL_ENTER(_("sh_reg_check_timer"));
261 if ((time_t) (tcurrent - lastcheck) >= sh_reg_check_interval)
262 {
263 lastcheck = tcurrent;
264 SL_RETURN((-1), _("sh_reg_check_timer"));
265 }
266 SL_RETURN(0, _("sh_reg_check_timer"));
267}
268
269#define SH_REGFORM_NEW 1
270#define SH_REGFORM_OLD 2
271
272static char * format_changes(int flag, char * buf, size_t len,
273 time_t time_old, unsigned long size_old,
274 unsigned long keys_old, unsigned long values_old,
275 char * hash_old,
276 time_t time_new, unsigned long size_new,
277 unsigned long keys_new, unsigned long values_new,
278 char * hash_new)
279{
280 char timestr1[32];
281 char timestr2[32];
282 char timestr3[32];
283
284 char buf_old[512] = "";
285 char buf_new[512] = "";
286
287 if ((0 != (flag & SH_REGFORM_NEW)) && (NULL != hash_new))
288 {
289 (void) sh_unix_gmttime (time_new, timestr1, sizeof(timestr1));
290 (void) sh_unix_gmttime (keys_new, timestr2, sizeof(timestr2));
291 (void) sh_unix_gmttime (values_new, timestr3, sizeof(timestr3));
292
293#ifdef SH_USE_XML
294 sl_snprintf(buf_new, sizeof(buf_new),
295 "size_new=\"%lu\" mtime_new=\"%s\" ctime_new=\"%s\" atime_new=\"%s\" chksum_new=\"%s\"",
296 size_new, timestr1, timestr2, timestr3, hash_new);
297#else
298 sl_snprintf(buf_new, sizeof(buf_new),
299 "size_new=<%lu>, mtime_new=<%s>, ctime_new=<%s>, atime_new=<%s>, chksum_new=<%s>",
300 size_new, timestr1, timestr2, timestr3, hash_new);
301#endif
302 }
303
304 if ((0 != (flag & SH_REGFORM_OLD)) && (NULL != hash_old))
305 {
306 (void) sh_unix_gmttime (time_old, timestr1, sizeof(timestr1));
307 (void) sh_unix_gmttime (keys_old, timestr2, sizeof(timestr2));
308 (void) sh_unix_gmttime (values_old, timestr3, sizeof(timestr3));
309
310#ifdef SH_USE_XML
311 sl_snprintf(buf_old, sizeof(buf_old),
312 " size_old=\"%lu\" mtime_old=\"%s\" ctime_old=\"%s\" atime_old=\"%s\" chksum_old=\"%s\"",
313 size_old, timestr1, timestr2, timestr3, hash_old);
314#else
315 sl_snprintf(buf_old, sizeof(buf_old),
316 " size_old=<%lu>, mtime_old=<%s>, ctime_old=<%s>, atime_old=<%s>, chksum_old=<%s>",
317 size_old, timestr1, timestr2, timestr3, hash_old);
318#endif
319 }
320
321 sl_strlcpy(buf, buf_new, len);
322 sl_strlcat(buf, buf_old, len);
323
324 return buf;
325}
326
327static void report_missing_entry(const char * path)
328{
329 char * infobuf = SH_ALLOC(1024);
330 char * errbuf = SH_ALLOC(1024);
331 char * tmp = sh_util_safe_name (path);
332 char timestr[32];
333 struct store2db save;
334
335 memset(&save, '\0', sizeof(struct store2db));
336 sh_hash_db2pop (path, &save);
337
338 (void) sh_unix_gmttime (save.val1, timestr, sizeof(timestr));
339
340 sl_snprintf(infobuf, 1024, _("mtime=%s size=%lu subkeys=%lu values=%lu"),
341 timestr,
342 (unsigned long) save.val0,
343 (unsigned long) save.val2,
344 (unsigned long) save.val3);
345
346 (void) format_changes (SH_REGFORM_OLD, errbuf, 1024,
347 save.val1, save.val0, save.val2, save.val3, save.checksum,
348 0, 0, 0, 0, NULL);
349
350 SH_MUTEX_LOCK(mutex_thread_nolog);
351 sh_error_handle(sh_reg_check_severity, FIL__, __LINE__, 0, MSG_REG_MISS,
352 infobuf, tmp, errbuf);
353 SH_MUTEX_UNLOCK(mutex_thread_nolog);
354
355 SH_FREE(tmp);
356 SH_FREE(errbuf);
357 SH_FREE(infobuf);
358 return;
359}
360
361int sh_reg_check_run(void)
362{
363 struct regkeylist *this = keylist;
364
365 if (this)
366 {
367 SH_MUTEX_LOCK(mutex_thread_nolog);
368 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
369 _("Checking the registry"),
370 _("sh_reg_check_run"));
371 SH_MUTEX_UNLOCK(mutex_thread_nolog);
372
373 while (this)
374 {
375 if (STOP_FALSE == this->stop)
376 {
377 /*
378 * -- Check key --
379 */
380 check_key (this->name, this->single);
381 }
382 this = this->next;
383 }
384 }
385 sh_hash_unvisited_custom ('H', report_missing_entry);
386
387 return 0;
388}
389
390int sh_reg_check_reconf(void)
391{
392 struct regkeylist *this;
393
394 while (keylist)
395 {
396 this = keylist;
397 keylist = keylist->next;
398
399 if (this->name)
400 SH_FREE(this->name);
401#ifdef HAVE_REGEX_H
402 if (STOP_FALSE != this->stop)
403 regfree(&(this->preg));
404#endif
405 SH_FREE(this);
406 }
407
408 sh_reg_check_interval = SH_REGISTRY_INTERVAL;
409
410 return 0;
411}
412
413int sh_reg_check_cleanup(void)
414{
415 sh_reg_check_reconf();
416 return 0;
417}
418
419/* >>>>>>>>>>>> Main check function <<<<<<<<<<<< */
420
421
422#include <windows.h>
423
424#define MAX_KEY_LENGTH (2*256)
425#define MAX_VALUE_NAME (2*16384)
426
427CHAR achValue[MAX_VALUE_NAME];
428
429unsigned long nKeys = 0;
430unsigned long nVals = 0;
431
[312]432static int CheckThisSubkey (HKEY key, char * subkey, char * path,
433 int isSingle, int view);
[294]434
435static time_t convertTime(FILETIME * ft)
436{
437 time_t result;
438
439 /* Shift high part up by 2^32
440 */
441 UINT64 date = ((UINT64)ft->dwHighDateTime) << 32;
442
443 /* Add low part
444 */
445 date |= (UINT64)ft->dwLowDateTime;
446
447 /* Subtract difference between Jan 1, 1601 and Jan 1, 1970
448 */
449 date -= ((UINT64)116444736) * ((UINT64)100) * ((UINT64)10000000);
450
451 /* Divide by number of 100-nanosecond intervals per second
452 */
453 date /= ((UINT64)10000000);
454
455 /* Convert to a time_t
456 */
457 result = (time_t) date;
458
459 return result;
460}
461
[295]462#if !defined(KEY_WOW64_64KEY)
463#define KEY_WOW64_64KEY 0x0100;
464#endif
465#if !defined(KEY_WOW64_32KEY)
466#define KEY_WOW64_32KEY 0x0200;
467#endif
[294]468
469
470#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
471
472int QueryKey(HKEY hKey, char * path, size_t pathlen, int isSingle)
473{
474 CHAR achKey[MAX_KEY_LENGTH]; /* buffer for subkey name */
475 DWORD cbName; /* size of name string */
476 /* CHAR achClass[MAX_PATH] = ""; *//* buffer for class name */
477 /* DWORD cchClassName = MAX_PATH/2;*//* size of class string */
478 DWORD cSubKeys=0; /* number of subkeys */
479 DWORD cbMaxSubKey; /* longest subkey size */
480 DWORD cchMaxClass; /* longest class string */
481 DWORD cValues; /* number of values for key */
482 DWORD cchMaxValue; /* longest value name */
483 DWORD cbMaxValueData; /* longest value data */
484 DWORD cbSecurityDescriptor; /* size of security descriptor */
485 FILETIME ftLastWriteTime; /* last write time */
486 DWORD lpType; /* type of data stored in value */
487 BYTE lpData[256]; /* buffer for data in value */
488 DWORD lpcbData; /* size of lpData buffer */
489 DWORD i, retCode;
490 DWORD cchValue = MAX_VALUE_NAME/2;
491
492 char hashbuf[KEYBUF_SIZE];
493 unsigned long totalSize = 0;
494 time_t fTime = 0;
495
496 char * tPath = NULL;
497 int doUpdate = S_FALSE;
498
499 retCode = RegQueryInfoKey(
500 hKey, /* key handle */
501 NULL /* achClass */, /* buffer for class name */
502 NULL /* &cchClassName */,/* size of class string */
503 NULL, /* reserved */
504 &cSubKeys, /* number of subkeys */
505 &cbMaxSubKey, /* longest subkey size */
506 &cchMaxClass, /* longest class string */
507 &cValues, /* number of values for this key */
508 &cchMaxValue, /* longest value name */
509 &cbMaxValueData, /* longest value data */
510 &cbSecurityDescriptor, /* security descriptor */
511 &ftLastWriteTime); /* last write time */
512
513 if (retCode != ERROR_SUCCESS)
514 {
515 return -1;
516 }
517
518 ++nKeys;
519
520 fTime = convertTime (&ftLastWriteTime);
521
522 /* Enumerate the subkeys, until RegEnumKeyEx fails. */
523
524 if (cSubKeys)
525 {
526 /*
527 * printf( "\nNumber of subkeys: %lu\n", (unsigned long) cSubKeys);
528 */
529
530 for (i=0; i<cSubKeys; i++)
531 {
532 cbName = MAX_KEY_LENGTH/2;
533 retCode = RegEnumKeyEx(hKey, i,
534 achKey,
535 &cbName,
536 NULL,
537 NULL,
538 NULL,
539 &ftLastWriteTime);
540
541 if (retCode == ERROR_SUCCESS && S_TRUE != isSingle)
542 {
543 /*
544 * _tprintf(TEXT("(%lu) %s\\%s\n"), (unsigned long) i+1,
545 * path, achKey);
546 */
[312]547 CheckThisSubkey (hKey, achKey, path, isSingle, 0);
[294]548 }
549 }
550 }
551
552 /* Enumerate the key values. */
553
554 if (cValues)
555 {
556 char hashtmp[3][KEYBUF_SIZE];
557
558 memset(hashbuf, '0', sizeof(hashbuf));
559
560 /* Loop over values and build checksum */
561
562 for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)
563 {
564 LPBYTE lpDataAlloc = NULL;
565
566 cchValue = MAX_VALUE_NAME/2;
567 achValue[0] = '\0';
568 lpcbData = sizeof(lpData);
569 retCode = RegEnumValue(hKey, i,
570 achValue,
571 &cchValue,
572 NULL,
573 &lpType,
574 lpData,
575 &lpcbData);
576
577 if (retCode == ERROR_MORE_DATA)
578 {
579 lpDataAlloc = SH_ALLOC(lpcbData);
580
581 retCode = RegEnumValue(hKey, i,
582 achValue,
583 &cchValue,
584 NULL,
585 &lpType,
586 lpDataAlloc,
587 &lpcbData);
588 }
589
590 if (retCode == ERROR_SUCCESS)
591 {
592 totalSize += lpcbData;
593
594 /* checksum(valuename) */
595 sh_tiger_hash (achValue, TIGER_DATA, cchValue,
596 hashtmp[0], KEYBUF_SIZE);
597
598 /* checksum(valuedata) */
599 if (NULL == lpDataAlloc)
600 {
601 sh_tiger_hash ((char*) lpData, TIGER_DATA, lpcbData,
602 hashtmp[1], KEYBUF_SIZE);
603 }
604 else
605 {
606 sh_tiger_hash ((char*) lpDataAlloc, TIGER_DATA, lpcbData,
607 hashtmp[1], KEYBUF_SIZE);
608 }
609
610 /* old_checksum */
611 memcpy(hashtmp[2], hashbuf, KEYBUF_SIZE);
612
613 /* hash(hash(valuename)+hash(valuedata)+old_hash) */
614 sh_tiger_hash ((char*) hashtmp, TIGER_DATA,
615 sizeof(hashtmp), hashbuf, sizeof(hashbuf));
616
617 ++nVals;
618 }
619
620 if (lpDataAlloc)
621 {
622 SH_FREE(lpDataAlloc);
623 }
624 }
625 }
626 else
627 {
628 /* no values */
629 sl_strlcpy(hashbuf, SH_KEY_NULL, sizeof(hashbuf));
630 }
631
632 /* Here we have:
633 * hashbuf [checksum over values],
634 * fTime [last write time],
635 * totalSize [size of all value data],
636 * cSubKeys [number of subkeys],
637 * cValues [number of values],
638 * path, pathlen [which may be up to 131072 (256*512) bytes]
639 */
640
641 if (pathlen > (PATH_MAX-1))
642 {
643 char hashbuf2[KEYBUF_SIZE];
644 char * p = strchr(path, '\\');
645
646 if (p)
647 {
648 char *q = p;
649
650 ++p;
651
652 tPath = SH_ALLOC(256 + KEYBUF_SIZE);
653 *q = '\0';
654 sl_strlcpy(tPath, path, 256); /* truncates */
655 *q = '\\';
656 sl_strlcat(tPath, "\\", 257);
657 (void) sh_tiger_hash(p, TIGER_DATA, sl_strlen(p),
658 hashbuf2, sizeof(hashbuf2));
659 sl_strlcat(tPath, hashbuf2, 256 + KEYBUF_SIZE);
660 }
661 }
662
663 if (sh.flag.checkSum == SH_CHECK_CHECK || sh.flag.update == S_TRUE)
664 {
665 struct store2db save;
666
667 memset(&save, '\0', sizeof(struct store2db));
668
669 if (tPath)
670 {
671 sh_hash_db2pop (tPath, &save);
672 }
673 else
674 {
675 sh_hash_db2pop (path, &save);
676 }
677
678 if (save.size == -1)
679 {
680 /* Not in database */
681
682 char * infobuf = SH_ALLOC(1024);
683 char * errbuf = SH_ALLOC(1024);
684 char * tmp = sh_util_safe_name ((tPath == NULL) ? path : tPath);
685 char timestr[32];
686
687 (void) sh_unix_gmttime (fTime, timestr, sizeof(timestr));
688
689 sl_snprintf(infobuf, 1024,
690 _("mtime=%s size=%lu subkeys=%lu values=%lu"),
691 timestr,
692 (unsigned long) totalSize,
693 (unsigned long) cSubKeys,
694 (unsigned long) cValues);
695
696 (void) format_changes (SH_REGFORM_NEW, errbuf, 1024,
697 0, 0, 0, 0, NULL,
698 fTime, totalSize, cSubKeys, cValues, hashbuf);
699
700 SH_MUTEX_LOCK(mutex_thread_nolog);
701 sh_error_handle(sh_reg_check_severity, FIL__, __LINE__,
702 0, MSG_REG_NEW,
703 infobuf, tmp, errbuf);
704 SH_MUTEX_UNLOCK(mutex_thread_nolog);
705
706 SH_FREE(tmp);
707 SH_FREE(errbuf);
708 SH_FREE(infobuf);
709
710 doUpdate = S_TRUE;
711 }
712 else if (save.val0 != totalSize ||
713 ((time_t) save.val1) != fTime ||
714 save.val2 != cSubKeys ||
715 save.val3 != cValues ||
716 0 != strcmp(save.checksum, hashbuf))
717 {
718 /* Change detected */
719 char * infobuf = SH_ALLOC(1024);
720 char * errbuf = SH_ALLOC(1024);
721 char * tmp = sh_util_safe_name ((tPath == NULL) ? path : tPath);
722 char timestr_new[32];
723
724 (void) sh_unix_gmttime (fTime, timestr_new, sizeof(timestr_new));
725
726 sl_snprintf(infobuf, 1024,
727 _("mtime=%s size %lu->%lu subkeys %lu->%lu values %lu->%lu checksum %s"),
728 timestr_new,
729 (unsigned long) save.val0, (unsigned long) totalSize,
730 (unsigned long) save.val2, (unsigned long) cSubKeys,
731 (unsigned long) save.val3, (unsigned long) cValues,
732 (0 == strcmp(save.checksum, hashbuf)) ? _("good") : _("bad"));
733
734 (void) format_changes (SH_REGFORM_OLD|SH_REGFORM_NEW, errbuf, 1024,
735 save.val1, save.val0,
736 save.val2, save.val3, save.checksum,
737 fTime, totalSize,
738 cSubKeys, cValues, hashbuf);
739
740 SH_MUTEX_LOCK(mutex_thread_nolog);
741 sh_error_handle(sh_reg_check_severity, FIL__, __LINE__,
742 0, MSG_REG_CHANGE,
743 infobuf, tmp, errbuf);
744 SH_MUTEX_UNLOCK(mutex_thread_nolog);
745
746 SH_FREE(tmp);
747 SH_FREE(errbuf);
748 SH_FREE(infobuf);
749
750 doUpdate = S_TRUE;
751 }
[403]752
[294]753 }
754
[403]755 if ( sh.flag.checkSum == SH_CHECK_INIT || doUpdate == S_TRUE /* change detected */ )
[294]756 {
757 struct store2db save;
758
759 memset(&save, '\0', sizeof(struct store2db));
760
761 save.val0 = totalSize;
762 save.val1 = fTime;
763 save.val2 = cSubKeys;
764 save.val3 = cValues;
765 sl_strlcpy(save.checksum, hashbuf, KEY_LEN+1);
766
767 if (tPath)
768 {
769 sh_hash_push2db (tPath, &save);
770 }
771 else
772 {
773 sh_hash_push2db (path, &save);
774 }
775 }
776
[403]777 /* Without this, freshly updated entries would get deleted
778 * as 'not seen'.
779 */
780 if (sh.flag.checkSum != SH_CHECK_INIT)
781 {
782 if (tPath)
783 sh_hash_set_visited (tPath);
784 else
785 sh_hash_set_visited (path);
786 }
[294]787
788 if (tPath)
789 {
790 SH_FREE(tPath);
791 }
792
793 return 0;
794}
795
796static int check_for_stop (char * name)
797{
798 struct regkeylist *this = keylist;
799
800 while (this)
801 {
802 if (STOP_FALSE != this->stop)
803 {
804#ifdef HAVE_REGEX_H
805 if (0 == regexec(&(this->preg), name, 0, NULL, 0))
806 return this->stop;
807#else
808 if (0 == strcmp(this->name, name))
809 return this->stop;
810#endif
811 }
812 this = this->next;
813 }
814 return STOP_FALSE;
815}
816
817
[295]818int CheckThisSubkey (HKEY key, char * subkey, char * path, int isSingle,
819 int view)
[294]820{
821 HKEY hTestKey;
[403]822 LONG qError;
[294]823 char * newpath;
824 size_t len;
825 int retval = -1;
826
827 len = strlen(path) + 1 + strlen(subkey) + 1;
828 newpath = SH_ALLOC(len);
829 snprintf(newpath, len, "%s\\%s", path, subkey);
830
831 /* Check for stop condition, if not single key.
832 * Set flag to isSingle = S_TRUE if we should stop here.
833 */
834 if (S_TRUE != isSingle)
835 {
836 int isStop = check_for_stop(newpath);
837
838 if (STOP_CHECK == isStop)
839 {
840 isSingle = S_TRUE;
841 }
842 else if (STOP_IGN == isStop)
843 {
844 SH_FREE(newpath);
845 return 0;
846 }
847 }
848
849 len = strlen(path) + 1 + strlen(subkey) + 1;
850 newpath = SH_ALLOC(len);
851 snprintf(newpath, len, "%s\\%s", path, subkey);
852
[403]853 qError = RegOpenKeyEx( key,
854 subkey,
855 0,
856 (KEY_READ | view),
857 &hTestKey);
858
859
860 if (qError == ERROR_SUCCESS)
[294]861 {
862 QueryKey(hTestKey, newpath, len-1, isSingle);
863 RegCloseKey(hTestKey);
864 retval = 0;
865 }
866 else
867 {
868 /* Error message */
[403]869 LPVOID lpMsgBuf;
870
871 char * tmp = sh_util_safe_name (newpath);
872 size_t tlen = sl_strlen(tmp);
873
[294]874 if (SL_TRUE == sl_ok_adds(64, tlen))
875 {
[403]876 char * errbuf;
877 size_t elen;
878
879 tlen += 64;
880
881 elen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
882 FORMAT_MESSAGE_FROM_SYSTEM |
883 FORMAT_MESSAGE_IGNORE_INSERTS,
884 NULL,
885 qError,
886 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
887 (LPTSTR) &lpMsgBuf,
888 0, NULL );
889
890 if (elen > 0 && SL_TRUE == sl_ok_adds(elen, tlen))
891 {
892 tlen += elen;
893
894 errbuf = SH_ALLOC(elen + tlen);
895 sl_snprintf(errbuf, 64+tlen, _("Failed to open key %s: %s"),
896 tmp, lpMsgBuf);
897 LocalFree(lpMsgBuf);
898
899 SH_MUTEX_LOCK(mutex_thread_nolog);
900 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
901 errbuf, _("CheckThisSubkey"));
902 SH_MUTEX_UNLOCK(mutex_thread_nolog);
903
904 SH_FREE(errbuf);
905 }
[294]906 }
[403]907 sh_reg_add_ign (newpath);
[294]908 SH_FREE(tmp);
909 }
910
911 SH_FREE(newpath);
912 return retval;
913}
914
915
916int check_key (char * key, int isSingle)
917{
918 HKEY topKey;
919 char * subkey;
920 char path[20] = "";
921 int pos = 0;
922
923 if (0 == strncmp(key, _("HKEY_CLASSES_ROOT"), 17))
924 {
925 topKey = HKEY_CLASSES_ROOT;
926 pos = 17;
927 strncpy(path, _("HKEY_CLASSES_ROOT"), sizeof(path));
928 }
929 else if (0 == strncmp(key, _("HKEY_CURRENT_USER"), 17))
930 {
931 topKey = HKEY_CURRENT_USER;
932 pos = 17;
933 strncpy(path, _("HKEY_CURRENT_USER"), sizeof(path));
934 }
935 else if (0 == strncmp(key, _("HKEY_LOCAL_MACHINE"), 18))
936 {
937 topKey = HKEY_LOCAL_MACHINE;
938 pos = 18;
939 strncpy(path, _("HKEY_LOCAL_MACHINE"), sizeof(path));
940 }
941 else if (0 == strncmp(key, _("HKEY_USERS"), 10))
942 {
943 topKey = HKEY_USERS;
944 pos = 10;
945 strncpy(path, _("HKEY_USERS"), sizeof(path));
946 }
947
948
949 if (pos > 0)
950 {
951 if (key[pos] == '\\')
952 {
953 ++pos;
954 subkey = &key[pos];
955 }
956 }
957 else
958 {
959
960 char * tmp = sh_util_safe_name_keepspace(key);
961 size_t tlen = sl_strlen(tmp);
962
963 if (SL_TRUE == sl_ok_adds(64, tlen))
964 {
965 char * errbuf = SH_ALLOC(64 + tlen);
966
967 sl_snprintf(errbuf, 64+tlen, _("Invalid key %s"), tmp);
968
969 SH_MUTEX_LOCK(mutex_thread_nolog);
970 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
971 errbuf, _("check_key"));
972 SH_MUTEX_UNLOCK(mutex_thread_nolog);
973
974 SH_FREE(errbuf);
975 }
976 SH_FREE(tmp);
977 return -1;
978 }
[295]979
980 /************************
981 if (ShCheckBothViews)
982 {
983 CheckThisSubkey (topKey, subkey, path, isSingle, KEY_WOW64_32KEY);
984 return CheckThisSubkey (topKey, subkey, path, isSingle, KEY_WOW64_64KEY);
985 }
986 *************************/
987
988 return CheckThisSubkey (topKey, subkey, path, isSingle, 0);
[294]989}
990
991/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
992#endif
993
994/* #ifdef USE_REGISTRY_CHECK */
995#endif
996
Note: See TracBrowser for help on using the repository browser.