Imported Upstream version 2.7
[ossec-hids.git] / src / analysisd / decoders / decoder.c
1 /* @(#) $Id: ./src/analysisd/decoders/decoder.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All rights reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation.
11  *
12  * License details at the LICENSE file included with OSSEC or
13  * online at: http://www.ossec.net/en/licensing.html
14  */
15
16
17 #include "shared.h"
18 #include "os_regex/os_regex.h"
19 #include "os_xml/os_xml.h"
20
21
22 #include "eventinfo.h"
23 #include "decoder.h"
24
25
26
27 /* DecodeEvent.
28  * Will use the osdecoders to decode the received event.
29  */
30 void DecodeEvent(Eventinfo *lf)
31 {
32     OSDecoderNode *node;
33     OSDecoderNode *child_node;
34     OSDecoderInfo *nnode;
35
36     char *llog;
37     char *pmatch;
38     char *cmatch;
39     char *regex_prev = NULL;
40
41
42     node = OS_GetFirstOSDecoder(lf->program_name);
43
44
45     /* Return if no node...
46      * This shouldn't happen here anyways.
47      */
48     if(!node)
49         return;
50
51
52     #ifdef TESTRULE
53     if(!alert_only)
54     {
55         print_out("\n**Phase 2: Completed decoding.");
56     }
57     #endif
58
59     do
60     {
61         nnode = node->osdecoder;
62
63
64         /* First checking program name */
65         if(lf->program_name)
66         {
67             if(!OSMatch_Execute(lf->program_name, lf->p_name_size,
68                         nnode->program_name))
69             {
70                 continue;
71             }
72             pmatch = lf->log;
73         }
74
75
76         /* If prematch fails, go to the next osdecoder in the list */
77         if(nnode->prematch)
78         {
79             if(!(pmatch = OSRegex_Execute(lf->log, nnode->prematch)))
80             {
81                 continue;
82             }
83
84             /* Next character */
85             if(*pmatch != '\0')
86                 pmatch++;
87         }
88
89
90         #ifdef TESTRULE
91         if(!alert_only)print_out("       decoder: '%s'", nnode->name);
92         #endif
93
94
95         lf->decoder_info = nnode;
96
97
98         child_node = node->child;
99
100
101         /* If no child node is set, set the child node
102          * as if it were the child (ugh)
103          */
104         if(!child_node)
105         {
106             child_node = node;
107         }
108
109         else
110         {
111             /* Check if we have any child osdecoder */
112             while(child_node)
113             {
114                 nnode = child_node->osdecoder;
115
116
117                 /* If we have a pre match and it matches, keep
118                  * going. If we don't have a prematch, stop
119                  * and go for the regexes.
120                  */
121                 if(nnode->prematch)
122                 {
123                     char *llog;
124
125                     /* If we have an offset set, use it */
126                     if(nnode->prematch_offset & AFTER_PARENT)
127                     {
128                         llog = pmatch;
129                     }
130                     else
131                     {
132                         llog = lf->log;
133                     }
134
135                     if((cmatch = OSRegex_Execute(llog, nnode->prematch)))
136                     {
137                         if(*cmatch != '\0')
138                             cmatch++;
139
140                         lf->decoder_info = nnode;
141
142                         break;
143                     }
144                 }
145                 else
146                 {
147                     cmatch = pmatch;
148                     break;
149                 }
150
151
152                 /* If we have multiple regex-only childs,
153                  * do not attempt to go any further with them.
154                  */
155                 if(child_node->osdecoder->get_next)
156                 {
157                     do
158                     {
159                         child_node = child_node->next;
160                     }while(child_node && child_node->osdecoder->get_next);
161
162                     if(!child_node)
163                         return;
164
165                     child_node = child_node->next;
166                     nnode = NULL;
167                 }
168                 else
169                 {
170                     child_node = child_node->next;
171                     nnode = NULL;
172                 }
173             }
174         }
175
176
177         /* Nothing matched */
178         if(!nnode)
179             return;
180
181
182         /* If we have a external decoder, execute it */
183         if(nnode->plugindecoder)
184         {
185             nnode->plugindecoder(lf);
186             return;
187         }
188
189
190         /* Getting the regex */
191         while(child_node)
192         {
193             if(nnode->regex)
194             {
195                 int i = 0;
196
197                 /* With regex we have multiple options
198                  * regarding the offset:
199                  * after the prematch,
200                  * after the parent,
201                  * after some previous regex,
202                  * or any offset
203                  */
204                 if(nnode->regex_offset)
205                 {
206                     if(nnode->regex_offset & AFTER_PARENT)
207                     {
208                         llog = pmatch;
209                     }
210                     else if(nnode->regex_offset & AFTER_PREMATCH)
211                     {
212                         llog = cmatch;
213                     }
214                     else if(nnode->regex_offset & AFTER_PREVREGEX)
215                     {
216                         if(!regex_prev)
217                             llog = cmatch;
218                         else
219                             llog = regex_prev;
220                     }
221                 }
222                 else
223                 {
224                     llog = lf->log;
225                 }
226
227                 /* If Regex does not match, return */
228                 if(!(regex_prev = OSRegex_Execute(llog, nnode->regex)))
229                 {
230                     if(nnode->get_next)
231                     {
232                         child_node = child_node->next;
233                         nnode = child_node->osdecoder;
234                         continue;
235                     }
236                     return;
237                 }
238
239
240                 /* Fixing next pointer */
241                 if(*regex_prev != '\0')
242                     regex_prev++;
243
244                 while(nnode->regex->sub_strings[i])
245                 {
246                     if(nnode->order[i])
247                     {
248                         nnode->order[i](lf, nnode->regex->sub_strings[i]);
249                         nnode->regex->sub_strings[i] = NULL;
250                         i++;
251                         continue;
252                     }
253
254                     /* We do not free any memory used above */
255                     os_free(nnode->regex->sub_strings[i]);
256                     nnode->regex->sub_strings[i] = NULL;
257                     i++;
258                 }
259
260                 /* If we have a next regex, try getting it */
261                 if(nnode->get_next)
262                 {
263                     child_node = child_node->next;
264                     nnode = child_node->osdecoder;
265                     continue;
266                 }
267
268                 break;
269             }
270
271             /* If we don't have a regex, we may leave now */
272             return;
273         }
274
275         /* ok to return  */
276         return;
277     }while((node=node->next) != NULL);
278
279     #ifdef TESTRULE
280     if(!alert_only)
281     {
282         print_out("       No decoder matched.");
283     }
284     #endif
285
286 }
287
288
289 /*** Event decoders ****/
290 void *DstUser_FP(Eventinfo *lf, char *field)
291 {
292     #ifdef TESTRULE
293     if(!alert_only)print_out("       dstuser: '%s'", field);
294     #endif
295
296     lf->dstuser = field;
297     return(NULL);
298 }
299 void *SrcUser_FP(Eventinfo *lf, char *field)
300 {
301     #ifdef TESTRULE
302     if(!alert_only)print_out("       srcuser: '%s'", field);
303     #endif
304
305     lf->srcuser = field;
306     return(NULL);
307 }
308 void *SrcIP_FP(Eventinfo *lf, char *field)
309 {
310     #ifdef TESTRULE
311     if(!alert_only)print_out("       srcip: '%s'", field);
312     #endif
313
314     lf->srcip = field;
315     return(NULL);
316 }
317 void *DstIP_FP(Eventinfo *lf, char *field)
318 {
319     #ifdef TESTRULE
320     if(!alert_only)print_out("       dstip: '%s'", field);
321     #endif
322
323     lf->dstip = field;
324     return(NULL);
325 }
326 void *SrcPort_FP(Eventinfo *lf, char *field)
327 {
328     #ifdef TESTRULE
329     if(!alert_only)print_out("       srcport: '%s'", field);
330     #endif
331
332     lf->srcport = field;
333     return(NULL);
334 }
335 void *DstPort_FP(Eventinfo *lf, char *field)
336 {
337     #ifdef TESTRULE
338     if(!alert_only)print_out("       dstport: '%s'", field);
339     #endif
340
341     lf->dstport = field;
342     return(NULL);
343 }
344 void *Protocol_FP(Eventinfo *lf, char *field)
345 {
346     #ifdef TESTRULE
347     if(!alert_only)print_out("       proto: '%s'", field);
348     #endif
349
350     lf->protocol = field;
351     return(NULL);
352 }
353 void *Action_FP(Eventinfo *lf, char *field)
354 {
355     #ifdef TESTRULE
356     if(!alert_only)print_out("       action: '%s'", field);
357     #endif
358
359     lf->action = field;
360     return(NULL);
361 }
362 void *ID_FP(Eventinfo *lf, char *field)
363 {
364     #ifdef TESTRULE
365     if(!alert_only)print_out("       id: '%s'", field);
366     #endif
367
368     lf->id = field;
369     return(NULL);
370 }
371 void *Url_FP(Eventinfo *lf, char *field)
372 {
373     #ifdef TESTRULE
374     if(!alert_only)print_out("       url: '%s'", field);
375     #endif
376
377     lf->url = field;
378     return(NULL);
379 }
380 void *Data_FP(Eventinfo *lf, char *field)
381 {
382     #ifdef TESTRULE
383     if(!alert_only)print_out("       extra_data: '%s'", field);
384     #endif
385
386     lf->data = field;
387     return(NULL);
388 }
389 void *Status_FP(Eventinfo *lf, char *field)
390 {
391     #ifdef TESTRULE
392     if(!alert_only)print_out("       status: '%s'", field);
393     #endif
394
395     lf->status = field;
396     return(NULL);
397 }
398 void *SystemName_FP(Eventinfo *lf, char *field)
399 {
400     #ifdef TESTRULE
401     if(!alert_only)print_out("       system_name: '%s'", field);
402     #endif
403
404     lf->systemname = field;
405     return(NULL);
406 }
407 void *None_FP(Eventinfo *lf, char *field)
408 {
409     free(field);
410     return(NULL);
411 }
412
413
414 /* EOF */