1 /* @(#) $Id: ./src/shared/report_op.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
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
17 /** Helper functions. */
18 FILE *__g_rtype = NULL;
19 void l_print_out(const char *msg, ...)
26 (void)vfprintf(__g_rtype, msg, args);
27 (void)fprintf(__g_rtype, "\n");
31 (void)vfprintf(stderr, msg, args);
32 (void)fprintf(stderr, "\n");
38 /* Sort function used by OSStore sort.
41 void *_os_report_sort_compare(void *d1, void *d2)
43 OSList *d1l = (OSList *)d1;
44 OSList *d2l = (OSList *)d2;
46 if(d1l->currently_size > d2l->currently_size)
55 /* Print output header. */
56 void _os_header_print(int t, char *hname)
60 l_print_out("Top entries for '%s':", hname);
61 l_print_out("------------------------------------------------");
65 l_print_out("Related entries for '%s':", hname);
66 l_print_out("------------------------------------------------");
71 /* Compares if the id is present in the string. */
72 int _os_report_str_int_compare(char *str, int id)
78 if((*str == ',')||(*str == ' '))
87 else if(isdigit((int)*str))
102 }while(*str++ != '\0');
109 /* Check if the al_data should be filtered. */
110 int _os_report_check_filters(alert_data *al_data, report_filter *r_filter)
112 /* Checking for the filters. */
115 if(!strstr(al_data->group, r_filter->group))
122 if(_os_report_str_int_compare(r_filter->rule, al_data->rule) != 1)
127 if(r_filter->location)
129 if(!OS_Match(r_filter->location, al_data->location))
136 if(al_data->level < atoi(r_filter->level))
143 if(!strstr(al_data->srcip, r_filter->srcip))
150 if(!strstr(al_data->user, r_filter->user))
157 if(!strstr(al_data->filename, r_filter->files))
167 /* Sets the proper value for the related entries. */
168 int _report_filter_value(char *filter_by, int prev_filter)
170 if(strcmp(filter_by, "group") == 0)
172 if(!(prev_filter & REPORT_REL_GROUP))
174 prev_filter|=REPORT_REL_GROUP;
178 else if(strcmp(filter_by, "rule") == 0)
180 if(!(prev_filter & REPORT_REL_RULE))
182 prev_filter|=REPORT_REL_RULE;
186 else if(strcmp(filter_by, "level") == 0)
188 if(!(prev_filter & REPORT_REL_LEVEL))
190 prev_filter|=REPORT_REL_LEVEL;
194 else if(strcmp(filter_by, "location") == 0)
196 if(!(prev_filter & REPORT_REL_LOCATION))
198 prev_filter|=REPORT_REL_LOCATION;
202 else if(strcmp(filter_by, "srcip") == 0)
204 if(!(prev_filter & REPORT_REL_SRCIP))
206 prev_filter|=REPORT_REL_SRCIP;
210 else if(strcmp(filter_by, "user") == 0)
212 if(!(prev_filter & REPORT_REL_USER))
214 prev_filter|=REPORT_REL_USER;
218 else if(strcmp(filter_by, "filename") == 0)
220 if(!(prev_filter & REPORT_REL_FILE))
222 prev_filter|=REPORT_REL_FILE;
228 merror("%s: ERROR: Invalid relation '%s'.", __local_name, filter_by);
235 /* Prints related entries. */
236 int _os_report_print_related(int print_related, OSList *st_data)
238 OSListNode *list_entry;
239 alert_data *list_aldata;
240 alert_data *saved_aldata;
243 list_entry = OSList_GetFirstNode(st_data);
246 saved_aldata = (alert_data *)list_entry->data;
248 /* Removing duplicates. */
249 list_entry = list_entry->prev;
252 if(print_related & REPORT_REL_LOCATION)
254 list_aldata = (alert_data *)list_entry->data;
255 if(strcmp(list_aldata->location, saved_aldata->location) == 0)
261 else if(print_related & REPORT_REL_GROUP)
263 list_aldata = (alert_data *)list_entry->data;
264 if(strcmp(list_aldata->group, saved_aldata->group) == 0)
270 else if(print_related & REPORT_REL_RULE)
272 list_aldata = (alert_data *)list_entry->data;
273 if(list_aldata->rule == saved_aldata->rule)
279 else if(print_related & REPORT_REL_USER)
281 list_aldata = (alert_data *)list_entry->data;
282 if(list_aldata->user == NULL || saved_aldata->user == NULL)
285 else if(strcmp(list_aldata->user, saved_aldata->user) == 0)
291 else if(print_related & REPORT_REL_SRCIP)
293 list_aldata = (alert_data *)list_entry->data;
294 if(list_aldata->srcip == NULL || saved_aldata->srcip == NULL)
297 else if(strcmp(list_aldata->srcip, saved_aldata->srcip) == 0)
303 else if(print_related & REPORT_REL_LEVEL)
305 list_aldata = (alert_data *)list_entry->data;
306 if(list_aldata->level == saved_aldata->level)
311 else if(print_related & REPORT_REL_FILE)
313 list_aldata = (alert_data *)list_entry->data;
314 if(list_aldata->filename == NULL || saved_aldata->filename == NULL)
317 else if(strcmp(list_aldata->filename, saved_aldata->filename) == 0)
322 list_entry = list_entry->prev;
327 if(print_related & REPORT_REL_LOCATION)
328 l_print_out(" location: '%s'", saved_aldata->location);
329 else if(print_related & REPORT_REL_GROUP)
330 l_print_out(" group: '%s'", saved_aldata->group);
331 else if(print_related & REPORT_REL_RULE)
332 l_print_out(" rule: '%d'", saved_aldata->rule);
333 else if(print_related & REPORT_REL_SRCIP && saved_aldata->srcip)
334 l_print_out(" srcip: '%s'", saved_aldata->srcip);
335 else if(print_related & REPORT_REL_USER && saved_aldata->user)
336 l_print_out(" user: '%s'", saved_aldata->user);
337 else if(print_related & REPORT_REL_LEVEL)
338 l_print_out(" level: '%d'", saved_aldata->level);
339 else if(print_related & REPORT_REL_FILE && saved_aldata->filename)
340 l_print_out(" filename: '%s'", saved_aldata->filename);
343 list_entry = OSList_GetNextNode(st_data);
351 /* Add the entry to the hash. */
352 int _os_report_add_tostore(char *key, OSStore *top, void *data)
356 /* Adding data to the hash. */
357 top_list = OSStore_Get(top, key);
360 OSList_AddData(top_list, data);
364 top_list = OSList_Create();
367 merror(MEM_ERROR, __local_name);
370 OSList_AddData(top_list, data);
372 OSStore_Put(top, key, top_list);
380 void os_report_printtop(void *topstore_pt, char *hname, int print_related)
383 OSStore *topstore = (OSStore *)topstore_pt;
384 OSStoreNode *next_node;
386 next_node = OSStore_GetFirstNode(topstore);
389 OSList *st_data = (OSList *)next_node->data;
390 char *lkey = (char *)next_node->key;
393 /* With location we leave more space to be clearer. */
396 if(strlen(lkey) > 46)
405 _os_header_print(print_related, hname);
408 l_print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size);
412 /* Print each destination. */
417 _os_header_print(print_related, hname);
420 l_print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size);
422 if(print_related & REPORT_REL_LOCATION)
423 _os_report_print_related(REPORT_REL_LOCATION, st_data);
424 if(print_related & REPORT_REL_SRCIP)
425 _os_report_print_related(REPORT_REL_SRCIP, st_data);
426 if(print_related & REPORT_REL_USER)
427 _os_report_print_related(REPORT_REL_USER, st_data);
428 if(print_related & REPORT_REL_RULE)
429 _os_report_print_related(REPORT_REL_RULE, st_data);
430 if(print_related & REPORT_REL_GROUP)
431 _os_report_print_related(REPORT_REL_GROUP, st_data);
432 if(print_related & REPORT_REL_LEVEL)
433 _os_report_print_related(REPORT_REL_LEVEL, st_data);
434 if(print_related & REPORT_REL_FILE)
435 _os_report_print_related(REPORT_REL_FILE, st_data);
439 next_node = next_node->next;
453 void os_ReportdStart(report_filter *r_filter)
455 int alerts_processed = 0;
456 int alerts_filtered = 0;
457 char *first_alert = NULL;
458 char *last_alert = NULL;
459 void **data_to_clean = NULL;
470 /* Getting current time before starting */
477 /* Initating file queue - to read the alerts */
478 os_calloc(1, sizeof(file_queue), fileq);
480 if(r_filter->report_type == REPORT_TYPE_DAILY && r_filter->filename)
482 fileq->fp = fopen(r_filter->filename, "r");
485 merror("%s: ERROR: Unable to open alerts file to generate report.", __local_name);
490 __g_rtype = r_filter->fp;
499 /* Creating top hashes. */
500 r_filter->top_user = OSStore_Create();
501 r_filter->top_srcip = OSStore_Create();
502 r_filter->top_level = OSStore_Create();
503 r_filter->top_rule = OSStore_Create();
504 r_filter->top_group = OSStore_Create();
505 r_filter->top_location = OSStore_Create();
506 r_filter->top_files = OSStore_Create();
508 Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET);
512 /* Reading the alerts. */
515 /* Get message if available */
516 al_data = Read_FileMon(fileq, p, 1);
525 /* Checking the filters. */
526 if(!_os_report_check_filters(al_data, r_filter))
528 FreeAlertData(al_data);
534 data_to_clean = os_AddPtArray(al_data, data_to_clean);
537 /* Setting first and last alert for summary. */
539 first_alert = al_data->date;
540 last_alert = al_data->date;
543 /* Adding source ip if it is set properly. */
544 if(al_data->srcip != NULL && strcmp(al_data->srcip, "(none)") != 0)
545 _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data);
548 /* Adding user if it is set properly. */
549 if(al_data->user != NULL && strcmp(al_data->user, "(none)") != 0)
550 _os_report_add_tostore(al_data->user, r_filter->top_user, al_data);
553 /* Adding level and severity. */
558 snprintf(mlevel, 16, "Severity %d" , al_data->level);
559 snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment);
561 _os_report_add_tostore(strdup(mlevel), r_filter->top_level,
563 _os_report_add_tostore(strdup(mrule), r_filter->top_rule,
567 /* Dealing with the group. */
572 mgroup = OS_StrBreak(',', al_data->group, 32);
578 while(*tmp_str == ' ')
586 _os_report_add_tostore(tmp_str, r_filter->top_group,
593 tmp_str = al_data->group;
594 while(*tmp_str == ' ')
598 _os_report_add_tostore(tmp_str, r_filter->top_group,
605 /* Adding to the location top filter. */
606 _os_report_add_tostore(al_data->location, r_filter->top_location,
610 if(al_data->filename != NULL)
612 _os_report_add_tostore(al_data->filename, r_filter->top_files,
617 /* No report available */
618 if(alerts_filtered == 0)
620 if(!r_filter->report_name)
621 merror("%s: INFO: Report completed and zero alerts post-filter.", __local_name);
623 merror("%s: INFO: Report '%s' completed and zero alerts post-filter.", __local_name, r_filter->report_name);
628 if(r_filter->report_name)
629 verbose("%s: INFO: Report '%s' completed. Creating output...", __local_name, r_filter->report_name);
631 verbose("%s: INFO: Report completed. Creating output...", __local_name);
635 if(r_filter->report_name)
636 l_print_out("Report '%s' completed.", r_filter->report_name);
638 l_print_out("Report completed. ==");
639 l_print_out("------------------------------------------------");
641 l_print_out("->Processed alerts: %d", alerts_processed);
642 l_print_out("->Post-filtering alerts: %d", alerts_filtered);
643 l_print_out("->First alert: %s", first_alert);
644 l_print_out("->Last alert: %s", last_alert);
648 OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare);
649 OSStore_Sort(r_filter->top_user, _os_report_sort_compare);
650 OSStore_Sort(r_filter->top_level, _os_report_sort_compare);
651 OSStore_Sort(r_filter->top_group, _os_report_sort_compare);
652 OSStore_Sort(r_filter->top_location, _os_report_sort_compare);
653 OSStore_Sort(r_filter->top_rule, _os_report_sort_compare);
654 OSStore_Sort(r_filter->top_files, _os_report_sort_compare);
656 if(r_filter->top_srcip)
657 os_report_printtop(r_filter->top_srcip, "Source ip", 0);
659 if(r_filter->top_user)
660 os_report_printtop(r_filter->top_user, "Username", 0);
662 if(r_filter->top_level)
663 os_report_printtop(r_filter->top_level, "Level", 0);
665 if(r_filter->top_group)
666 os_report_printtop(r_filter->top_group, "Group", 0);
668 if(r_filter->top_location)
669 os_report_printtop(r_filter->top_location, "Location", 0);
671 if(r_filter->top_rule)
672 os_report_printtop(r_filter->top_rule, "Rule", 0);
674 if(r_filter->top_files)
675 os_report_printtop(r_filter->top_files, "Filenames", 0);
678 /* Print related events. */
679 if(r_filter->related_srcip)
680 os_report_printtop(r_filter->top_srcip, "Source ip",
681 r_filter->related_srcip);
683 if(r_filter->related_user)
684 os_report_printtop(r_filter->top_user, "Username",
685 r_filter->related_user);
687 if(r_filter->related_level)
688 os_report_printtop(r_filter->top_level, "Level",
689 r_filter->related_level);
691 if(r_filter->related_group)
692 os_report_printtop(r_filter->top_group, "Group",
693 r_filter->related_group);
695 if(r_filter->related_location)
696 os_report_printtop(r_filter->top_location, "Location",
697 r_filter->related_location);
699 if(r_filter->related_rule)
700 os_report_printtop(r_filter->top_rule, "Rule",
701 r_filter->related_rule);
703 if(r_filter->related_file)
704 os_report_printtop(r_filter->top_files, "Filename",
705 r_filter->related_file);
708 /* If we have to dump the alerts. */
713 if(r_filter->show_alerts)
715 l_print_out("Log dump:");
716 l_print_out("------------------------------------------------");
718 while(data_to_clean[i])
720 alert_data *md = data_to_clean[i];
721 if(r_filter->show_alerts)
722 l_print_out("%s %s\nRule: %d (level %d) -> '%s'\n%s\n\n", md->date, md->location, md->rule, md->level, md->comment, md->log[0]);
727 data_to_clean = NULL;
735 /** int os_report_check_filters(char *filter_by, char *filter_value,
736 * report_filter *r_filter)
737 * Checks the configuration filters.
739 int os_report_configfilter(char *filter_by, char *filter_value,
740 report_filter *r_filter, int arg_type)
742 if(!filter_by || !filter_value)
747 if(arg_type == REPORT_FILTER)
749 if(strcmp(filter_by, "group") == 0)
751 r_filter->group = filter_value;
753 else if(strcmp(filter_by, "rule") == 0)
755 r_filter->rule = filter_value;
757 else if(strcmp(filter_by, "level") == 0)
759 r_filter->level = filter_value;
761 else if(strcmp(filter_by, "location") == 0)
763 r_filter->location = filter_value;
765 else if(strcmp(filter_by, "user") == 0)
767 r_filter->user = filter_value;
769 else if(strcmp(filter_by, "srcip") == 0)
771 r_filter->srcip = filter_value;
773 else if(strcmp(filter_by, "filename") == 0)
775 r_filter->files = filter_value;
779 merror("%s: ERROR: Invalid filter '%s'.", __local_name, filter_by);
785 if(strcmp(filter_by, "group") == 0)
787 r_filter->related_group =
788 _report_filter_value(filter_value, r_filter->related_group);
790 if(r_filter->related_group == -1)
793 else if(strcmp(filter_by, "rule") == 0)
795 r_filter->related_rule =
796 _report_filter_value(filter_value, r_filter->related_rule);
798 if(r_filter->related_rule == -1)
801 else if(strcmp(filter_by, "level") == 0)
803 r_filter->related_level =
804 _report_filter_value(filter_value, r_filter->related_level);
806 if(r_filter->related_level == -1)
809 else if(strcmp(filter_by, "location") == 0)
811 r_filter->related_location =
812 _report_filter_value(filter_value, r_filter->related_location);
814 if(r_filter->related_location == -1)
817 else if(strcmp(filter_by, "srcip") == 0)
819 r_filter->related_srcip =
820 _report_filter_value(filter_value, r_filter->related_srcip);
822 if(r_filter->related_srcip == -1)
825 else if(strcmp(filter_by, "user") == 0)
827 r_filter->related_user =
828 _report_filter_value(filter_value, r_filter->related_user);
830 if(r_filter->related_user == -1)
833 else if(strcmp(filter_by, "filename") == 0)
835 r_filter->related_file =
836 _report_filter_value(filter_value, r_filter->related_file);
838 if(r_filter->related_file == -1)
843 merror("%s: ERROR: Invalid related entry '%s'.", __local_name, filter_by);