source: trunk/src/sh_log_correlate.c@ 334

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

Fix for ticket #209 (check for pcre_dfa_exec).

File size: 7.1 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#if defined(HAVE_PCRE_DFA_EXEC)
274 int ovector[SH_MINIBUF];
275 int wspace[SH_MINIBUF];
276#endif
277
278#if defined(HAVE_PCRE_DFA_EXEC)
279 int val = pcre_dfa_exec(mkeep->rule, NULL,
280 sh_string_str(res),
281 (int)sh_string_len(res),
282 0, /* start at offset 0 in the subject */
283 0,
284 ovector, SH_MINIBUF,
285 wspace, SH_MINIBUF);
286#else
287 int val = pcre_exec(mkeep->rule, NULL,
288 sh_string_str(res),
289 (int)sh_string_len(res),
290 0, /* start at offset 0 in the subject */
291 0,
292 NULL, 0);
293 val = (val >= 0) ? 1 : val;
294#endif
295
296 if (val >= 0)
297 {
298 sh_string * alias;
299 SH_MUTEX_LOCK(mutex_thread_nolog);
300 sh_error_handle (mkeep->queue->severity, FIL__, __LINE__, 0,
301 MSG_LOGMON_COR, sh_string_str(mkeep->label),
302 val);
303
304 alias = mkeep->queue->alias;
305 if (alias)
306 {
307 sh_error_mail (sh_string_str(alias),
308 mkeep->queue->severity, FIL__, __LINE__, 0,
309 MSG_LOGMON_COR, sh_string_str(mkeep->label),
310 val);
311 }
312
313 SH_MUTEX_UNLOCK(mutex_thread_nolog);
314 }
315 mkeep = mkeep->next;
316 }
317 sh_string_destroy(&res);
318 }
319 }
320 return;
321}
322
323#endif
Note: See TracBrowser for help on using the repository browser.