source: trunk/src/sh_log_correlate.c@ 357

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

Fix for ticket #263 (log correlation may not work).

File size: 7.4 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
60 if (!keep)
61 return;
62 sh_string_destroy(&(keep->label));
63 SH_FREE(keep);
64}
65
66void sh_keep_destroy()
67{
68 struct sh_keep * keep;
69
70 while (keeplist)
71 {
72 keep = keeplist;
73 keeplist = keep->next;
74 sh_keep_free(keep);
75 --keepcount;
76 }
77 keeplist = NULL;
78 keeplast = NULL;
79 keepcount = 0;
80}
81
82int sh_keep_add(sh_string * label, unsigned long delay, time_t last)
83{
84 struct sh_keep * keep = SH_ALLOC(sizeof(struct sh_keep));
85
86 keep->label = sh_string_copy(label);
87 keep->delay = delay;
88 keep->last = last;
89 keep->next = NULL;
90
91 if (keeplast && keeplist)
92 {
93 keeplast->next = keep;
94 keeplast = keep;
95 }
96 else
97 {
98 keeplist = keep;
99 keeplast = keeplist;
100 }
101 ++keepcount;
102 return 0;
103}
104
105int sh_keep_comp(const void * a, const void * b)
106{
107 return ( (int)(((struct sh_keep *)a)->last) -
108 (int)(((struct sh_keep *)b)->last) );
109}
110
111/* -- Sort the kept labels and build a string ----------------- */
112
113static sh_string * sh_keep_eval()
114{
115 unsigned long count = 0;
116 sh_string * res = NULL;
117 time_t now = time(NULL);
118 struct sh_keep * keep = keeplist;
119 struct sh_keep * prev = keeplist;
120 struct sh_keep * arr;
121
122 if (keepcount > 0)
123 {
124 arr = SH_ALLOC (keepcount * sizeof(struct sh_keep));
125
126 while (count < keepcount && keep)
127 {
128 if ((now >= keep->last) &&
129 ((unsigned long)(now - keep->last) <= keep->delay))
130 {
131 memcpy(&(arr[count]), keep, sizeof(struct sh_keep));
132 ++count;
133 prev = keep;
134 keep = keep->next;
135 }
136 else /* Too old or in future, delete it */
137 {
138 if (keep != keeplist)
139 {
140 prev->next = keep->next;
141 sh_keep_free(keep);
142 keep = prev->next;
143 --keepcount;
144 }
145 else /* list head */
146 {
147 keeplist = keep->next;
148 prev = keeplist;
149 sh_keep_free(keep);
150 keep = keeplist;
151 --keepcount;
152 }
153 }
154 }
155
156 if (count > 0)
157 {
158 unsigned long i;
159 qsort(arr, count, sizeof(struct sh_keep), sh_keep_comp);
160 res = sh_string_copy(arr[0].label);
161 for (i = 1; i < count; ++i)
162 res = sh_string_add(res, arr[i].label);
163 }
164 SH_FREE(arr);
165 }
166
167 return res;
168}
169
170/* -- Match the string against correlation rules -------------- */
171
172struct sh_mkeep
173{
174 sh_string * label; /* label of match rule */
175 pcre * rule; /* compiled regex for rule */
176 time_t reported; /* last reported */
177 struct sh_qeval * queue; /* assigned queue */
178 struct sh_mkeep * next;
179};
180
181struct sh_mkeep * mkeep_list = NULL;
182
183
184int sh_keep_match_add(const char * str, const char * queue,
185 const char * pattern)
186{
187 unsigned int nfields = 1; /* seconds:label */
188 size_t lengths[1];
189 char * new = sh_util_strdup(str);
190 char ** splits = split_array_braced(new, _("CORRELATE"),
191 &nfields, lengths);
192
193 if (nfields == 1 && lengths[0] > 0)
194 {
195 struct sh_mkeep * mkeep = SH_ALLOC(sizeof(struct sh_mkeep));
196 const char * error;
197 int erroffset;
198 struct sh_qeval * rqueue = NULL;
199
200 mkeep->rule = pcre_compile(pattern, PCRE_NO_AUTO_CAPTURE,
201 &error, &erroffset, NULL);
202 if (!(mkeep->rule))
203 {
204 sh_string * msg = sh_string_new(0);
205 sh_string_add_from_char(msg, _("Bad regex: "));
206 sh_string_add_from_char(msg, pattern);
207
208 SH_MUTEX_LOCK(mutex_thread_nolog);
209 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
210 sh_string_str(msg),
211 _("sh_keep_match_add"));
212 SH_MUTEX_UNLOCK(mutex_thread_nolog);
213 sh_string_destroy(&msg);
214
215 SH_FREE(splits);
216 SH_FREE(mkeep);
217 SH_FREE(new);
218 return -1;
219 }
220
221 if (0 != strcmp(queue, _("trash")))
222 {
223
224 rqueue = sh_log_find_queue(queue);
225 if (!rqueue)
226 {
227 pcre_free(mkeep->rule);
228 SH_FREE(splits);
229 SH_FREE(mkeep);
230 SH_FREE(new);
231 return -1;
232 }
233 }
234
235 mkeep->queue = rqueue;
236 mkeep->label = sh_string_new_from_lchar(splits[0], strlen(splits[0]));
237 mkeep->reported = 0;
238 mkeep->next = mkeep_list;
239 mkeep_list = mkeep;
240 }
241 SH_FREE(new);
242 return 0;
243}
244
245void sh_keep_match_del()
246{
247 struct sh_mkeep * mkeep = mkeep_list;
248 while (mkeep)
249 {
250 mkeep_list = mkeep->next;
251 sh_string_destroy(&(mkeep->label));
252 pcre_free(mkeep->rule);
253 mkeep = mkeep_list;
254 }
255 mkeep_list = NULL;
256}
257
258static struct sh_mkeep ** dummy_mkeep;
259
260void sh_keep_match()
261{
262 if (mkeep_list)
263 {
264 sh_string * res = sh_keep_eval();
265
266 if (res)
267 {
268 struct sh_mkeep * mkeep = mkeep_list;
269
270 dummy_mkeep = &mkeep;
271
272 while (mkeep)
273 {
274 /* Use pcre_dfa_exec() to obtain number of matches. Needs ovector
275 * array, otherwise number of matches is not returned.
276 */
277#if defined(HAVE_PCRE_DFA_EXEC)
278 int ovector[SH_MINIBUF];
279 int wspace[SH_MINIBUF];
280#endif
281
282#if defined(HAVE_PCRE_DFA_EXEC)
283 int val = pcre_dfa_exec(mkeep->rule, NULL,
284 sh_string_str(res),
285 (int)sh_string_len(res),
286 0, /* start at offset 0 in the subject */
287 0,
288 ovector, SH_MINIBUF,
289 wspace, SH_MINIBUF);
290#else
291 int val = pcre_exec(mkeep->rule, NULL,
292 sh_string_str(res),
293 (int)sh_string_len(res),
294 0, /* start at offset 0 in the subject */
295 0,
296 NULL, 0);
297 val = (val >= 0) ? 1 : val;
298#endif
299
300 if (val >= 0)
301 {
302 sh_string * alias;
303 time_t now = time(NULL);
304
305 if ((mkeep->reported < now) &&
306 (60 < (now - mkeep->reported)))
307 {
308 mkeep->reported = now;
309
310 SH_MUTEX_LOCK(mutex_thread_nolog);
311 sh_error_handle (mkeep->queue->severity, FIL__, __LINE__, 0,
312 MSG_LOGMON_COR, sh_string_str(mkeep->label),
313 val);
314
315 alias = mkeep->queue->alias;
316 if (alias)
317 {
318 sh_error_mail (sh_string_str(alias),
319 mkeep->queue->severity, FIL__, __LINE__, 0,
320 MSG_LOGMON_COR, sh_string_str(mkeep->label),
321 val);
322 }
323
324 SH_MUTEX_UNLOCK(mutex_thread_nolog);
325 }
326 }
327 mkeep = mkeep->next;
328 }
329 sh_string_destroy(&res);
330 }
331 }
332 return;
333}
334
335#endif
Note: See TracBrowser for help on using the repository browser.