source: trunk/src/sh_log_correlate.c @ 272

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

Fixes tickets #190, #191, #192, #193, and #194.

File size: 6.8 KB
Line 
1#include "config_xor.h"
2
3#ifdef USE_LOGFILE_MONITOR
4
5#undef  FIL__
6#define FIL__  _("sh_log_correlate.c")
7
8#include <string.h>
9#include <time.h>
10
11/* Debian/Ubuntu: libpcre3-dev */
12#ifdef HAVE_PCRE_PCRE_H
13#include <pcre/pcre.h>
14#else
15#include <pcre.h>
16#endif
17
18#ifndef PCRE_NO_AUTO_CAPTURE
19#define PCRE_NO_AUTO_CAPTURE 0
20#endif
21
22#include "samhain.h"
23#include "sh_pthread.h"
24#include "sh_utils.h"
25#include "sh_string.h"
26#include "sh_log_check.h"
27#include "sh_log_evalrule.h"
28
29extern int flag_err_debug;
30
31/*--------------------------------------------------------------
32 *
33 *   Event correlation
34 *
35 *--------------------------------------------------------------*/
36
37/* For each even to be correlated, we keep a label in a list. We
38 * then build a string from the (time-sorted) list of labels, and
39 * match this string against a regular expression.
40 */
41
42/* -- The list of labels kept in memory ----------------------- */
43
44struct sh_keep
45{
46  sh_string       * label;           /* label of keep rule      */
47  unsigned long     delay;           /* valid delay             */
48  time_t            last;            /* seen at                 */
49  struct sh_keep *  next; 
50};
51
52static struct sh_keep * keeplist  = NULL;
53static struct sh_keep * keeplast  = NULL;
54static unsigned long    keepcount = 0;
55
56static void sh_keep_free(void * item)
57{
58  struct sh_keep * keep = (struct sh_keep *) item;
59  if (!keep)
60    return;
61  sh_string_destroy(&(keep->label));
62  SH_FREE(keep);
63}
64
65void sh_keep_destroy()
66{
67  struct sh_keep * keep;
68
69  while (keeplist)
70    {
71      keep = keeplist;
72      keeplist = keep->next;
73      sh_keep_free(keep);
74      --keepcount;
75    }
76  keeplist  = NULL;
77  keeplast  = NULL;
78  keepcount = 0;
79}
80
81int sh_keep_add(sh_string * label, unsigned long delay, time_t last)
82{
83  struct sh_keep * keep = SH_ALLOC(sizeof(struct sh_keep));
84
85  keep->label = sh_string_copy(label);
86  keep->delay = delay;
87  keep->last  = last;
88  keep->next  = NULL;
89
90  if (keeplast && keeplist)
91    {
92      keeplast->next = keep;
93      keeplast       = keep;
94    }
95  else
96    {
97      keeplist = keep;
98      keeplast = keeplist;
99    }
100  ++keepcount;
101  return 0;
102}
103
104int sh_keep_comp(const void * a, const void * b)
105{
106  return ( (int)(((struct sh_keep *)a)->last) - 
107           (int)(((struct sh_keep *)b)->last) );
108}
109
110/* -- Sort the kept labels and build a string ----------------- */
111
112static sh_string * sh_keep_eval()
113{
114  unsigned long count   = 0;
115  sh_string * res       = NULL;
116  time_t now            = time(NULL);
117  struct sh_keep * keep = keeplist;
118  struct sh_keep * prev = keeplist;
119  struct sh_keep * arr;
120
121  if (keepcount > 0)
122    {
123      arr = SH_ALLOC (keepcount * sizeof(struct sh_keep));
124
125      while (count < keepcount && keep)
126        {
127          if ((now > keep->last) && 
128              ((unsigned long)(now - keep->last) <= keep->delay))
129            {
130              memcpy(&(arr[count]), keep, sizeof(struct sh_keep));
131              ++count;
132              prev = keep;
133              keep = keep->next;
134            }
135          else /* Too old or in future, delete it */
136            {
137              if (keep != keeplist)
138                {
139                  prev->next = keep->next;
140                  sh_keep_free(keep);
141                  keep = prev->next;
142                  --keepcount;
143                }
144              else /* list head */
145                {
146                  keeplist = keep->next;
147                  prev     = keeplist;
148                  sh_keep_free(keep);
149                  keep     = keeplist;
150                  --keepcount;
151                }
152            }
153        }
154
155      if (count > 0)
156        {
157          unsigned long i;
158          qsort(arr, count, sizeof(struct sh_keep), sh_keep_comp);
159          res = sh_string_copy(arr[0].label);
160          for (i = 1; i < count; ++i)
161            res = sh_string_add(res, arr[i].label);
162        }
163      SH_FREE(arr);
164    }
165  return res;
166}
167
168/* -- Match the string against correlation rules -------------- */
169
170struct sh_mkeep
171{
172  sh_string       * label;           /* label of match rule     */
173  pcre            * rule;            /* compiled regex for rule */
174  struct sh_qeval * queue;           /* assigned queue          */
175  struct sh_mkeep * next; 
176};
177
178struct sh_mkeep * mkeep_list = NULL;
179
180
181int sh_keep_match_add(const char * str, const char * queue, 
182                      const char * pattern)
183{
184  unsigned int nfields = 1; /* seconds:label */
185  size_t       lengths[1];
186  char *       new    = sh_util_strdup(str);
187  char **      splits = split_array_braced(new, _("CORRELATE"), 
188                                           &nfields, lengths);
189
190  if (nfields == 1 && lengths[0] > 0)
191    {
192      struct sh_mkeep * mkeep = SH_ALLOC(sizeof(struct sh_mkeep));
193      const char * error;
194      int          erroffset;
195      struct sh_qeval * rqueue = NULL;
196
197      mkeep->rule = pcre_compile(pattern, PCRE_NO_AUTO_CAPTURE, 
198                             &error, &erroffset, NULL);
199      if (!(mkeep->rule))
200        {
201          sh_string * msg =  sh_string_new(0);
202          sh_string_add_from_char(msg, _("Bad regex: "));
203          sh_string_add_from_char(msg, pattern);
204         
205          SH_MUTEX_LOCK(mutex_thread_nolog);
206          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
207                          sh_string_str(msg),
208                          _("sh_keep_match_add"));
209          SH_MUTEX_UNLOCK(mutex_thread_nolog);
210          sh_string_destroy(&msg);
211         
212          SH_FREE(splits);
213          SH_FREE(mkeep);
214          SH_FREE(new);
215          return -1;
216        }
217
218      if (0 != strcmp(queue, _("trash")))
219        {
220
221          rqueue = sh_log_find_queue(queue);
222          if (!rqueue)
223            {
224              pcre_free(mkeep->rule);
225              SH_FREE(splits);
226              SH_FREE(mkeep);
227              SH_FREE(new);
228              return -1;
229            }
230        }
231
232      mkeep->queue = rqueue;
233      mkeep->label = sh_string_new_from_lchar(splits[0], strlen(splits[0]));
234      mkeep->next  = mkeep_list;
235      mkeep_list   = mkeep;
236    }
237  SH_FREE(new);
238  return 0;
239}
240
241void sh_keep_match_del()
242{
243  struct sh_mkeep * mkeep = mkeep_list;
244  while (mkeep)
245    {
246      mkeep_list = mkeep->next;
247      sh_string_destroy(&(mkeep->label));
248      pcre_free(mkeep->rule);
249      mkeep = mkeep_list;
250    }
251  mkeep_list = NULL;
252}
253
254static struct sh_mkeep ** dummy_mkeep;
255
256void sh_keep_match()
257{
258  if (mkeep_list)
259    {
260      sh_string       * res = sh_keep_eval();
261
262      if (res)
263        {
264          struct sh_mkeep * mkeep = mkeep_list;
265
266          dummy_mkeep = &mkeep;
267
268          while (mkeep)
269            {
270              /* Use pcre_dfa_exec() to obtain number of matches. Needs ovector
271               * array, otherwise number of matches is not returned.
272               */
273              int ovector[SH_MINIBUF];
274              int wspace[SH_MINIBUF];
275              int val = pcre_dfa_exec(mkeep->rule, NULL, 
276                                      sh_string_str(res), 
277                                      (int)sh_string_len(res), 
278                                      0, /* start at offset 0 in the subject */
279                                      0, 
280                                      ovector, SH_MINIBUF,
281                                      wspace, SH_MINIBUF);
282              if (val >= 0)
283                {
284                  sh_string * alias;
285                  SH_MUTEX_LOCK(mutex_thread_nolog);
286                  sh_error_handle (mkeep->queue->severity, FIL__, __LINE__, 0, 
287                                   MSG_LOGMON_COR, sh_string_str(mkeep->label),
288                                   val);
289
290                  alias = mkeep->queue->alias;
291                  if (alias)
292                    {
293                      sh_error_mail (sh_string_str(alias), 
294                                     mkeep->queue->severity, FIL__, __LINE__, 0, 
295                                     MSG_LOGMON_COR, sh_string_str(mkeep->label),
296                                     val);
297                    }
298                 
299                  SH_MUTEX_UNLOCK(mutex_thread_nolog);
300                }
301              mkeep = mkeep->next;
302            }
303          sh_string_destroy(&res);
304        }
305    }
306  return;
307}
308
309#endif
Note: See TracBrowser for help on using the repository browser.