3 /* Copyright (C) 2009 Trend Micro Inc.
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 2) as published by the FSF - Free Software
16 /** Helper functions. */
17 FILE *__g_rtype = NULL;
18 void l_print_out(const char *msg, ...)
25 (void)vfprintf(__g_rtype, msg, args);
26 (void)fprintf(__g_rtype, "\n");
30 (void)vfprintf(stderr, msg, args);
31 (void)fprintf(stderr, "\n");
37 /* Sort function used by OSStore sort.
40 void *_os_report_sort_compare(void *d1, void *d2)
42 OSList *d1l = (OSList *)d1;
43 OSList *d2l = (OSList *)d2;
45 if(d1l->currently_size > d2l->currently_size)
54 /* Print output header. */
55 void _os_header_print(int t, char *hname)
59 l_print_out("Top entries for '%s':", hname);
60 l_print_out("------------------------------------------------");
64 l_print_out("Related entries for '%s':", hname);
65 l_print_out("------------------------------------------------");
70 /* Compares if the id is present in the string. */
71 int _os_report_str_int_compare(char *str, int id)
77 if((*str == ',')||(*str == ' '))
86 else if(isdigit((int)*str))
101 }while(*str++ != '\0');
108 /* Check if the al_data should be filtered. */
109 int _os_report_check_filters(alert_data *al_data, report_filter *r_filter)
111 /* Checking for the filters. */
114 if(!strstr(al_data->group, r_filter->group))
121 if(_os_report_str_int_compare(r_filter->rule, al_data->rule) != 1)
126 if(r_filter->location)
128 if(!OS_Match(r_filter->location, al_data->location))
135 if(al_data->level < atoi(r_filter->level))
142 if(!strstr(al_data->srcip, r_filter->srcip))
149 if(!strstr(al_data->user, r_filter->user))
159 /* Sets the proper value for the related entries. */
160 int _report_filter_value(char *filter_by, int prev_filter)
162 if(strcmp(filter_by, "group") == 0)
164 if(!(prev_filter & REPORT_REL_GROUP))
166 prev_filter|=REPORT_REL_GROUP;
170 else if(strcmp(filter_by, "rule") == 0)
172 if(!(prev_filter & REPORT_REL_RULE))
174 prev_filter|=REPORT_REL_RULE;
178 else if(strcmp(filter_by, "level") == 0)
180 if(!(prev_filter & REPORT_REL_LEVEL))
182 prev_filter|=REPORT_REL_LEVEL;
186 else if(strcmp(filter_by, "location") == 0)
188 if(!(prev_filter & REPORT_REL_LOCATION))
190 prev_filter|=REPORT_REL_LOCATION;
194 else if(strcmp(filter_by, "srcip") == 0)
196 if(!(prev_filter & REPORT_REL_SRCIP))
198 prev_filter|=REPORT_REL_SRCIP;
202 else if(strcmp(filter_by, "user") == 0)
204 if(!(prev_filter & REPORT_REL_USER))
206 prev_filter|=REPORT_REL_USER;
212 merror("%s: ERROR: Invalid relation '%s'.", __local_name, filter_by);
219 /* Prints related entries. */
220 int _os_report_print_related(int print_related, OSList *st_data)
222 OSListNode *list_entry;
223 alert_data *list_aldata;
224 alert_data *saved_aldata;
227 list_entry = OSList_GetFirstNode(st_data);
230 saved_aldata = (alert_data *)list_entry->data;
232 /* Removing duplicates. */
233 list_entry = list_entry->prev;
236 if(print_related & REPORT_REL_LOCATION)
238 list_aldata = (alert_data *)list_entry->data;
239 if(strcmp(list_aldata->location, saved_aldata->location) == 0)
245 else if(print_related & REPORT_REL_GROUP)
247 list_aldata = (alert_data *)list_entry->data;
248 if(strcmp(list_aldata->group, saved_aldata->group) == 0)
254 else if(print_related & REPORT_REL_RULE)
256 list_aldata = (alert_data *)list_entry->data;
257 if(list_aldata->rule == saved_aldata->rule)
263 else if(print_related & REPORT_REL_USER)
265 list_aldata = (alert_data *)list_entry->data;
266 if(strcmp(list_aldata->user, saved_aldata->user) == 0)
272 else if(print_related & REPORT_REL_SRCIP)
274 list_aldata = (alert_data *)list_entry->data;
275 if(strcmp(list_aldata->srcip, saved_aldata->srcip) == 0)
281 else if(print_related & REPORT_REL_LEVEL)
283 list_aldata = (alert_data *)list_entry->data;
284 if(list_aldata->level == saved_aldata->level)
289 list_entry = list_entry->prev;
294 if(print_related & REPORT_REL_LOCATION)
295 l_print_out(" location: '%s'", saved_aldata->location);
296 else if(print_related & REPORT_REL_GROUP)
297 l_print_out(" group: '%s'", saved_aldata->group);
298 else if(print_related & REPORT_REL_RULE)
299 l_print_out(" rule: '%d'", saved_aldata->rule);
300 else if(print_related & REPORT_REL_SRCIP)
301 l_print_out(" srcip: '%s'", saved_aldata->srcip);
302 else if(print_related & REPORT_REL_USER)
303 l_print_out(" user: '%s'", saved_aldata->user);
304 else if(print_related & REPORT_REL_LEVEL)
305 l_print_out(" level: '%d'", saved_aldata->level);
308 list_entry = OSList_GetNextNode(st_data);
316 /* Add the entry to the hash. */
317 int _os_report_add_tostore(char *key, OSStore *top, void *data)
321 /* Adding data to the hash. */
322 top_list = OSStore_Get(top, key);
325 OSList_AddData(top_list, data);
329 top_list = OSList_Create();
332 merror(MEM_ERROR, __local_name);
335 OSList_AddData(top_list, data);
337 OSStore_Put(top, key, top_list);
345 void os_report_printtop(void *topstore_pt, char *hname, int print_related)
348 OSStore *topstore = (OSStore *)topstore_pt;
349 OSStoreNode *next_node;
351 next_node = OSStore_GetFirstNode(topstore);
354 OSList *st_data = (OSList *)next_node->data;
355 char *lkey = (char *)next_node->key;
358 /* With location we leave more space to be clearer. */
361 if(strlen(lkey) > 46)
370 _os_header_print(print_related, hname);
373 l_print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size);
377 /* Print each destination. */
382 _os_header_print(print_related, hname);
385 l_print_out("%-48s|%-8d|", (char *)next_node->key, st_data->currently_size);
387 if(print_related & REPORT_REL_LOCATION)
388 _os_report_print_related(REPORT_REL_LOCATION, st_data);
389 if(print_related & REPORT_REL_SRCIP)
390 _os_report_print_related(REPORT_REL_SRCIP, st_data);
391 if(print_related & REPORT_REL_USER)
392 _os_report_print_related(REPORT_REL_USER, st_data);
393 if(print_related & REPORT_REL_RULE)
394 _os_report_print_related(REPORT_REL_RULE, st_data);
395 if(print_related & REPORT_REL_GROUP)
396 _os_report_print_related(REPORT_REL_GROUP, st_data);
397 if(print_related & REPORT_REL_LEVEL)
398 _os_report_print_related(REPORT_REL_LEVEL, st_data);
402 next_node = next_node->next;
416 void os_ReportdStart(report_filter *r_filter)
418 int alerts_processed = 0;
419 int alerts_filtered = 0;
420 char *first_alert = NULL;
421 char *last_alert = NULL;
422 void **data_to_clean = NULL;
433 /* Getting current time before starting */
440 /* Initating file queue - to read the alerts */
441 os_calloc(1, sizeof(file_queue), fileq);
443 if(r_filter->report_type == REPORT_TYPE_DAILY && r_filter->filename)
445 fileq->fp = fopen(r_filter->filename, "r");
448 merror("%s: ERROR: Unable to open alerts file to generate report.", __local_name);
453 __g_rtype = r_filter->fp;
462 /* Creating top hashes. */
463 r_filter->top_user = OSStore_Create();
464 r_filter->top_srcip = OSStore_Create();
465 r_filter->top_level = OSStore_Create();
466 r_filter->top_rule = OSStore_Create();
467 r_filter->top_group = OSStore_Create();
468 r_filter->top_location = OSStore_Create();
470 Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET);
473 /* Reading the alerts. */
476 /* Get message if available */
477 al_data = Read_FileMon(fileq, p, 1);
486 /* Checking the filters. */
487 if(!_os_report_check_filters(al_data, r_filter))
489 FreeAlertData(al_data);
495 data_to_clean = os_AddPtArray(al_data, data_to_clean);
498 /* Setting first and last alert for summary. */
500 first_alert = al_data->date;
501 last_alert = al_data->date;
504 /* Adding source ip if it is set properly. */
505 if(strcmp(al_data->srcip, "(none)") != 0)
506 _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data);
509 /* Adding user if it is set properly. */
510 if(strcmp(al_data->user, "(none)") != 0)
511 _os_report_add_tostore(al_data->user, r_filter->top_user, al_data);
514 /* Adding level and severity. */
519 snprintf(mlevel, 16, "Severity %d" , al_data->level);
520 snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment);
522 _os_report_add_tostore(strdup(mlevel), r_filter->top_level,
524 _os_report_add_tostore(strdup(mrule), r_filter->top_rule,
528 /* Dealing with the group. */
533 mgroup = OS_StrBreak(',', al_data->group, 32);
539 while(*tmp_str == ' ')
547 _os_report_add_tostore(tmp_str, r_filter->top_group,
554 tmp_str = al_data->group;
555 while(*tmp_str == ' ')
559 _os_report_add_tostore(tmp_str, r_filter->top_group,
566 /* Adding to the location top filter. */
567 _os_report_add_tostore(al_data->location, r_filter->top_location,
571 /* No report available */
572 if(alerts_filtered == 0)
574 if(!r_filter->report_name)
575 merror("%s: INFO: Report completed and zero alerts post-filter.", __local_name);
577 merror("%s: INFO: Report '%s' completed and zero alerts post-filter.", __local_name, r_filter->report_name);
582 if(r_filter->report_name)
583 verbose("%s: INFO: Report '%s' completed. Creating output...", __local_name, r_filter->report_name);
585 verbose("%s: INFO: Report completed. Creating output...", __local_name);
589 if(r_filter->report_name)
590 l_print_out("Report '%s' completed.", r_filter->report_name);
592 l_print_out("Report completed. ==");
593 l_print_out("------------------------------------------------");
595 l_print_out("->Processed alerts: %d", alerts_processed);
596 l_print_out("->Post-filtering alerts: %d", alerts_filtered);
597 l_print_out("->First alert: %s", first_alert);
598 l_print_out("->Last alert: %s", last_alert);
602 OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare);
603 OSStore_Sort(r_filter->top_user, _os_report_sort_compare);
604 OSStore_Sort(r_filter->top_level, _os_report_sort_compare);
605 OSStore_Sort(r_filter->top_group, _os_report_sort_compare);
606 OSStore_Sort(r_filter->top_location, _os_report_sort_compare);
607 OSStore_Sort(r_filter->top_rule, _os_report_sort_compare);
609 if(r_filter->top_srcip)
610 os_report_printtop(r_filter->top_srcip, "Source ip", 0);
612 if(r_filter->top_user)
613 os_report_printtop(r_filter->top_user, "Username", 0);
615 if(r_filter->top_level)
616 os_report_printtop(r_filter->top_level, "Level", 0);
618 if(r_filter->top_group)
619 os_report_printtop(r_filter->top_group, "Group", 0);
621 if(r_filter->top_location)
622 os_report_printtop(r_filter->top_location, "Location", 0);
624 if(r_filter->top_rule)
625 os_report_printtop(r_filter->top_rule, "Rule", 0);
628 /* Print related events. */
629 if(r_filter->related_srcip)
630 os_report_printtop(r_filter->top_srcip, "Source ip",
631 r_filter->related_srcip);
633 if(r_filter->related_user)
634 os_report_printtop(r_filter->top_user, "Username",
635 r_filter->related_user);
637 if(r_filter->related_level)
638 os_report_printtop(r_filter->top_level, "Level",
639 r_filter->related_level);
641 if(r_filter->related_group)
642 os_report_printtop(r_filter->top_group, "Group",
643 r_filter->related_group);
645 if(r_filter->related_location)
646 os_report_printtop(r_filter->top_location, "Location",
647 r_filter->related_location);
649 if(r_filter->related_rule)
650 os_report_printtop(r_filter->top_rule, "Rule",
651 r_filter->related_rule);
654 /* If we have to dump the alerts. */
659 if(r_filter->show_alerts)
661 l_print_out("Log dump:");
662 l_print_out("------------------------------------------------");
664 while(data_to_clean[i])
666 alert_data *md = data_to_clean[i];
667 if(r_filter->show_alerts)
668 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]);
673 data_to_clean = NULL;
681 /** int os_report_check_filters(char *filter_by, char *filter_value,
682 * report_filter *r_filter)
683 * Checks the configuration filters.
685 int os_report_configfilter(char *filter_by, char *filter_value,
686 report_filter *r_filter, int arg_type)
688 if(!filter_by || !filter_value)
693 if(arg_type == REPORT_FILTER)
695 if(strcmp(filter_by, "group") == 0)
697 r_filter->group = filter_value;
699 else if(strcmp(filter_by, "rule") == 0)
701 r_filter->rule = filter_value;
703 else if(strcmp(filter_by, "level") == 0)
705 r_filter->level = filter_value;
707 else if(strcmp(filter_by, "location") == 0)
709 r_filter->location = filter_value;
711 else if(strcmp(filter_by, "user") == 0)
713 r_filter->user = filter_value;
715 else if(strcmp(filter_by, "srcip") == 0)
717 r_filter->srcip = filter_value;
721 merror("%s: ERROR: Invalid filter '%s'.", __local_name, filter_by);
727 if(strcmp(filter_by, "group") == 0)
729 r_filter->related_group =
730 _report_filter_value(filter_value, r_filter->related_group);
732 if(r_filter->related_group == -1)
735 else if(strcmp(filter_by, "rule") == 0)
737 r_filter->related_rule =
738 _report_filter_value(filter_value, r_filter->related_rule);
740 if(r_filter->related_rule == -1)
743 else if(strcmp(filter_by, "level") == 0)
745 r_filter->related_level =
746 _report_filter_value(filter_value, r_filter->related_level);
748 if(r_filter->related_level == -1)
751 else if(strcmp(filter_by, "location") == 0)
753 r_filter->related_location =
754 _report_filter_value(filter_value, r_filter->related_location);
756 if(r_filter->related_location == -1)
759 else if(strcmp(filter_by, "srcip") == 0)
761 r_filter->related_srcip =
762 _report_filter_value(filter_value, r_filter->related_srcip);
764 if(r_filter->related_srcip == -1)
767 else if(strcmp(filter_by, "user") == 0)
769 r_filter->related_user =
770 _report_filter_value(filter_value, r_filter->related_user);
772 if(r_filter->related_user == -1)
777 merror("%s: ERROR: Invalid related entry '%s'.", __local_name, filter_by);