/* 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); } }
/* OS_Run: Read the queue and send the appropriate alerts. * not supposed to return.. */ static void OS_Run(MailConfig *mail) { MailMsg *msg; MailMsg *s_msg = NULL; MailMsg *msg_sms = NULL; time_t tm; struct tm *p; int i = 0; int mailtosend = 0; int childcount = 0; int thishour = 0; int n_errs = 0; file_queue *fileq; /* Getting currently time before starting */ tm = time(NULL); p = localtime(&tm); thishour = p->tm_hour; /* Init file queue */ i = 0; i |= CRALERT_MAIL_SET; os_calloc(1, sizeof(file_queue), fileq); Init_FileQueue(fileq, p, i); /* Creating the list */ OS_CreateMailList(MAIL_LIST_SIZE); /* Setting default timeout */ mail_timeout = DEFAULT_TIMEOUT; /* Clearing global vars */ _g_subject_level = 0; memset(_g_subject, '\0', SUBJECT_SIZE +2); while(1) { tm = time(NULL); p = localtime(&tm); /* SMS messages are sent without delay */ if(msg_sms) { pid_t pid; pid = fork(); if(pid < 0) { merror("%s: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno)); merror(FORK_ERROR, ARGV0); sleep(30); continue; } else if (pid == 0) { if(OS_Sendsms(mail, p, msg_sms) < 0) merror(SNDMAIL_ERROR, ARGV0, mail->smtpserver); exit(0); } /* Freeing sms structure */ FreeMailMsg(msg_sms); msg_sms = NULL; /* Increasing child count */ childcount++; } /* If mail_timeout == NEXTMAIL_TIMEOUT, we will try to get * more messages, before sending anything */ if((mail_timeout == NEXTMAIL_TIMEOUT) && (p->tm_hour == thishour)) { /* getting more messages */ } /* Hour changed. Send all supressed mails */ else if(((mailtosend < mail->maxperhour) && (mailtosend != 0))|| ((p->tm_hour != thishour) && (childcount < MAXCHILDPROCESS))) { MailNode *mailmsg; pid_t pid; /* Checking if we have anything to sent */ mailmsg = OS_CheckLastMail(); if(mailmsg == NULL) { /* dont fork in here */ goto snd_check_hour; } pid = fork(); if(pid < 0) { merror("%s: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno)); merror(FORK_ERROR, ARGV0); sleep(30); continue; } else if (pid == 0) { if(OS_Sendmail(mail, p) < 0) merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); exit(0); } /* Cleaning the memory */ mailmsg = OS_PopLastMail(); do { FreeMail(mailmsg); mailmsg = OS_PopLastMail(); }while(mailmsg); /* Increasing child count */ childcount++; /* Clearing global vars */ _g_subject[0] = '\0'; _g_subject[SUBJECT_SIZE -1] = '\0'; _g_subject_level = 0; /* Cleaning up set values */ if(mail->gran_to) { i = 0; while(mail->gran_to[i] != NULL) { if(s_msg && mail->gran_set[i] == DONOTGROUP) { mail->gran_set[i] = FULL_FORMAT; } else { mail->gran_set[i] = 0; } i++; } } snd_check_hour: /* If we sent everything */ if(p->tm_hour != thishour) { thishour = p->tm_hour; mailtosend = 0; } } /* Saved message for the do_not_group option. */ if(s_msg) { /* We need to set the remaining do no group to * full format. */ if(mail->gran_to) { i = 0; while(mail->gran_to[i] != NULL) { if(mail->gran_set[i] == DONOTGROUP) { mail->gran_set[i] = FULL_FORMAT; } i++; } } OS_AddMailtoList(s_msg); s_msg = NULL; mailtosend++; continue; } /* Receive message from queue */ if((msg = OS_RecvMailQ(fileq, p, mail, &msg_sms)) != NULL) { /* If the e-mail priority is do_not_group, we first will * flush all previous entries and then send it. * We use s_msg to hold the pointer to the message * while we flush it. */ if(mail->priority == DONOTGROUP) { s_msg = msg; } else { OS_AddMailtoList(msg); } /* Change timeout to see if any new message is coming shortly */ if(mail->groupping) { /* If priority is set, send email now */ if(mail->priority) { mail_timeout = DEFAULT_TIMEOUT; /* If do_not_group is set, we do not increase the * list count in here. */ if(mail->priority != DONOTGROUP) { mailtosend++; } } else { /* 5 seconds only */ mail_timeout = NEXTMAIL_TIMEOUT; } } else { /* Send message by itself */ mailtosend++; } } else { if(mail_timeout == NEXTMAIL_TIMEOUT) { mailtosend++; /* Default timeout */ mail_timeout = DEFAULT_TIMEOUT; } } /* Waiting for the childs .. */ while (childcount) { int wp; int p_status; wp = waitpid((pid_t) -1, &p_status, WNOHANG); if (wp < 0) { merror(WAITPID_ERROR, ARGV0); n_errs++; } /* if = 0, we still need to wait for the child process */ else if (wp == 0) break; else { if(p_status != 0) { merror(CHLDWAIT_ERROR,ARGV0,p_status); merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); n_errs++; } childcount--; } /* Too many errors */ if(n_errs > 6) { merror(TOOMANY_WAIT_ERROR,ARGV0); merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); exit(1); } } } }
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); } }