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(al_data->group) /* Probably unnecessary, all (?) alerts should have groups) */
117 if(!strstr(al_data->group, r_filter->group))
125 if(_os_report_str_int_compare(r_filter->rule, al_data->rule) != 1)
130 if(r_filter->location)
132 if(!OS_Match(r_filter->location, al_data->location))
139 if(al_data->level < atoi(r_filter->level))
149 if(!strstr(al_data->srcip, r_filter->srcip))
159 if(!strstr(al_data->user, r_filter->user))
167 if(al_data->filename)
169 if(!strstr(al_data->filename, r_filter->files))
180 /* Sets the proper value for the related entries. */
181 int _report_filter_value(char *filter_by, int prev_filter)
183 if(strcmp(filter_by, "group") == 0)
185 if(!(prev_filter & REPORT_REL_GROUP))
187 prev_filter|=REPORT_REL_GROUP;
191 else if(strcmp(filter_by, "rule") == 0)
193 if(!(prev_filter & REPORT_REL_RULE))
195 prev_filter|=REPORT_REL_RULE;
199 else if(strcmp(filter_by, "level") == 0)
201 if(!(prev_filter & REPORT_REL_LEVEL))
203 prev_filter|=REPORT_REL_LEVEL;
207 else if(strcmp(filter_by, "location") == 0)
209 if(!(prev_filter & REPORT_REL_LOCATION))
211 prev_filter|=REPORT_REL_LOCATION;
215 else if(strcmp(filter_by, "srcip") == 0)
217 if(!(prev_filter & REPORT_REL_SRCIP))
219 prev_filter|=REPORT_REL_SRCIP;
223 else if(strcmp(filter_by, "user") == 0)
225 if(!(prev_filter & REPORT_REL_USER))
227 prev_filter|=REPORT_REL_USER;
231 else if(strcmp(filter_by, "filename") == 0)
233 if(!(prev_filter & REPORT_REL_FILE))
235 prev_filter|=REPORT_REL_FILE;
241 merror("%s: ERROR: Invalid relation '%s'.", __local_name, filter_by);
248 /* Prints related entries. */
249 int _os_report_print_related(int print_related, OSList *st_data)
251 OSListNode *list_entry;
252 alert_data *list_aldata;
253 alert_data *saved_aldata;
256 list_entry = OSList_GetFirstNode(st_data);
259 saved_aldata = (alert_data *)list_entry->data;
261 /* Removing duplicates. */
262 list_entry = list_entry->prev;
265 if(print_related & REPORT_REL_LOCATION)
267 list_aldata = (alert_data *)list_entry->data;
268 if(strcmp(list_aldata->location, saved_aldata->location) == 0)
274 else if(print_related & REPORT_REL_GROUP)
276 list_aldata = (alert_data *)list_entry->data;
277 if(strcmp(list_aldata->group, saved_aldata->group) == 0)
283 else if(print_related & REPORT_REL_RULE)
285 list_aldata = (alert_data *)list_entry->data;
286 if(list_aldata->rule == saved_aldata->rule)
292 else if(print_related & REPORT_REL_USER)
294 list_aldata = (alert_data *)list_entry->data;
295 if(list_aldata->user == NULL || saved_aldata->user == NULL)
298 else if(strcmp(list_aldata->user, saved_aldata->user) == 0)
304 else if(print_related & REPORT_REL_SRCIP)
306 list_aldata = (alert_data *)list_entry->data;
307 if(list_aldata->srcip == NULL || saved_aldata->srcip == NULL)
310 else if(strcmp(list_aldata->srcip, saved_aldata->srcip) == 0)
316 else if(print_related & REPORT_REL_LEVEL)
318 list_aldata = (alert_data *)list_entry->data;
319 if(list_aldata->level == saved_aldata->level)
324 else if(print_related & REPORT_REL_FILE)
326 list_aldata = (alert_data *)list_entry->data;
327 if(list_aldata->filename == NULL || saved_aldata->filename == NULL)
330 else if(strcmp(list_aldata->filename, saved_aldata->filename) == 0)
335 list_entry = list_entry->prev;
340 if(print_related & REPORT_REL_LOCATION)
341 l_print_out(" location: '%s'", saved_aldata->location);
342 else if(print_related & REPORT_REL_GROUP)
343 l_print_out(" group: '%s'", saved_aldata->group);
344 else if(print_related & REPORT_REL_RULE)
345 l_print_out(" rule: '%d'", saved_aldata->rule);
346 else if((print_related & REPORT_REL_SRCIP) && saved_aldata->srcip)
347 l_print_out(" srcip: '%s'", saved_aldata->srcip);
348 else if((print_related & REPORT_REL_USER) && saved_aldata->user)
349 l_print_out(" user: '%s'", saved_aldata->user);
350 else if(print_related & REPORT_REL_LEVEL)
351 l_print_out(" level: '%d'", saved_aldata->level);
352 else if((print_related & REPORT_REL_FILE) && saved_aldata->filename)
353 l_print_out(" filename: '%s'", saved_aldata->filename);
356 list_entry = OSList_GetNextNode(st_data);
364 /* Add the entry to the hash. */
365 int _os_report_add_tostore(char *key, OSStore *top, void *data)
369 /* Adding data to the hash. */
370 top_list = OSStore_Get(top, key);
373 OSList_AddData(top_list, data);
377 top_list = OSList_Create();
380 merror(MEM_ERROR, __local_name);
383 OSList_AddData(top_list, data);
385 OSStore_Put(top, key, top_list);
393 void os_report_printtop(void *topstore_pt, char *hname, int print_related)
396 OSStore *topstore = (OSStore *)topstore_pt;
397 OSStoreNode *next_node;
399 next_node = OSStore_GetFirstNode(topstore);
402 OSList *st_data = (OSList *)next_node->data;
403 char *lkey = (char *)next_node->key;
406 /* With location we leave more space to be clearer. */
409 if(strlen(lkey) > 76)
418 _os_header_print(print_related, hname);
421 l_print_out("%-78s|%-8d|", (char *)next_node->key, st_data->currently_size);
425 /* Print each destination. */
430 _os_header_print(print_related, hname);
433 l_print_out("%-78s|%-8d|", (char *)next_node->key, st_data->currently_size);
435 if(print_related & REPORT_REL_LOCATION)
436 _os_report_print_related(REPORT_REL_LOCATION, st_data);
437 if(print_related & REPORT_REL_SRCIP)
438 _os_report_print_related(REPORT_REL_SRCIP, st_data);
439 if(print_related & REPORT_REL_USER)
440 _os_report_print_related(REPORT_REL_USER, st_data);
441 if(print_related & REPORT_REL_RULE)
442 _os_report_print_related(REPORT_REL_RULE, st_data);
443 if(print_related & REPORT_REL_GROUP)
444 _os_report_print_related(REPORT_REL_GROUP, st_data);
445 if(print_related & REPORT_REL_LEVEL)
446 _os_report_print_related(REPORT_REL_LEVEL, st_data);
447 if(print_related & REPORT_REL_FILE)
448 _os_report_print_related(REPORT_REL_FILE, st_data);
452 next_node = next_node->next;
466 void os_ReportdStart(report_filter *r_filter)
468 int alerts_processed = 0;
469 int alerts_filtered = 0;
470 char *first_alert = NULL;
471 char *last_alert = NULL;
472 void **data_to_clean = NULL;
483 /* Getting current time before starting */
490 /* Initating file queue - to read the alerts */
491 os_calloc(1, sizeof(file_queue), fileq);
493 if(r_filter->report_type == REPORT_TYPE_DAILY && r_filter->filename)
495 fileq->fp = fopen(r_filter->filename, "r");
498 merror("%s: ERROR: Unable to open alerts file to generate report.", __local_name);
503 __g_rtype = r_filter->fp;
512 /* Creating top hashes. */
513 r_filter->top_user = OSStore_Create();
514 r_filter->top_srcip = OSStore_Create();
515 r_filter->top_level = OSStore_Create();
516 r_filter->top_rule = OSStore_Create();
517 r_filter->top_group = OSStore_Create();
518 r_filter->top_location = OSStore_Create();
519 r_filter->top_files = OSStore_Create();
521 Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET);
525 /* Reading the alerts. */
528 /* Get message if available */
529 al_data = Read_FileMon(fileq, p, 1);
538 /* Checking the filters. */
539 if(!_os_report_check_filters(al_data, r_filter))
541 FreeAlertData(al_data);
547 data_to_clean = os_AddPtArray(al_data, data_to_clean);
550 /* Setting first and last alert for summary. */
552 first_alert = al_data->date;
553 last_alert = al_data->date;
556 /* Adding source ip if it is set properly. */
557 if(al_data->srcip != NULL && strcmp(al_data->srcip, "(none)") != 0)
558 _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data);
561 /* Adding user if it is set properly. */
562 if(al_data->user != NULL && strcmp(al_data->user, "(none)") != 0)
563 _os_report_add_tostore(al_data->user, r_filter->top_user, al_data);
566 /* Adding level and severity. */
571 snprintf(mlevel, 16, "Severity %d" , al_data->level);
572 snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment);
574 _os_report_add_tostore(strdup(mlevel), r_filter->top_level,
576 _os_report_add_tostore(strdup(mrule), r_filter->top_rule,
580 /* Dealing with the group. */
585 mgroup = OS_StrBreak(',', al_data->group, 32);
591 while(*tmp_str == ' ')
599 _os_report_add_tostore(tmp_str, r_filter->top_group,
606 tmp_str = al_data->group;
607 while(*tmp_str == ' ')
611 _os_report_add_tostore(tmp_str, r_filter->top_group,
618 /* Adding to the location top filter. */
619 _os_report_add_tostore(al_data->location, r_filter->top_location,
623 if(al_data->filename != NULL)
625 _os_report_add_tostore(al_data->filename, r_filter->top_files,
630 /* No report available */
631 if(alerts_filtered == 0)
633 if(!r_filter->report_name)
634 merror("%s: INFO: Report completed and zero alerts post-filter.", __local_name);
636 merror("%s: INFO: Report '%s' completed and zero alerts post-filter.", __local_name, r_filter->report_name);
641 if(r_filter->report_name)
642 verbose("%s: INFO: Report '%s' completed. Creating output...", __local_name, r_filter->report_name);
644 verbose("%s: INFO: Report completed. Creating output...", __local_name);
648 if(r_filter->report_name)
649 l_print_out("Report '%s' completed.", r_filter->report_name);
651 l_print_out("Report completed. ==");
652 l_print_out("------------------------------------------------");
654 l_print_out("->Processed alerts: %d", alerts_processed);
655 l_print_out("->Post-filtering alerts: %d", alerts_filtered);
656 l_print_out("->First alert: %s", first_alert);
657 l_print_out("->Last alert: %s", last_alert);
661 OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare);
662 OSStore_Sort(r_filter->top_user, _os_report_sort_compare);
663 OSStore_Sort(r_filter->top_level, _os_report_sort_compare);
664 OSStore_Sort(r_filter->top_group, _os_report_sort_compare);
665 OSStore_Sort(r_filter->top_location, _os_report_sort_compare);
666 OSStore_Sort(r_filter->top_rule, _os_report_sort_compare);
667 OSStore_Sort(r_filter->top_files, _os_report_sort_compare);
669 if(r_filter->top_srcip)
670 os_report_printtop(r_filter->top_srcip, "Source ip", 0);
672 if(r_filter->top_user)
673 os_report_printtop(r_filter->top_user, "Username", 0);
675 if(r_filter->top_level)
676 os_report_printtop(r_filter->top_level, "Level", 0);
678 if(r_filter->top_group)
679 os_report_printtop(r_filter->top_group, "Group", 0);
681 if(r_filter->top_location)
682 os_report_printtop(r_filter->top_location, "Location", 0);
684 if(r_filter->top_rule)
685 os_report_printtop(r_filter->top_rule, "Rule", 0);
687 if(r_filter->top_files)
688 os_report_printtop(r_filter->top_files, "Filenames", 0);
691 /* Print related events. */
692 if(r_filter->related_srcip)
693 os_report_printtop(r_filter->top_srcip, "Source ip",
694 r_filter->related_srcip);
696 if(r_filter->related_user)
697 os_report_printtop(r_filter->top_user, "Username",
698 r_filter->related_user);
700 if(r_filter->related_level)
701 os_report_printtop(r_filter->top_level, "Level",
702 r_filter->related_level);
704 if(r_filter->related_group)
705 os_report_printtop(r_filter->top_group, "Group",
706 r_filter->related_group);
708 if(r_filter->related_location)
709 os_report_printtop(r_filter->top_location, "Location",
710 r_filter->related_location);
712 if(r_filter->related_rule)
713 os_report_printtop(r_filter->top_rule, "Rule",
714 r_filter->related_rule);
716 if(r_filter->related_file)
717 os_report_printtop(r_filter->top_files, "Filename",
718 r_filter->related_file);
721 /* If we have to dump the alerts. */
726 if(r_filter->show_alerts)
728 l_print_out("Log dump:");
729 l_print_out("------------------------------------------------");
731 while(data_to_clean[i])
733 alert_data *md = data_to_clean[i];
734 if(r_filter->show_alerts)
735 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]);
740 data_to_clean = NULL;
748 /** int os_report_check_filters(char *filter_by, char *filter_value,
749 * report_filter *r_filter)
750 * Checks the configuration filters.
752 int os_report_configfilter(char *filter_by, char *filter_value,
753 report_filter *r_filter, int arg_type)
755 if(!filter_by || !filter_value)
760 if(arg_type == REPORT_FILTER)
762 if(strcmp(filter_by, "group") == 0)
764 r_filter->group = filter_value;
766 else if(strcmp(filter_by, "rule") == 0)
768 r_filter->rule = filter_value;
770 else if(strcmp(filter_by, "level") == 0)
772 r_filter->level = filter_value;
774 else if(strcmp(filter_by, "location") == 0)
776 r_filter->location = filter_value;
778 else if(strcmp(filter_by, "user") == 0)
780 r_filter->user = filter_value;
782 else if(strcmp(filter_by, "srcip") == 0)
784 r_filter->srcip = filter_value;
786 else if(strcmp(filter_by, "filename") == 0)
788 r_filter->files = filter_value;
792 merror("%s: ERROR: Invalid filter '%s'.", __local_name, filter_by);
798 if(strcmp(filter_by, "group") == 0)
800 r_filter->related_group =
801 _report_filter_value(filter_value, r_filter->related_group);
803 if(r_filter->related_group == -1)
806 else if(strcmp(filter_by, "rule") == 0)
808 r_filter->related_rule =
809 _report_filter_value(filter_value, r_filter->related_rule);
811 if(r_filter->related_rule == -1)
814 else if(strcmp(filter_by, "level") == 0)
816 r_filter->related_level =
817 _report_filter_value(filter_value, r_filter->related_level);
819 if(r_filter->related_level == -1)
822 else if(strcmp(filter_by, "location") == 0)
824 r_filter->related_location =
825 _report_filter_value(filter_value, r_filter->related_location);
827 if(r_filter->related_location == -1)
830 else if(strcmp(filter_by, "srcip") == 0)
832 r_filter->related_srcip =
833 _report_filter_value(filter_value, r_filter->related_srcip);
835 if(r_filter->related_srcip == -1)
838 else if(strcmp(filter_by, "user") == 0)
840 r_filter->related_user =
841 _report_filter_value(filter_value, r_filter->related_user);
843 if(r_filter->related_user == -1)
846 else if(strcmp(filter_by, "filename") == 0)
848 r_filter->related_file =
849 _report_filter_value(filter_value, r_filter->related_file);
851 if(r_filter->related_file == -1)
856 merror("%s: ERROR: Invalid related entry '%s'.", __local_name, filter_by);