source: trunk/src/sh_log_correlate.c@ 588

Last change on this file since 588 was 588, checked in by katerina, 16 hours ago

Fix for ticket #476 (move logfile monitoring module from PCRE to PCRE2).

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