source: trunk/src/sh_log_correlate.c@ 282

Last change on this file since 282 was 272, checked in by katerina, 15 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.