source: trunk/src/sh_registry.c @ 422

Last change on this file since 422 was 422, checked in by katerina, 9 years ago

Fix for tickets #326, #327.

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