/* OS_DBD: Monitor the alerts and insert them into the database. * Only return in case of error. */ void OS_DBD(DBConfig *db_config) { time_t tm; struct tm *p; file_queue *fileq; alert_data *al_data; /* Getting currently time before starting */ tm = time(NULL); p = localtime(&tm); /* Initating file queue - to read the alerts */ os_calloc(1, sizeof(file_queue), fileq); Init_FileQueue(fileq, p, 0); /* Creating location hash */ db_config->location_hash = OSHash_Create(); if(!db_config->location_hash) { ErrorExit(MEM_ERROR, ARGV0); } /* Getting maximum ID */ db_config->alert_id = OS_SelectMaxID(db_config); db_config->alert_id++; /* Infinite loop reading the alerts and inserting them. */ while(1) { tm = time(NULL); p = localtime(&tm); /* Get message if available (timeout of 5 seconds) */ al_data = Read_FileMon(fileq, p, 5); if(!al_data) { continue; } /* Inserting into the db */ OS_Alert_InsertDB(al_data, db_config); /* Clearing the memory */ FreeAlertData(al_data); } }
/* Receive a Message on the Mail queue */ MailMsg *OS_RecvMailQ(file_queue *fileq, struct tm *p, MailConfig *Mail, MailMsg **msg_sms) { int i = 0, sms_set = 0, donotgroup = 0; size_t body_size = OS_MAXSTR - 3, log_size; char logs[OS_MAXSTR + 1]; char extra_data[OS_MAXSTR + 1]; char log_string[OS_MAXSTR / 4 + 1]; char *subject_host; #ifdef LIBGEOIP_ENABLED char geoip_msg_src[OS_SIZE_1024 + 1]; char geoip_msg_dst[OS_SIZE_1024 + 1]; #endif MailMsg *mail; alert_data *al_data; Mail->priority = 0; /* Get message if available */ al_data = Read_FileMon(fileq, p, mail_timeout); if (!al_data) { return (NULL); } /* If e-mail came correctly, generate the e-mail body/subject */ os_calloc(1, sizeof(MailMsg), mail); os_calloc(BODY_SIZE, sizeof(char), mail->body); os_calloc(SUBJECT_SIZE, sizeof(char), mail->subject); /* Generate the logs */ logs[0] = '\0'; extra_data[0] = '\0'; logs[OS_MAXSTR] = '\0'; while (al_data->log[i]) { log_size = strlen(al_data->log[i]) + 4; /* If size left is small than the size of the log, stop it */ if (body_size <= log_size) { break; } strncat(logs, al_data->log[i], body_size); strncat(logs, "\r\n", body_size); body_size -= log_size; i++; } if (al_data->old_md5) { log_size = strlen(al_data->old_md5) + 16 + 4; if (body_size > log_size) { strncat(logs, "Old md5sum was: ", 16); strncat(logs, al_data->old_md5, body_size); strncat(logs, "\r\n", 4); body_size -= log_size; } } if (al_data->new_md5) { log_size = strlen(al_data->new_md5) + 16 + 4; if (body_size > log_size) { strncat(logs, "New md5sum is : ", 16); strncat(logs, al_data->new_md5, body_size); strncat(logs, "\r\n", 4); body_size -= log_size; } } if (al_data->old_sha1) { log_size = strlen(al_data->old_sha1) + 17 + 4; if (body_size > log_size) { strncat(logs, "Old sha1sum was: ", 17); strncat(logs, al_data->old_sha1, body_size); strncat(logs, "\r\n", 4); body_size -= log_size; } } if (al_data->new_sha1) { log_size = strlen(al_data->new_sha1) + 17 + 4; if (body_size > log_size) { strncat(logs, "New sha1sum is : ", 17); strncat(logs, al_data->new_sha1, body_size); strncat(logs, "\r\n", 4); body_size -= log_size; } } /* EXTRA DATA */ if (al_data->srcip) { log_size = snprintf(log_string, sizeof(log_string) - 1, "Src IP: %s\r\n", al_data->srcip ); if (body_size > log_size) { if ( strncat(extra_data, log_string, log_size) != NULL ) { body_size -= log_size; } } } if (al_data->dstip) { log_size = snprintf(log_string, sizeof(log_string) - 1, "Dst IP: %s\r\n", al_data->dstip ); if (body_size > log_size) { if ( strncat(extra_data, log_string, log_size) != NULL ) { body_size -= log_size; } } } if (al_data->user) { log_size = snprintf(log_string, sizeof(log_string) - 1, "User: %s\r\n", al_data->user ); if (body_size > log_size) { if ( strncat(extra_data, log_string, log_size) != NULL ) { body_size -= log_size; } } } /* Subject */ subject_host = strchr(al_data->location, '>'); if (subject_host) { subject_host--; *subject_host = '\0'; } /* We have two subject options - full and normal */ if (Mail->subject_full) { /* Option for a clean full subject (without ossec in the name) */ #ifdef CLEANFULL snprintf(mail->subject, SUBJECT_SIZE - 1, MAIL_SUBJECT_FULL2, al_data->level, al_data->comment, al_data->location); #else snprintf(mail->subject, SUBJECT_SIZE - 1, MAIL_SUBJECT_FULL, al_data->location, al_data->level, al_data->comment); #endif } else { snprintf(mail->subject, SUBJECT_SIZE - 1, MAIL_SUBJECT, al_data->location, al_data->level); } /* Fix subject back */ if (subject_host) { *subject_host = '-'; } #ifdef LIBGEOIP_ENABLED /* Get GeoIP information */ if (Mail->geoip) { if (al_data->srcgeoip) { snprintf(geoip_msg_src, OS_SIZE_1024, "Src Location: %s\r\n", al_data->srcgeoip); } else { geoip_msg_src[0] = '\0'; } if (al_data->dstgeoip) { snprintf(geoip_msg_dst, OS_SIZE_1024, "Dst Location: %s\r\n", al_data->dstgeoip); } else { geoip_msg_dst[0] = '\0'; } } else { geoip_msg_src[0] = '\0'; geoip_msg_dst[0] = '\0'; } #endif /* Body */ #ifdef LIBGEOIP_ENABLED snprintf(mail->body, BODY_SIZE - 1, MAIL_BODY, al_data->date, al_data->location, al_data->rule, al_data->level, al_data->comment, geoip_msg_src, geoip_msg_dst, extra_data, logs); #else snprintf(mail->body, BODY_SIZE - 1, MAIL_BODY, al_data->date, al_data->location, al_data->rule, al_data->level, al_data->comment, extra_data, logs); #endif debug2("OS_RecvMailQ: mail->body[%s]", mail->body); /* Check for granular email configs */ if (Mail->gran_to) { i = 0; while (Mail->gran_to[i] != NULL) { int gr_set = 0; /* Look if location is set */ if (Mail->gran_location[i]) { if (OSMatch_Execute(al_data->location, strlen(al_data->location), Mail->gran_location[i])) { gr_set = 1; } else { i++; continue; } } /* Look for the level */ if (Mail->gran_level[i]) { if (al_data->level >= Mail->gran_level[i]) { gr_set = 1; } else { i++; continue; } } /* Look for rule id */ if (Mail->gran_id[i]) { int id_i = 0; while (Mail->gran_id[i][id_i] != 0) { if (Mail->gran_id[i][id_i] == al_data->rule) { break; } id_i++; } /* If we found, id is going to be a valid rule */ if (Mail->gran_id[i][id_i]) { gr_set = 1; } else { i++; continue; } } /* Look for the group */ if (Mail->gran_group[i]) { if (OSMatch_Execute(al_data->group, strlen(al_data->group), Mail->gran_group[i])) { gr_set = 1; } else { i++; continue; } } /* If we got here, everything matched. Set this e-mail to be used. */ if (gr_set) { if (Mail->gran_format[i] == SMS_FORMAT) { Mail->gran_set[i] = SMS_FORMAT; /* Set the SMS flag */ sms_set = 1; } else { /* Options */ if (Mail->gran_format[i] == FORWARD_NOW) { Mail->priority = 1; Mail->gran_set[i] = FULL_FORMAT; } else if (Mail->gran_format[i] == DONOTGROUP) { Mail->priority = DONOTGROUP; Mail->gran_set[i] = DONOTGROUP; donotgroup = 1; } else { Mail->gran_set[i] = FULL_FORMAT; } } } i++; } } /* If DONOTGROUP is set, we can't assign the new subject */ if (!donotgroup) { /* Get highest level for alert */ if (_g_subject[0] != '\0') { if (_g_subject_level < al_data->level) { strncpy(_g_subject, mail->subject, SUBJECT_SIZE); _g_subject_level = al_data->level; } } else { strncpy(_g_subject, mail->subject, SUBJECT_SIZE); _g_subject_level = al_data->level; } } /* If SMS is set, create the SMS output */ if (sms_set) { MailMsg *msg_sms_tmp; /* Allocate memory for SMS */ os_calloc(1, sizeof(MailMsg), msg_sms_tmp); os_calloc(BODY_SIZE, sizeof(char), msg_sms_tmp->body); os_calloc(SUBJECT_SIZE, sizeof(char), msg_sms_tmp->subject); snprintf(msg_sms_tmp->subject, SUBJECT_SIZE - 1, SMS_SUBJECT, al_data->level, al_data->rule, al_data->comment); strncpy(msg_sms_tmp->body, logs, 128); msg_sms_tmp->body[127] = '\0'; *msg_sms = msg_sms_tmp; } /* Clear the memory */ FreeAlertData(al_data); return (mail); }
void os_ReportdStart(report_filter *r_filter) { int alerts_processed = 0; int alerts_filtered = 0; char *first_alert = NULL; char *last_alert = NULL; void **data_to_clean = NULL; time_t tm; struct tm *p; file_queue *fileq; alert_data *al_data; /* Getting current time before starting */ tm = time(NULL); p = localtime(&tm); /* Initating file queue - to read the alerts */ os_calloc(1, sizeof(file_queue), fileq); if(r_filter->report_type == REPORT_TYPE_DAILY && r_filter->filename) { fileq->fp = fopen(r_filter->filename, "r"); if(!fileq->fp) { merror("%s: ERROR: Unable to open alerts file to generate report.", __local_name); return; } if(r_filter->fp) { __g_rtype = r_filter->fp; } } else { fileq->fp = stdin; } /* Creating top hashes. */ r_filter->top_user = OSStore_Create(); r_filter->top_srcip = OSStore_Create(); r_filter->top_level = OSStore_Create(); r_filter->top_rule = OSStore_Create(); r_filter->top_group = OSStore_Create(); r_filter->top_location = OSStore_Create(); r_filter->top_files = OSStore_Create(); Init_FileQueue(fileq, p, CRALERT_READ_ALL|CRALERT_FP_SET); /* Reading the alerts. */ while(1) { /* Get message if available */ al_data = Read_FileMon(fileq, p, 1); if(!al_data) { break; } alerts_processed++; /* Checking the filters. */ if(!_os_report_check_filters(al_data, r_filter)) { FreeAlertData(al_data); continue; } alerts_filtered++; data_to_clean = os_AddPtArray(al_data, data_to_clean); /* Setting first and last alert for summary. */ if(!first_alert) first_alert = al_data->date; last_alert = al_data->date; /* Adding source ip if it is set properly. */ if(al_data->srcip != NULL && strcmp(al_data->srcip, "(none)") != 0) _os_report_add_tostore(al_data->srcip, r_filter->top_srcip, al_data); /* Adding user if it is set properly. */ if(al_data->user != NULL && strcmp(al_data->user, "(none)") != 0) _os_report_add_tostore(al_data->user, r_filter->top_user, al_data); /* Adding level and severity. */ { char mlevel[16]; char mrule[76 +1]; mrule[76] = '\0'; snprintf(mlevel, 16, "Severity %d" , al_data->level); snprintf(mrule, 76, "%d - %s" , al_data->rule, al_data->comment); _os_report_add_tostore(strdup(mlevel), r_filter->top_level, al_data); _os_report_add_tostore(strdup(mrule), r_filter->top_rule, al_data); } /* Dealing with the group. */ { char *tmp_str; char **mgroup; mgroup = OS_StrBreak(',', al_data->group, 32); if(mgroup) { while(*mgroup) { tmp_str = *mgroup; while(*tmp_str == ' ') tmp_str++; if(*tmp_str == '\0') { mgroup++; continue; } _os_report_add_tostore(tmp_str, r_filter->top_group, al_data); mgroup++; } } else { tmp_str = al_data->group; while(*tmp_str == ' ') tmp_str++; if(*tmp_str != '\0') { _os_report_add_tostore(tmp_str, r_filter->top_group, al_data); } } } /* Adding to the location top filter. */ _os_report_add_tostore(al_data->location, r_filter->top_location, al_data); if(al_data->filename != NULL) { _os_report_add_tostore(al_data->filename, r_filter->top_files, al_data); } } /* No report available */ if(alerts_filtered == 0) { if(!r_filter->report_name) merror("%s: INFO: Report completed and zero alerts post-filter.", __local_name); else merror("%s: INFO: Report '%s' completed and zero alerts post-filter.", __local_name, r_filter->report_name); return; } if(r_filter->report_name) verbose("%s: INFO: Report '%s' completed. Creating output...", __local_name, r_filter->report_name); else verbose("%s: INFO: Report completed. Creating output...", __local_name); l_print_out(" "); if(r_filter->report_name) l_print_out("Report '%s' completed.", r_filter->report_name); else l_print_out("Report completed. =="); l_print_out("------------------------------------------------"); l_print_out("->Processed alerts: %d", alerts_processed); l_print_out("->Post-filtering alerts: %d", alerts_filtered); l_print_out("->First alert: %s", first_alert); l_print_out("->Last alert: %s", last_alert); l_print_out(" "); l_print_out(" "); OSStore_Sort(r_filter->top_srcip, _os_report_sort_compare); OSStore_Sort(r_filter->top_user, _os_report_sort_compare); OSStore_Sort(r_filter->top_level, _os_report_sort_compare); OSStore_Sort(r_filter->top_group, _os_report_sort_compare); OSStore_Sort(r_filter->top_location, _os_report_sort_compare); OSStore_Sort(r_filter->top_rule, _os_report_sort_compare); OSStore_Sort(r_filter->top_files, _os_report_sort_compare); if(r_filter->top_srcip) os_report_printtop(r_filter->top_srcip, "Source ip", 0); if(r_filter->top_user) os_report_printtop(r_filter->top_user, "Username", 0); if(r_filter->top_level) os_report_printtop(r_filter->top_level, "Level", 0); if(r_filter->top_group) os_report_printtop(r_filter->top_group, "Group", 0); if(r_filter->top_location) os_report_printtop(r_filter->top_location, "Location", 0); if(r_filter->top_rule) os_report_printtop(r_filter->top_rule, "Rule", 0); if(r_filter->top_files) os_report_printtop(r_filter->top_files, "Filenames", 0); /* Print related events. */ if(r_filter->related_srcip) os_report_printtop(r_filter->top_srcip, "Source ip", r_filter->related_srcip); if(r_filter->related_user) os_report_printtop(r_filter->top_user, "Username", r_filter->related_user); if(r_filter->related_level) os_report_printtop(r_filter->top_level, "Level", r_filter->related_level); if(r_filter->related_group) os_report_printtop(r_filter->top_group, "Group", r_filter->related_group); if(r_filter->related_location) os_report_printtop(r_filter->top_location, "Location", r_filter->related_location); if(r_filter->related_rule) os_report_printtop(r_filter->top_rule, "Rule", r_filter->related_rule); if(r_filter->related_file) os_report_printtop(r_filter->top_files, "Filename", r_filter->related_file); /* If we have to dump the alerts. */ if(data_to_clean) { int i = 0; if(r_filter->show_alerts) { l_print_out("Log dump:"); l_print_out("------------------------------------------------"); } while(data_to_clean[i]) { alert_data *md = data_to_clean[i]; if(r_filter->show_alerts) 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]); FreeAlertData(md); i++; } free(data_to_clean); data_to_clean = NULL; } }
/* OS_SyslogD: Monitor the alerts and sends them via syslog. * Only return in case of error. */ void OS_CSyslogD(SyslogConfig **syslog_config) { int s = 0; time_t tm; struct tm *p; int tries = 0; file_queue *fileq; alert_data *al_data; /* Getting currently time before starting */ tm = time(NULL); p = localtime(&tm); /* Initating file queue - to read the alerts */ os_calloc(1, sizeof(file_queue), fileq); while( (Init_FileQueue(fileq, p, 0) ) < 0 ) { tries++; if( tries > OS_CSYSLOGD_MAX_TRIES ) { merror("%s: ERROR: Could not open queue after %d tries, exiting!", ARGV0, tries ); exit(1); } sleep(1); } debug1("%s: INFO: File queue connected.", ARGV0 ); /* Connecting to syslog. */ s = 0; while(syslog_config[s]) { syslog_config[s]->socket = OS_ConnectUDP(syslog_config[s]->port, syslog_config[s]->server, 0); if(syslog_config[s]->socket < 0) { merror(CONNS_ERROR, ARGV0, syslog_config[s]->server); } else { merror("%s: INFO: Forwarding alerts via syslog to: '%s:%d'.", ARGV0, syslog_config[s]->server, syslog_config[s]->port); } s++; } /* Infinite loop reading the alerts and inserting them. */ while(1) { tm = time(NULL); p = localtime(&tm); /* Get message if available (timeout of 5 seconds) */ al_data = Read_FileMon(fileq, p, 5); if(!al_data) { continue; } /* Sending via syslog */ s = 0; while(syslog_config[s]) { OS_Alert_SendSyslog(al_data, syslog_config[s]); s++; } /* Clearing the memory */ FreeAlertData(al_data); } }