Imported Upstream version 2.3
[ossec-hids.git] / src / shared / report_op.c
1 /* @(#) $Id: report_op.c,v 1.2 2009/06/24 18:53:08 dcid Exp $ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All rights reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 3) as published by the FSF - Free Software
9  * Foundation
10  */
11
12
13 #include "shared.h"
14
15
16 /** Helper functions. */
17
18 /* Sort function used by OSStore sort.
19  * Returns if d1 > d2. 
20  */
21 void *_os_report_sort_compare(void *d1, void *d2)
22 {
23    OSList *d1l = (OSList *)d1;
24    OSList *d2l = (OSList *)d2; 
25
26    if(d1l->currently_size > d2l->currently_size)
27    {
28        return(d1l);
29    }
30
31    return(NULL);
32 }
33
34
35 /* Compares if the id is present in the string. */
36 int _os_report_str_int_compare(char *str, int id)
37 {
38     int pt_check = 0;
39     
40     do
41     {
42         if((*str == ',')||(*str == ' '))
43         {
44             pt_check = 0;
45             continue;
46         }
47         else if(*str == '\0')
48         {
49             break;
50         }
51         else if(isdigit((int)*str))
52         {
53             if(pt_check == 0)
54             {
55                 if(id == atoi(str))
56                 {
57                     return(1);
58                 }
59             }
60             pt_check = 1;
61         }
62         else
63         {
64             return(-1);
65         }
66     }while(*str++ != '\0');
67
68     return(0);
69 }
70
71
72
73 /* Check if the al_data should be filtered. */
74 int _os_report_check_filters(alert_data *al_data, report_filter *r_filter)
75 {
76     /* Checking for the filters. */
77     if(r_filter->group)
78     {
79         if(!strstr(al_data->group, r_filter->group))
80         {
81             return(0);
82         }
83     }
84     if(r_filter->rule)
85     {
86         if(_os_report_str_int_compare(r_filter->rule, al_data->rule) != 1)
87         {
88             return(0);
89         }
90     }
91     if(r_filter->location)
92     {
93         if(!OS_Match2(r_filter->location, al_data->location))
94         {
95             return(0);
96         }
97     }
98     if(r_filter->level)
99     {
100         if(al_data->level < atoi(r_filter->level))
101         {
102             return(0);
103         }
104     }
105
106     return(1);
107 }
108
109
110
111 /* Sets the proper value for the related entries. */
112 int _report_filter_value(char *filter_by, int prev_filter)
113 {
114     if(strcmp(filter_by, "group") == 0)
115     {
116         if(!(prev_filter & REPORT_REL_GROUP))
117         {
118             prev_filter|=REPORT_REL_GROUP;
119         }
120         return(prev_filter);
121     }
122     else if(strcmp(filter_by, "rule") == 0)
123     {
124         if(!(prev_filter & REPORT_REL_RULE))
125         {
126             prev_filter|=REPORT_REL_RULE;
127         }
128         return(prev_filter);
129     }
130     else if(strcmp(filter_by, "level") == 0)
131     {
132         if(!(prev_filter & REPORT_REL_LEVEL))
133         {
134             prev_filter|=REPORT_REL_LEVEL;
135         }
136         return(prev_filter);
137     }
138     else if(strcmp(filter_by, "location") == 0)
139     {
140         if(!(prev_filter & REPORT_REL_LOCATION))
141         {
142             prev_filter|=REPORT_REL_LOCATION;
143         }
144         return(prev_filter);
145     }
146     else if(strcmp(filter_by, "srcip") == 0)
147     {
148         if(!(prev_filter & REPORT_REL_SRCIP))
149         {
150             prev_filter|=REPORT_REL_SRCIP;
151         }
152         return(prev_filter);
153     }
154     else if(strcmp(filter_by, "user") == 0)
155     {
156         if(!(prev_filter & REPORT_REL_USER))
157         {
158             prev_filter|=REPORT_REL_USER;
159         }
160         return(prev_filter);
161     }
162     else
163     {
164         merror("%s: ERROR: Invalid relation '%s'.", ARGV0, filter_by);
165         return(-1);
166     }   
167 }
168
169
170
171 /* Prints related entries. */
172 int _os_report_print_related(int print_related, OSList *st_data)
173 {
174     OSListNode *list_entry;
175     alert_data *list_aldata;
176     alert_data *saved_aldata;
177     
178                 
179     list_entry = OSList_GetFirstNode(st_data);
180     while(list_entry)
181     {
182         saved_aldata = (alert_data *)list_entry->data;
183         
184         /* Removing duplicates. */
185         list_entry = list_entry->prev;
186         while(list_entry)
187         {
188             if(print_related & REPORT_REL_LOCATION)
189             {
190                 list_aldata = (alert_data *)list_entry->data;
191                 if(strcmp(list_aldata->location, saved_aldata->location) == 0)
192                 {
193                     break;
194                 }
195             }
196
197             else if(print_related & REPORT_REL_GROUP)
198             {
199                 list_aldata = (alert_data *)list_entry->data;
200                 if(strcmp(list_aldata->group, saved_aldata->group) == 0)
201                 {
202                     break;
203                 }
204             }
205
206             else if(print_related & REPORT_REL_RULE)
207             {
208                 list_aldata = (alert_data *)list_entry->data;
209                 if(list_aldata->rule == saved_aldata->rule)
210                 {
211                     break;
212                 }
213             }
214
215             else if(print_related & REPORT_REL_USER)
216             {
217                 list_aldata = (alert_data *)list_entry->data;
218                 if(strcmp(list_aldata->user, saved_aldata->user) == 0)
219                 {
220                     break;
221                 }
222             }
223
224             else if(print_related & REPORT_REL_SRCIP)
225             {
226                 list_aldata = (alert_data *)list_entry->data;
227                 if(strcmp(list_aldata->srcip, saved_aldata->srcip) == 0)
228                 {
229                     break;
230                 }
231             }
232
233             else if(print_related & REPORT_REL_LEVEL)
234             {
235                 list_aldata = (alert_data *)list_entry->data;
236                 if(list_aldata->level == saved_aldata->level)
237                 {
238                     break;
239                 }
240             }
241             list_entry = list_entry->prev;
242         }
243
244         if(!list_entry)
245         {
246             if(print_related & REPORT_REL_LOCATION)
247                 print_out("   location: '%s'", saved_aldata->location);
248             else if(print_related & REPORT_REL_GROUP)
249                 print_out("   group: '%s'", saved_aldata->group);
250             else if(print_related & REPORT_REL_RULE)
251                 print_out("   rule: '%d'", saved_aldata->rule);
252             else if(print_related & REPORT_REL_SRCIP)
253                 print_out("   srcip: '%s'", saved_aldata->srcip);
254             else if(print_related & REPORT_REL_USER)
255                 print_out("   user: '%s'", saved_aldata->user);
256             else if(print_related & REPORT_REL_LEVEL)
257                 print_out("   level: '%d'", saved_aldata->level);
258         }
259
260         list_entry = OSList_GetNextNode(st_data);
261     }
262
263     return(0);
264 }
265
266
267
268 /* Add the entry to the hash. */
269 int _os_report_add_tostore(char *key, OSStore *top, void *data)
270 {
271     OSList *top_list;
272
273     /* Adding data to the hash. */
274     top_list = OSStore_Get(top, key);
275     if(top_list)
276     {
277         OSList_AddData(top_list, data);
278     }
279     else
280     {
281         top_list = OSList_Create();
282         if(!top_list)
283         {
284             merror(MEM_ERROR, ARGV0);
285             return(0);
286         }
287         OSList_AddData(top_list, data);
288
289         OSStore_Put(top, key, top_list);
290     }
291
292     return(1);
293 }
294
295
296
297 void os_report_printtop(void *topstore_pt, char *hname, int print_related)
298 {
299     OSStore *topstore = (OSStore *)topstore_pt;
300     OSStoreNode *next_node;
301     
302     if(!print_related)
303     {
304         print_out("Top entries for '%s':", hname);
305         print_out("------------------------------------------------");
306     }
307     else
308     {
309         print_out("Related entries for '%s':", hname);
310         print_out("------------------------------------------------");
311     }
312     
313
314     next_node = OSStore_GetFirstNode(topstore);
315     while(next_node)
316     {
317         OSList *st_data = (OSList *)next_node->data;
318         char *lkey = (char *)next_node->key;
319
320
321         /* With location we leave more space to be clearer. */
322         if(!print_related)
323         {
324             if(strlen(lkey) > 46)
325             {
326                 lkey[44] = '.';
327                 lkey[45] = '.';
328                 lkey[46] = '\0';
329             }
330
331             print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size);
332         }
333
334
335         /* Print each destination. */
336         else
337         {
338             print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size);
339
340             if(print_related & REPORT_REL_LOCATION)
341                 _os_report_print_related(REPORT_REL_LOCATION, st_data);
342             if(print_related & REPORT_REL_SRCIP)
343                 _os_report_print_related(REPORT_REL_SRCIP, st_data);
344             if(print_related & REPORT_REL_USER)
345                 _os_report_print_related(REPORT_REL_USER, st_data);
346             if(print_related & REPORT_REL_RULE)
347                 _os_report_print_related(REPORT_REL_RULE, st_data);
348             if(print_related & REPORT_REL_GROUP)
349                 _os_report_print_related(REPORT_REL_GROUP, st_data);
350             if(print_related & REPORT_REL_LEVEL)
351                 _os_report_print_related(REPORT_REL_LEVEL, st_data);
352
353         }
354
355         next_node = next_node->next;
356     }
357
358
359     print_out(" ");
360     print_out(" ");
361     return; 
362 }
363
364
365
366 void os_ReportdStart(report_filter *r_filter)
367 {
368     int alerts_processed = 0;
369     int alerts_filtered = 0;
370     char *first_alert = NULL;
371     char *last_alert = NULL;
372     
373     
374     time_t tm;     
375     struct tm *p;       
376     
377
378     file_queue *fileq;
379     alert_data *al_data;
380
381
382     /* Getting current time before starting */
383     tm = time(NULL);
384     p = localtime(&tm); 
385
386
387
388     /* Creating top hashes. */
389     r_filter->top_user = OSStore_Create();
390     r_filter->top_srcip = OSStore_Create();
391     r_filter->top_level = OSStore_Create();
392     r_filter->top_rule = OSStore_Create();
393     r_filter->top_group = OSStore_Create();
394     r_filter->top_location = OSStore_Create();
395
396     
397
398     /* Initating file queue - to read the alerts */
399     os_calloc(1, sizeof(file_queue), fileq);
400     fileq->fp = stdin;
401     Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET);
402
403
404     /* Reading the alerts. */
405     while(1)
406     {
407         /* Get message if available */
408         al_data = Read_FileMon(fileq, p, 1);
409         if(!al_data)
410         {
411             verbose("%s: Report completed. Creating output...", ARGV0);
412             break;
413         }
414
415         alerts_processed++;
416         
417
418         /* Checking the filters. */
419         if(!_os_report_check_filters(al_data, r_filter))
420         {
421             FreeAlertData(al_data);
422             continue;
423         }
424         
425         
426         alerts_filtered++;
427
428
429         /* Setting first and last alert for summary. */
430         if(!first_alert)
431             first_alert = al_data->date;
432         last_alert = al_data->date;
433         
434         
435         /* Adding source ip if it is set properly. */
436         if(strcmp(al_data->srcip, "(none)") != 0)
437             _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data);
438
439         
440         /* Adding user if it is set properly. */
441         if(strcmp(al_data->user, "(none)") != 0)
442             _os_report_add_tostore(al_data->user, r_filter->top_user, al_data);
443
444
445         /* Adding level and severity. */
446         {
447             char mlevel[16];
448             char mrule[76 +1];
449             mrule[76] = '\0';
450             snprintf(mlevel, 16, "Severity %d" , al_data->level);
451             snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment);
452             
453             _os_report_add_tostore(strdup(mlevel), r_filter->top_level, 
454                                    al_data);
455             _os_report_add_tostore(strdup(mrule), r_filter->top_rule, 
456                                    al_data);
457         }
458
459         /* Dealing with the group. */
460         {
461             char *tmp_str;
462             char **mgroup;
463
464             mgroup = OS_StrBreak(',', al_data->group, 32);
465             if(mgroup)
466             {
467                 while(*mgroup)
468                 {
469                     tmp_str = *mgroup;
470                     while(*tmp_str == ' ')
471                         tmp_str++;
472                     if(*tmp_str == '\0')
473                     {
474                         mgroup++;
475                         continue;
476                     }
477                     
478                     _os_report_add_tostore(tmp_str, r_filter->top_group, 
479                                            al_data);
480                     mgroup++;
481                 }
482             }
483             else
484             {
485                 tmp_str = al_data->group;
486                 while(*tmp_str == ' ')
487                     tmp_str++;
488                 if(*tmp_str != '\0')
489                 {
490                     _os_report_add_tostore(tmp_str, r_filter->top_group, 
491                                            al_data);
492                 }
493             }
494         }
495
496
497         /* Adding to the location top filter. */        
498         _os_report_add_tostore(al_data->location, r_filter->top_location, 
499                                al_data);
500     }
501
502
503
504     print_out(" ");
505     if(r_filter->report_name)
506         print_out("Report '%s' completed.", r_filter->report_name);
507     else
508         print_out("Report completed. ==");
509     print_out("------------------------------------------------");
510             
511     print_out("->Processed alerts: %d", alerts_processed);
512     print_out("->Post-filtering alerts: %d", alerts_filtered);
513     print_out("->First alert: %s", first_alert);
514     print_out("->Last alert: %s", last_alert);
515     print_out(" ");
516     print_out(" ");
517     
518     OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare);
519     OSStore_Sort(r_filter->top_user,  _os_report_sort_compare);
520     OSStore_Sort(r_filter->top_level, _os_report_sort_compare);
521     OSStore_Sort(r_filter->top_group, _os_report_sort_compare);
522     OSStore_Sort(r_filter->top_location, _os_report_sort_compare);
523     OSStore_Sort(r_filter->top_rule, _os_report_sort_compare);
524     
525     if(r_filter->top_srcip)
526         os_report_printtop(r_filter->top_srcip, "Source ip", 0);
527     
528     if(r_filter->top_user)
529         os_report_printtop(r_filter->top_user, "Username", 0);
530     
531     if(r_filter->top_level)
532         os_report_printtop(r_filter->top_level, "Level", 0);
533     
534     if(r_filter->top_group)
535         os_report_printtop(r_filter->top_group, "Group", 0);
536     
537     if(r_filter->top_location)
538         os_report_printtop(r_filter->top_location, "Location", 0);
539     
540     if(r_filter->top_rule)
541         os_report_printtop(r_filter->top_rule, "Rule", 0);
542
543
544     /* Print related events. */
545     if(r_filter->related_srcip)
546         os_report_printtop(r_filter->top_srcip, "Source ip", 
547                            r_filter->related_srcip);
548
549     if(r_filter->related_user)
550         os_report_printtop(r_filter->top_user, "Username", 
551                            r_filter->related_user);
552
553     if(r_filter->related_level)
554         os_report_printtop(r_filter->top_level, "Level", 
555                            r_filter->related_level);
556
557     if(r_filter->related_group)
558         os_report_printtop(r_filter->top_group, "Group", 
559                            r_filter->related_group);
560     
561     if(r_filter->related_location)
562         os_report_printtop(r_filter->top_location, "Location", 
563                            r_filter->related_location);
564     
565     if(r_filter->related_rule)
566         os_report_printtop(r_filter->top_rule, "Rule", 
567                            r_filter->related_rule);
568 }
569
570
571
572
573
574 /** int os_report_check_filters(char *filter_by, char *filter_value,
575  *                              report_filter *r_filter)
576  * Checks the configuration filters.
577  */
578 int os_report_configfilter(char *filter_by, char *filter_value, 
579                            report_filter *r_filter, int arg_type)
580 {
581     if(!filter_by || !filter_value)
582     {
583         return(-1);
584     }
585     
586     if(arg_type == REPORT_FILTER)
587     {
588         if(strcmp(filter_by, "group") == 0)
589         {
590             r_filter->group = filter_value;    
591         }
592         else if(strcmp(filter_by, "rule") == 0)
593         {
594             r_filter->rule = filter_value;    
595         }
596         else if(strcmp(filter_by, "level") == 0)
597         {
598             r_filter->level = filter_value;    
599         }
600         else if(strcmp(filter_by, "location") == 0)
601         {
602             r_filter->location = filter_value;    
603         }
604         else
605         {
606             merror("%s: ERROR: Invalid filter '%s'.", ARGV0, filter_by);
607             return(-1);
608         }
609     }
610     else
611     {
612         if(strcmp(filter_by, "group") == 0)
613         {
614             r_filter->related_group = 
615             _report_filter_value(filter_value, r_filter->related_group);
616
617             if(r_filter->related_group == -1)
618                 return(-1);
619         }
620         else if(strcmp(filter_by, "rule") == 0)
621         {
622             r_filter->related_rule = 
623             _report_filter_value(filter_value, r_filter->related_rule);
624
625             if(r_filter->related_rule == -1)
626                 return(-1);
627         }
628         else if(strcmp(filter_by, "level") == 0)
629         {
630             r_filter->related_level = 
631             _report_filter_value(filter_value, r_filter->related_level);
632
633             if(r_filter->related_level == -1)
634                 return(-1);
635         }
636         else if(strcmp(filter_by, "location") == 0)
637         {
638             r_filter->related_location = 
639             _report_filter_value(filter_value, r_filter->related_location);
640
641             if(r_filter->related_location == -1)
642                 return(-1);
643         }
644         else if(strcmp(filter_by, "srcip") == 0)
645         {
646             r_filter->related_srcip = 
647             _report_filter_value(filter_value, r_filter->related_srcip);
648
649             if(r_filter->related_srcip == -1)
650                 return(-1);
651         }
652         else if(strcmp(filter_by, "user") == 0)
653         {
654             r_filter->related_user = 
655             _report_filter_value(filter_value, r_filter->related_user);
656         
657             if(r_filter->related_user == -1)
658                 return(-1);
659         }
660         else
661         {
662             merror("%s: ERROR: Invalid related entry '%s'.", ARGV0, filter_by);
663             return(-1);
664         }
665     }
666
667     return(0);
668 }
669
670
671
672 /* EOF */