/* Handle syslog TCP connections */ void HandleSyslogTCP() { int client_socket = 0; int st_errors = 0; int childcount = 0; char srcip[IPSIZE + 1]; /* Initialize some variables */ memset(srcip, '\0', IPSIZE + 1); /* Connecting to the message queue * Exit if it fails. */ if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } while (1) { /* Wait for the children */ while (childcount) { int wp; wp = waitpid((pid_t) - 1, NULL, WNOHANG); if (wp < 0) { merror(WAITPID_ERROR, ARGV0, errno, strerror(errno)); } /* if = 0, we still need to wait for the child process */ else if (wp == 0) { break; } else { childcount--; } } /* Accept new connections */ client_socket = OS_AcceptTCP(logr.sock, srcip, IPSIZE); if (client_socket < 0) { st_errors++; } /* Check if IP is allowed here */ if (OS_IPNotAllowed(srcip)) { merror(DENYIP_WARN, ARGV0, srcip); close(client_socket); } /* Fork to deal with new client */ if (fork() == 0) { HandleClient(client_socket, srcip); exit(0); } else { childcount++; /* Close client socket, since the child is handling it */ close(client_socket); continue; } } }
/* Send a message related to rootcheck change/addition */ int send_rootcheck_msg(const char *msg) { if (SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } /* Try to send it again */ SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ); } return (0); }
/* Send pgsql message and check the return code. */ void __send_pgsql_msg(int pos, int drop_it, char *buffer) { debug2("%s: DEBUG: Reading PostgreSQL message: '%s'", ARGV0, buffer); if(drop_it == 0) { if(SendMSG(logr_queue, buffer, logff[pos].file, POSTGRESQL_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } }
/* Send syscheck message. * Send a message related to syscheck change/addition. */ int send_syscheck_msg(char *msg) { if(SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } /* If we reach here, we can try to send it again */ SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ); } return(0); }
/* notify_rk * Report a problem. */ int notify_rk(int rk_type, const char *msg) { /* Non-queue notification */ if(rootcheck.notify != QUEUE) { if(rk_type == ALERT_OK) printf("[OK]: %s\n", msg); else if(rk_type == ALERT_SYSTEM_ERR) printf("[ERR]: %s\n", msg); else if(rk_type == ALERT_POLICY_VIOLATION) printf("[INFO]: %s\n", msg); else { printf("[FAILED]: %s\n", msg); } printf("\n"); return(0); } /* No need to alert on that to the server */ if(rk_type <= ALERT_SYSTEM_ERR) return(0); #ifdef OSSECHIDS if(SendMSG(rootcheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((rootcheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } if(SendMSG(rootcheck.queue,msg,ROOTCHECK,ROOTCHECK_MQ) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } #endif return(0); }
int main(int argc, char **argv) { int c,r; int test_config = 0,run_foreground = 0; char *cfg = DEFAULTCPATH; /* Zeroing the structure */ syscheck.workdir = NULL; /* Setting the name */ OS_SetName(ARGV0); while((c = getopt(argc, argv, "VtdhfD:c:")) != -1) { switch(c) { case 'V': print_version(); break; case 'h': help(ARGV0); break; case 'd': nowDebug(); break; case 'f': run_foreground = 1; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); syscheck.workdir = optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; default: help(ARGV0); break; } } /* Checking if the configuration is present */ if(File_DateofChange(cfg) < 0) ErrorExit(NO_CONFIG, ARGV0, cfg); /* Read syscheck config */ if((r = Read_Syscheck_Config(cfg)) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, cfg); } else if((r == 1) || (syscheck.disabled == 1)) { if(!syscheck.dir) { if(!test_config) merror(SK_NO_DIR, ARGV0); dump_syscheck_entry(&syscheck, "", 0, 0, NULL); } else if(!syscheck.dir[0]) { if(!test_config) merror(SK_NO_DIR, ARGV0); } syscheck.dir[0] = NULL; if(!test_config) { merror("%s: WARN: Syscheck disabled.", ARGV0); } } /* Reading internal options */ read_internal(); /* Rootcheck config */ if(rootcheck_init(test_config) == 0) { syscheck.rootcheck = 1; } else { syscheck.rootcheck = 0; merror("%s: WARN: Rootcheck module disabled.", ARGV0); } /* Exit if testing config */ if(test_config) exit(0); /* Setting default values */ if(syscheck.workdir == NULL) syscheck.workdir = DEFAULTDIR; if(!run_foreground) { nowDaemon(); goDaemon(); } /* Initial time to settle */ sleep(syscheck.tsleep + 2); /* Connect to the queue */ if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno)); sleep(5); if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { /* more 10 seconds of wait.. */ merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno)); sleep(10); if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) ErrorExit(QUEUE_FATAL,ARGV0,DEFAULTQPATH); } } /* Start the signal handling */ StartSIG(ARGV0); /* Creating pid */ if(CreatePID(ARGV0, getpid()) < 0) merror(PID_ERROR,ARGV0); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); if(syscheck.rootcheck) { verbose(STARTUP_MSG, "ossec-rootcheck", (int)getpid()); } /* Printing directories to be monitored. */ r = 0; while(syscheck.dir[r] != NULL) { verbose("%s: INFO: Monitoring directory: '%s'.", ARGV0, syscheck.dir[r]); r++; } /* Checking directories set for real time. */ r = 0; while(syscheck.dir[r] != NULL) { if(syscheck.opts[r] & CHECK_REALTIME) { #ifdef USEINOTIFY verbose("%s: INFO: Directory set for real time monitoring: " "'%s'.", ARGV0, syscheck.dir[r]); #elif WIN32 verbose("%s: INFO: Directory set for real time monitoring: " "'%s'.", ARGV0, syscheck.dir[r]); #else verbose("%s: WARN: Ignoring flag for real time monitoring on " "directory: '%s'.", ARGV0, syscheck.dir[r]); #endif } r++; } /* Some sync time */ sleep(syscheck.tsleep + 10); /* Start the daemon */ start_daemon(); return(0); }
/* Syscheck unix main */ int main(int argc, char **argv) { int c, r; int debug_level = 0; int test_config = 0, run_foreground = 0; const char *cfg = DEFAULTCPATH; /* Set the name */ OS_SetName(ARGV0); while ((c = getopt(argc, argv, "Vtdhfc:")) != -1) { switch (c) { case 'V': print_version(); break; case 'h': help_syscheckd(); break; case 'd': nowDebug(); debug_level ++; break; case 'f': run_foreground = 1; break; case 'c': if (!optarg) { ErrorExit("%s: -c needs an argument", ARGV0); } cfg = optarg; break; case 't': test_config = 1; break; default: help_syscheckd(); break; } } /* Read internal options */ read_internal(debug_level); debug1(STARTED_MSG, ARGV0); /* Check if the configuration is present */ if (File_DateofChange(cfg) < 0) { ErrorExit(NO_CONFIG, ARGV0, cfg); } /* Read syscheck config */ if ((r = Read_Syscheck_Config(cfg)) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, cfg); } else if ((r == 1) || (syscheck.disabled == 1)) { if (!syscheck.dir) { if (!test_config) { merror(SK_NO_DIR, ARGV0); } dump_syscheck_entry(&syscheck, "", 0, 0, NULL); } else if (!syscheck.dir[0]) { if (!test_config) { merror(SK_NO_DIR, ARGV0); } } syscheck.dir[0] = NULL; if (!test_config) { merror("%s: WARN: Syscheck disabled.", ARGV0); } } /* Rootcheck config */ if (rootcheck_init(test_config) == 0) { syscheck.rootcheck = 1; } else { syscheck.rootcheck = 0; merror("%s: WARN: Rootcheck module disabled.", ARGV0); } /* Exit if testing config */ if (test_config) { exit(0); } /* Setup libmagic */ #ifdef USE_MAGIC init_magic(&magic_cookie); #endif if (!run_foreground) { nowDaemon(); goDaemon(); } /* Initial time to settle */ sleep(syscheck.tsleep + 2); /* Connect to the queue */ if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno)); sleep(5); if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { /* more 10 seconds of wait */ merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno)); sleep(10); if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } /* Start signal handling */ StartSIG(ARGV0); /* Create pid */ if (CreatePID(ARGV0, getpid()) < 0) { ErrorExit(PID_ERROR, ARGV0); } /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); if (syscheck.rootcheck) { verbose(STARTUP_MSG, "ossec-rootcheck", (int)getpid()); } /* Print directories to be monitored */ r = 0; while (syscheck.dir[r] != NULL) { char optstr[ 100 ]; verbose("%s: INFO: Monitoring directory: '%s', with options %s.", ARGV0, syscheck.dir[r], syscheck_opts2str(optstr, sizeof( optstr ), syscheck.opts[r])); r++; } /* Print ignores. */ if(syscheck.ignore) for (r = 0; syscheck.ignore[r] != NULL; r++) verbose("%s: INFO: ignoring: '%s'", ARGV0, syscheck.ignore[r]); /* Print files with no diff. */ if (syscheck.nodiff){ r = 0; while (syscheck.nodiff[r] != NULL) { verbose("%s: INFO: No diff for file: '%s'", ARGV0, syscheck.nodiff[r]); r++; } } /* Check directories set for real time */ r = 0; while (syscheck.dir[r] != NULL) { if (syscheck.opts[r] & CHECK_REALTIME) { #ifdef INOTIFY_ENABLED verbose("%s: INFO: Directory set for real time monitoring: " "'%s'.", ARGV0, syscheck.dir[r]); #elif defined(WIN32) verbose("%s: INFO: Directory set for real time monitoring: " "'%s'.", ARGV0, syscheck.dir[r]); #else verbose("%s: WARN: Ignoring flag for real time monitoring on " "directory: '%s'.", ARGV0, syscheck.dir[r]); #endif } r++; } /* Some sync time */ sleep(syscheck.tsleep + 10); /* Start the daemon */ start_daemon(); }
void OS_ReadMSG_analysisd(int m_queue) #endif { int i; char msg[OS_MAXSTR +1]; Eventinfo *lf; RuleInfo *stats_rule = NULL; /* Null to global currently pointers */ currently_rule = NULL; /* Initiating the logs */ OS_InitLog(); /* Initiating the integrity database */ SyscheckInit(); /* Initializing Rootcheck */ RootcheckInit(); /* Initializing host info */ HostinfoInit(); /* Creating the event list */ OS_CreateEventList(Config.memorysize); /* Initiating the FTS list */ if(!FTS_Init()) { ErrorExit(FTS_LIST_ERROR, ARGV0); } /* Initialize the Accumulator */ if(!Accumulate_Init()) { merror("accumulator: ERROR: Initialization failed"); exit(1); } /* Starting the active response queues */ if(Config.ar) { /* Waiting the ARQ to settle .. */ sleep(3); #ifndef LOCAL if(Config.ar & REMOTE_AR) { if((arq = StartMQ(ARQUEUE, WRITE)) < 0) { merror(ARQ_ERROR, ARGV0); /* If LOCAL_AR is set, keep it there */ if(Config.ar & LOCAL_AR) { Config.ar = 0; Config.ar|=LOCAL_AR; } else { Config.ar = 0; } } else { verbose(CONN_TO, ARGV0, ARQUEUE, "active-response"); } } #else /* Only for LOCAL_ONLY installs */ if(Config.ar & REMOTE_AR) { if(Config.ar & LOCAL_AR) { Config.ar = 0; Config.ar|=LOCAL_AR; } else { Config.ar = 0; } } #endif if(Config.ar & LOCAL_AR) { if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0) { merror(ARQ_ERROR, ARGV0); /* If REMOTE_AR is set, keep it there */ if(Config.ar & REMOTE_AR) { Config.ar = 0; Config.ar|=REMOTE_AR; } else { Config.ar = 0; } } else { verbose(CONN_TO, ARGV0, EXECQUEUE, "exec"); } } } debug1("%s: DEBUG: Active response Init completed.", ARGV0); /* Getting currently time before starting */ c_time = time(NULL); /* Starting the hourly/weekly stats */ if(Start_Hour() < 0) Config.stats = 0; else { /* Initializing stats rules */ stats_rule = zerorulemember( STATS_MODULE, Config.stats, 0,0,0,0,0,0); if(!stats_rule) { ErrorExit(MEM_ERROR, ARGV0); } stats_rule->group = "stats,"; stats_rule->comment = "Excessive number of events (above normal)."; } /* Doing some cleanup */ memset(msg, '\0', OS_MAXSTR +1); /* Initializing the logs */ { lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); if(!lf) ErrorExit(MEM_ERROR, ARGV0); lf->year = prev_year; strncpy(lf->mon, prev_month, 3); lf->day = today; if(OS_GetLogLocation(lf) < 0) { ErrorExit("%s: Error allocating log files", ARGV0); } Free_Eventinfo(lf); } debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0); if(Config.custom_alert_output) debug1("%s: INFO: Custom output found.!",ARGV0); /* Daemon loop */ while(1) { lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); /* This shouldn't happen .. */ if(lf == NULL) { ErrorExit(MEM_ERROR,ARGV0); } DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0)); /* Receive message from queue */ if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg))) { RuleNode *rulenode_pt; /* Getting the time we received the event */ c_time = time(NULL); /* Default values for the log info */ Zero_Eventinfo(lf); /* Checking for a valid message. */ if(i < 4) { merror(IMSG_ERROR, ARGV0, msg); Free_Eventinfo(lf); continue; } /* Message before extracting header */ DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg); /* Clean the msg appropriately */ if(OS_CleanMSG(msg, lf) < 0) { merror(IMSG_ERROR,ARGV0, msg); Free_Eventinfo(lf); continue; } /* Msg cleaned */ DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log); /* Currently rule must be null in here */ currently_rule = NULL; /** Checking the date/hour changes **/ /* Update the hour */ if(thishour != __crt_hour) { /* Search all the rules and print the number * of alerts that each one fired. */ DumpLogstats(); thishour = __crt_hour; /* Check if the date has changed */ if(today != lf->day) { if(Config.stats) { /* Update the hourly stats (done daily) */ Update_Hour(); } if(OS_GetLogLocation(lf) < 0) { ErrorExit("%s: Error allocating log files", ARGV0); } today = lf->day; strncpy(prev_month, lf->mon, 3); prev_year = lf->year; } } /* Incrementing number of events received */ hourly_events++; /*** Running decoders ***/ /* Integrity check from syscheck */ if(msg[0] == SYSCHECK_MQ) { hourly_syscheck++; if(!DecodeSyscheck(lf)) { /* We don't process syscheck events further */ goto CLMEM; } /* Getting log size */ lf->size = strlen(lf->log); } /* Rootcheck decoding */ else if(msg[0] == ROOTCHECK_MQ) { if(!DecodeRootcheck(lf)) { /* We don't process rootcheck events further */ goto CLMEM; } lf->size = strlen(lf->log); } /* Host information special decoder */ else if(msg[0] == HOSTINFO_MQ) { if(!DecodeHostinfo(lf)) { /* We don't process hostinfo events further */ goto CLMEM; } lf->size = strlen(lf->log); } /* Run the general Decoders */ else { /* Getting log size */ lf->size = strlen(lf->log); DecodeEvent(lf); } /* Run accumulator */ if( lf->decoder_info->accumulate == 1 ) { lf = Accumulate(lf); } /* Firewall event */ if(lf->decoder_info->type == FIREWALL) { /* If we could not get any information from * the log, just ignore it */ hourly_firewall++; if(Config.logfw) { if(!FW_Log(lf)) { goto CLMEM; } } } /* We only check if the last message is * duplicated on syslog. */ else if(lf->decoder_info->type == SYSLOG) { /* Checking if the message is duplicated */ if(LastMsg_Stats(lf->full_log) == 1) goto CLMEM; else LastMsg_Change(lf->full_log); } /* Stats checking */ if(Config.stats) { if(Check_Hour() == 1) { void *saved_rule = lf->generated_rule; char *saved_log; /* Saving previous log */ saved_log = lf->full_log; lf->generated_rule = stats_rule; lf->full_log = __stats_comment; /* alert for statistical analysis */ if(stats_rule->alert_opts & DO_LOGALERT) { __crt_ftell = ftell(_aflog); if(Config.custom_alert_output) { OS_CustomLog(lf,Config.custom_alert_output_format); } else { OS_Log(lf); } } /* Set lf to the old values */ lf->generated_rule = saved_rule; lf->full_log = saved_log; } } /* Checking the rules */ DEBUG_MSG("%s: DEBUG: Checking the rules - %d ", ARGV0, lf->decoder_info->type); /* Looping all the rules */ rulenode_pt = OS_GetFirstRule(); if(!rulenode_pt) { ErrorExit("%s: Rules in an inconsistent state. Exiting.", ARGV0); } do { if(lf->decoder_info->type == OSSEC_ALERT) { if(!lf->generated_rule) { goto CLMEM; } /* We go ahead in here and process the alert. */ currently_rule = lf->generated_rule; } /* The categories must match */ else if(rulenode_pt->ruleinfo->category != lf->decoder_info->type) { continue; } /* Checking each rule. */ else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt)) == NULL) { continue; } /* Ignore level 0 */ if(currently_rule->level == 0) { break; } /* Checking ignore time */ if(currently_rule->ignore_time) { if(currently_rule->time_ignored == 0) { currently_rule->time_ignored = lf->time; } /* If the currently time - the time the rule was ignored * is less than the time it should be ignored, * leave (do not alert again). */ else if((lf->time - currently_rule->time_ignored) < currently_rule->ignore_time) { break; } else { currently_rule->time_ignored = lf->time; } } /* Pointer to the rule that generated it */ lf->generated_rule = currently_rule; /* Checking if we should ignore it */ if(currently_rule->ckignore && IGnore(lf)) { /* Ignoring rule */ lf->generated_rule = NULL; break; } /* Checking if we need to add to ignore list */ if(currently_rule->ignore) { AddtoIGnore(lf); } /* Log the alert if configured to ... */ if(currently_rule->alert_opts & DO_LOGALERT) { __crt_ftell = ftell(_aflog); if(Config.custom_alert_output) { OS_CustomLog(lf,Config.custom_alert_output_format); } else { OS_Log(lf); } } /* Log to prelude */ #ifdef PRELUDE if(Config.prelude) { if(Config.prelude_log_level <= currently_rule->level) { OS_PreludeLog(lf); } } #endif /* Log to zeromq */ #ifdef ZEROMQ_OUTPUT if(Config.zeromq_output) { zeromq_output_event(lf); } #endif /* Log to Picviz */ if (Config.picviz) { OS_PicvizLog(lf); } /* Execute an active response */ if(currently_rule->ar) { int do_ar; active_response **rule_ar; rule_ar = currently_rule->ar; while(*rule_ar) { do_ar = 1; if((*rule_ar)->ar_cmd->expect & USERNAME) { if(!lf->dstuser || !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$")) { if(lf->dstuser) merror(CRAFTED_USER, ARGV0, lf->dstuser); do_ar = 0; } } if((*rule_ar)->ar_cmd->expect & SRCIP) { if(!lf->srcip || !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$")) { if(lf->srcip) merror(CRAFTED_IP, ARGV0, lf->srcip); do_ar = 0; } } if((*rule_ar)->ar_cmd->expect & FILENAME) { if(!lf->filename) { do_ar = 0; } } if(do_ar) { OS_Exec(&execdq, &arq, lf, *rule_ar); } rule_ar++; } } /* Copy the structure to the state memory of if_matched_sid */ if(currently_rule->sid_prev_matched) { if(!OSList_AddData(currently_rule->sid_prev_matched, lf)) { merror("%s: Unable to add data to sig list.", ARGV0); } else { lf->sid_node_to_delete = currently_rule->sid_prev_matched->last_node; } } /* Group list */ else if(currently_rule->group_prev_matched) { i = 0; while(i < currently_rule->group_prev_matched_sz) { if(!OSList_AddData( currently_rule->group_prev_matched[i], lf)) { merror("%s: Unable to add data to grp list.",ARGV0); } i++; } } OS_AddEvent(lf); break; }while((rulenode_pt = rulenode_pt->next) != NULL); /* If configured to log all, do it */ if(Config.logall) OS_Store(lf); /* Cleaning the memory */ CLMEM: /* Only clear the memory if the eventinfo was not * added to the stateful memory * -- message is free inside clean event -- */ if(lf->generated_rule == NULL) Free_Eventinfo(lf); } else { free(lf); } } return; }
/** void HandleSyslog() v0.2 * Handle syslog connections */ void HandleSyslog() { char buffer[OS_SIZE_1024 +2]; char srcip[IPSIZE +1]; char *buffer_pt = NULL; int recv_b; struct sockaddr_storage peer_info; socklen_t peer_size; /* setting peer size */ peer_size = sizeof(peer_info); /* Initializing some variables */ memset(buffer, '\0', OS_SIZE_1024 +2); /* Connecting to the message queue * Exit if it fails. */ if((logr.m_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) { ErrorExit(QUEUE_FATAL,ARGV0, DEFAULTQUEUE); } /* Infinite loop in here */ while(1) { /* Receiving message */ recv_b = recvfrom(logr.sock, buffer, OS_SIZE_1024, 0, (struct sockaddr *)&peer_info, &peer_size); /* Nothing received */ if(recv_b <= 0) continue; /* null terminating the message */ buffer[recv_b] = '\0'; /* Removing new line */ if(buffer[recv_b -1] == '\n') { buffer[recv_b -1] = '\0'; } /* Setting the source ip */ satop((struct sockaddr *) &peer_info, srcip, IPSIZE); srcip[IPSIZE] = '\0'; /* Removing syslog header */ if(buffer[0] == '<') { buffer_pt = strchr(buffer+1, '>'); if(buffer_pt) { buffer_pt++; } else { buffer_pt = buffer; } } else { buffer_pt = buffer; } /* Checking if IP is allowed here */ if(OS_IPNotAllowed(srcip)) { merror(DENYIP_WARN,ARGV0,srcip); } else if(SendMSG(logr.m_queue, buffer_pt, srcip, SYSLOG_MQ) < 0) { merror(QUEUE_ERROR,ARGV0,DEFAULTQUEUE, strerror(errno)); if((logr.m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0) { ErrorExit(QUEUE_FATAL,ARGV0,DEFAULTQUEUE); } } } }
/* AgentdStart v0.2, 2005/11/09 * Starts the agent daemon. */ void AgentdStart(char *dir, int uid, int gid, char *user, char *group) { int rc = 0; int pid = 0; int maxfd = 0; fd_set fdset; struct timeval fdtimeout; pid = getpid(); available_server = 0; /* Going Daemon */ if (!run_foreground) { nowDaemon(); goDaemonLight(); } /* Setting group ID */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR, ARGV0, group); /* chrooting */ if(Privsep_Chroot(dir) < 0) ErrorExit(CHROOT_ERROR, ARGV0, dir); nowChroot(); if(Privsep_SetUser(uid) < 0) ErrorExit(SETUID_ERROR, ARGV0, user); /* Create the queue. In this case we are going to create * and read from it * Exit if fails. */ if((agt->m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); maxfd = agt->m_queue; agt->sock = -1; /* Creating PID file */ if(CreatePID(ARGV0, getpid()) < 0) merror(PID_ERROR,ARGV0); /* Reading the private keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); OS_StartCounter(&keys); /* cmoraes : changed the following call to os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id); */ os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id, agt->profile); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); /* Initial random numbers */ #ifdef __OpenBSD__ srandomdev(); #else srandom( time(0) + getpid()+ pid + getppid()); #endif random(); /* Connecting UDP */ rc = 0; while(rc < agt->rip_id) { verbose("%s: INFO: Server IP Address: %s", ARGV0, agt->rip[rc]); rc++; } /* Trying to connect to the server */ if(!connect_server(0)) { ErrorExit(UNABLE_CONN, ARGV0); } /* Setting max fd for select */ if(agt->sock > maxfd) { maxfd = agt->sock; } /* Connecting to the execd queue */ if(agt->execdq == 0) { if((agt->execdq = StartMQ(EXECQUEUE, WRITE)) < 0) { merror("%s: INFO: Unable to connect to the active response " "queue (disabled).", ARGV0); agt->execdq = -1; } } /* Trying to connect to server */ os_setwait(); start_agent(1); os_delwait(); /* Sending integrity message for agent configs */ intcheck_file(OSSECCONF, dir); intcheck_file(OSSEC_DEFINES, dir); /* Sending first notification */ run_notify(); /* Maxfd must be higher socket +1 */ maxfd++; /* monitor loop */ while(1) { /* Monitoring all available sockets from here */ FD_ZERO(&fdset); FD_SET(agt->sock, &fdset); FD_SET(agt->m_queue, &fdset); fdtimeout.tv_sec = 1; fdtimeout.tv_usec = 0; /* Continuously send notifications */ run_notify(); /* Wait with a timeout for any descriptor */ rc = select(maxfd, &fdset, NULL, NULL, &fdtimeout); if(rc == -1) { ErrorExit(SELECT_ERROR, ARGV0); } else if(rc == 0) { continue; } /* For the receiver */ if(FD_ISSET(agt->sock, &fdset)) { receive_msg(); } /* For the forwarder */ if(FD_ISSET(agt->m_queue, &fdset)) { EventForward(); } } }
/* Real monitord global */ void Monitord() { time_t tm; struct tm *p; int today = 0; int thismonth = 0; int thisyear = 0; char str[OS_SIZE_1024 +1]; /* Waiting a few seconds to settle */ sleep(10); memset(str, '\0', OS_SIZE_1024 +1); /* Getting currently time before starting */ tm = time(NULL); p = localtime(&tm); today = p->tm_mday; thismonth = p->tm_mon; thisyear = p->tm_year+1900; /* Connecting to the message queue * Exit if it fails. */ if((mond.a_queue = StartMQ(DEFAULTQUEUE,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } /* Sending startup message */ snprintf(str, OS_SIZE_1024 -1, OS_AD_STARTED); if(SendMSG(mond.a_queue, str, ARGV0, LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); } /* Main monitor loop */ while(1) { tm = time(NULL); p = localtime(&tm); /* Checking unavailable agents */ if(mond.monitor_agents) { monitor_agents(); } /* Day changed, deal with log files */ if(today != p->tm_mday) { /* Generate reports. */ generate_reports(today, thismonth, thisyear, p); manage_files(today, thismonth, thisyear); today = p->tm_mday; thismonth = p->tm_mon; thisyear = p->tm_year+1900; } /* We only check every two minutes */ sleep(120); } }
/* Read DJB multilog. */ void *read_djbmultilog(int pos, int *rc, int drop_it) { int str_len = 0; int need_clear = 0; char *p; char str[OS_MAXSTR + 1]; char buffer[OS_MAXSTR + 1]; str[OS_MAXSTR]= '\0'; *rc = 0; /* Must have a valid program name. */ if(!logff[pos].djb_program_name) { return(NULL); } /* Getting new entry */ while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) { /* Getting buffer size */ str_len = strlen(str); /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; /* If need clear is set, we just get the line and ignore it. */ if(need_clear) { need_clear = 0; continue; } } else { need_clear = 1; } /* Multilog messages have the following format: * @40000000463246020c2ca16c xx... */ if((str_len > 26) && (str[0] == '@') && isalnum((int)str[1]) && isalnum((int)str[2]) && isalnum((int)str[3]) && isalnum((int)str[24]) && (str[25] == ' ')) { /* Removing spaces and tabs */ p = str + 26; while(*p == ' ' || *p == '\t') { p++; } /* If message has a valid syslog header, send as is. */ if((str_len > 44) && (p[3] == ' ') && (p[6] == ' ') && (p[9] == ':') && (p[12] == ':') && (p[15] == ' ')) { p+=16; strncpy(buffer, p, OS_MAXSTR); } else { /* We will add a proper syslog header. */ time_t djbtime; struct tm *pt; djbtime = time(NULL); pt = localtime(&djbtime); /* Syslog time: Apr 27 14:50:32 */ snprintf(buffer, OS_MAXSTR, "%s %02d %02d:%02d:%02d %s %s: %s", djb_month[pt->tm_mon], pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec, djb_host, logff[pos].djb_program_name, p); } } else { debug2("%s: DEBUG: Invalid DJB log: '%s'", ARGV0, str); continue; } debug2("%s: DEBUG: Reading DJB multilog message: '%s'", ARGV0, buffer); /* Sending message to queue */ if(drop_it == 0) { if(SendMSG(logr_queue, buffer, logff[pos].file, MYSQL_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } continue; } return(NULL); }
/* Read syslog files */ void *read_syslog(int pos, int *rc, int drop_it) { int __ms = 0; char *p; char str[OS_MAXSTR + 1]; fpos_t fp_pos; str[OS_MAXSTR] = '\0'; *rc = 0; /* Get initial file location */ fgetpos(logff[pos].fp, &fp_pos); while (fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) { /* Get the last occurrence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; /* From issue #913 @ybonnamy */ } else if((p = strchr(str, '\0')) != NULL) { /* Replace NUL with a space */ *p = ' '; } /* If we didn't get the new line, because the * size is large, send what we got so far. */ else if (strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2)) { /* Message size > maximum allowed */ __ms = 1; } else { /* Message not complete. Return. */ debug1("%s: Message not complete. Trying again: '%s'", ARGV0, str); fsetpos(logff[pos].fp, &fp_pos); break; } #ifdef WIN32 if ((p = strrchr(str, '\r')) != NULL) { *p = '\0'; } /* Look for empty string (only on Windows) */ if (strlen(str) <= 2) { fgetpos(logff[pos].fp, &fp_pos); continue; } /* Windows can have comment on their logs */ if (str[0] == '#') { fgetpos(logff[pos].fp, &fp_pos); continue; } #endif debug2("%s: DEBUG: Reading syslog message: '%s'", ARGV0, str); /* Send message to queue */ if (drop_it == 0) { if (SendMSG(logr_queue, str, logff[pos].file, LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if ((logr_queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } /* Incorrect message size */ if (__ms) { // strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2) // truncate str before logging to ossec.log #define OUTSIZE 4096 char buf[OUTSIZE + 1]; buf[OUTSIZE] = '\0'; snprintf(buf, OUTSIZE, "%s", str); merror("%s: Large message size(length=%d): '%s...'", ARGV0, (int)strlen(str), buf); while (fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL) { /* Get the last occurrence of \n */ if (strrchr(str, '\n') != NULL) { break; } } __ms = 0; } fgetpos(logff[pos].fp, &fp_pos); continue; } return (NULL); }
/* Locally starts (after service/win init) */ int local_start() { int debug_level; int accept_manager_commands = 0; char *cfg = DEFAULTCPATH; WSADATA wsaData; DWORD threadID; DWORD threadID2; /* Starting logr */ logr = (agent *)calloc(1, sizeof(agent)); if(!logr) { ErrorExit(MEM_ERROR, ARGV0); } logr->port = DEFAULT_SECURE; /* Getting debug level */ debug_level = getDefine_Int("windows","debug", 0, 2); while(debug_level != 0) { nowDebug(); debug_level--; } accept_manager_commands = getDefine_Int("logcollector", "remote_commands", 0, 1); /* Configuration file not present */ if(File_DateofChange(cfg) < 0) ErrorExit("%s: Configuration file '%s' not found",ARGV0,cfg); /* Starting Winsock */ if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { ErrorExit("%s: WSAStartup() failed", ARGV0); } /* Read agent config */ debug1("%s: DEBUG: Reading agent configuration.", ARGV0); if(ClientConf(cfg) < 0) { ErrorExit(CLIENT_ERROR,ARGV0); } if(logr->notify_time == 0) { logr->notify_time = NOTIFY_TIME; } if(logr->max_time_reconnect_try == 0 ) { logr->max_time_reconnect_try = NOTIFY_TIME * 3; } if(logr->max_time_reconnect_try <= logr->notify_time) { logr->max_time_reconnect_try = (logr->notify_time * 3); verbose("%s Max time to reconnect can't be less than notify_time(%d), using notify_time*3 (%d)",ARGV0,logr->notify_time,logr->max_time_reconnect_try); } verbose("%s Using notify time: %d and max time to reconnect: %d",ARGV0,logr->notify_time,logr->max_time_reconnect_try); /* Reading logcollector config file */ debug1("%s: DEBUG: Reading logcollector configuration.", ARGV0); if(LogCollectorConfig(cfg, accept_manager_commands) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, cfg); } /* Checking auth keys */ if(!OS_CheckKeys()) { ErrorExit(AG_NOKEYS_EXIT, ARGV0); } /* If there is not file to monitor, create a clean entry * for the mark messages. */ if(logff == NULL) { os_calloc(2, sizeof(logreader), logff); logff[0].file = NULL; logff[0].ffile = NULL; logff[0].logformat = NULL; logff[0].fp = NULL; logff[1].file = NULL; logff[1].logformat = NULL; merror(NO_FILE, ARGV0); } /* Reading execd config. */ if(!WinExecd_Start()) { logr->execdq = -1; } /* Reading keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); OS_StartCounter(&keys); os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id, NULL); /* Initial random numbers */ srandom(time(0)); random(); /* Socket connection */ logr->sock = -1; StartMQ(NULL, 0); /* Starting mutex */ debug1("%s: DEBUG: Creating thread mutex.", ARGV0); hMutex = CreateMutex(NULL, FALSE, NULL); if(hMutex == NULL) { ErrorExit("%s: Error creating mutex.", ARGV0); } /* Starting syscheck thread */ if(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)skthread, NULL, 0, (LPDWORD)&threadID) == NULL) { merror(THREAD_ERROR, ARGV0); } /* Checking if server is connected */ os_setwait(); start_agent(1); os_delwait(); /* Sending integrity message for agent configs */ intcheck_file(cfg, ""); intcheck_file(OSPATROL_DEFINES, ""); /* Starting receiver thread */ if(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)receiver_thread, NULL, 0, (LPDWORD)&threadID2) == NULL) { merror(THREAD_ERROR, ARGV0); } /* Sending agent information message */ send_win32_info(time(0)); /* Startting logcollector -- main process here */ LogCollectorStart(); WSACleanup(); return(0); }
/** int main(int argc, char **argv) v0.1 */ int main(int argc, char **argv) { int c; int test_config = 0,run_foreground = 0; gid_t gid; int m_queue = 0; const char *group = GROUPGLOBAL; const char *cfg = DEFAULTCPATH; /* Setting the name */ OS_SetName(ARGV0); while((c = getopt(argc, argv, "Vtdhfg:c:")) != -1){ switch(c){ case 'V': print_version(); break; case 'h': help_execd(); break; case 'd': nowDebug(); break; case 'f': run_foreground = 1; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument.",ARGV0); group = optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument.",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; default: help_execd(); break; } } /* Check if the group given are valid */ gid = Privsep_GetGroup(group); if(gid == (gid_t)-1) ErrorExit(USER_ERROR,ARGV0,"",group); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group, errno, strerror(errno)); /* Reading config */ if((c = ExecdConfig(cfg)) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, cfg); } /* Exit if test_config */ if(test_config) exit(0); /* Signal manipulation */ StartSIG2(ARGV0, execd_shutdown); if (!run_foreground) { /* Going daemon */ nowDaemon(); goDaemon(); } /* Active response disabled */ if(c == 1) { verbose(EXEC_DISABLED, ARGV0); exit(0); } /* Creating the PID file */ if(CreatePID(ARGV0, getpid()) < 0) merror(PID_ERROR, ARGV0); /* Starting queue (exec queue) */ if((m_queue = StartMQ(EXECQUEUEPATH,READ)) < 0) ErrorExit(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno)); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); /* The real daemon Now */ ExecdStart(m_queue); exit(0); }
/* Handle secure connections */ void HandleSecure() { int agentid; char buffer[OS_MAXSTR + 1]; char cleartext_msg[OS_MAXSTR + 1]; char srcip[IPSIZE + 1]; char *tmp_msg; char srcmsg[OS_FLSIZE + 1]; ssize_t recv_b; struct sockaddr_in peer_info; socklen_t peer_size; /* Send msg init */ send_msg_init(); /* Initialize key mutex */ keyupdate_init(); /* Initialize manager */ manager_init(0); /* Create Active Response forwarder thread */ if (CreateThread(AR_Forward, (void *)NULL) != 0) { ErrorExit(THREAD_ERROR, ARGV0); } /* Create wait_for_msgs thread */ if (CreateThread(wait_for_msgs, (void *)NULL) != 0) { ErrorExit(THREAD_ERROR, ARGV0); } /* Connect to the message queue * Exit if it fails. */ if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } verbose(AG_AX_AGENTS, ARGV0, MAX_AGENTS); /* Read authentication keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); OS_StartCounter(&keys); /* Set up peer size */ peer_size = sizeof(peer_info); logr.peer_size = sizeof(peer_info); /* Initialize some variables */ memset(buffer, '\0', OS_MAXSTR + 1); memset(cleartext_msg, '\0', OS_MAXSTR + 1); memset(srcmsg, '\0', OS_FLSIZE + 1); tmp_msg = NULL; while (1) { /* Receive message */ recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0, (struct sockaddr *)&peer_info, &peer_size); /* Nothing received */ if (recv_b <= 0) { continue; } /* Set the source IP */ strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE); srcip[IPSIZE] = '\0'; /* Get a valid agent id */ if (buffer[0] == '!') { tmp_msg = buffer; tmp_msg++; /* We need to make sure that we have a valid id * and that we reduce the recv buffer size */ while (isdigit((int)*tmp_msg)) { tmp_msg++; recv_b--; } if (*tmp_msg != '!') { merror(ENCFORMAT_ERROR, __local_name, srcip); continue; } *tmp_msg = '\0'; tmp_msg++; recv_b -= 2; agentid = OS_IsAllowedDynamicID(&keys, buffer + 1, srcip); if (agentid == -1) { if (check_keyupdate()) { agentid = OS_IsAllowedDynamicID(&keys, buffer + 1, srcip); if (agentid == -1) { merror(ENC_IP_ERROR, ARGV0, srcip); continue; } } else { merror(ENC_IP_ERROR, ARGV0, srcip); continue; } } } else { agentid = OS_IsAllowedIP(&keys, srcip); if (agentid < 0) { if (check_keyupdate()) { agentid = OS_IsAllowedIP(&keys, srcip); if (agentid == -1) { merror(DENYIP_WARN, ARGV0, srcip); continue; } } else { merror(DENYIP_WARN, ARGV0, srcip); continue; } } tmp_msg = buffer; } /* Decrypt the message */ tmp_msg = ReadSecMSG(&keys, tmp_msg, cleartext_msg, agentid, recv_b - 1); if (tmp_msg == NULL) { /* If duplicated, a warning was already generated */ continue; } /* Check if it is a control message */ if (IsValidHeader(tmp_msg)) { /* We need to save the peerinfo if it is a control msg */ memcpy(&keys.keyentries[agentid]->peer_info, &peer_info, peer_size); keys.keyentries[agentid]->rcvd = time(0); save_controlmsg((unsigned)agentid, tmp_msg); continue; } /* Generate srcmsg */ snprintf(srcmsg, OS_FLSIZE, "(%s) %s", keys.keyentries[agentid]->name, keys.keyentries[agentid]->ip->ip); /* If we can't send the message, try to connect to the * socket again. If it not exit. */ if (SendMSG(logr.m_queue, tmp_msg, srcmsg, SECURE_MQ) < 0) { merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } } } }
/* Read Output of commands */ void *read_fullcommand(int pos, int *rc, int drop_it) { int n = 0; int cmd_size = 0; char *p; char str[OS_MAXSTR+1]; char strfinal[OS_MAXSTR+1]; FILE *cmd_output; str[OS_MAXSTR]= '\0'; strfinal[OS_MAXSTR]= '\0'; *rc = 0; debug2("%s: DEBUG: Running full command '%s'", ARGV0, logff[pos].command); cmd_output = popen(logff[pos].command, "r"); if(!cmd_output) { merror("%s: ERROR: Unable to execute command: '%s'.", ARGV0, logff[pos].command); logff[pos].command = NULL; } snprintf(str, 256, "ossec: output: '%s':\n", (NULL != logff[pos].alias) ? logff[pos].alias : logff[pos].command); cmd_size = strlen(str); n = fread(str + cmd_size, 1, OS_MAXSTR - OS_LOG_HEADER - 256, cmd_output); if(n > 0) { str[cmd_size +n] = '\0'; /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; } debug2("%s: DEBUG: Reading command message: '%s'", ARGV0, str); /* Removing empty lines. */ n = 0; p = str; while(*p != '\0') { if(p[0] == '\r') { p++; continue; } if(p[0] == '\n' && p[1] == '\n') { p++; } strfinal[n] = *p; n++; p++; } strfinal[n] = '\0'; /* Sending message to queue */ if(drop_it == 0) { if(SendMSG(logr_queue,strfinal, (NULL != logff[pos].alias) ? logff[pos].alias : logff[pos].command, LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } } pclose(cmd_output); return(NULL); }
/* Handle each client */ static void HandleClient(int client_socket, char *srcip) { int sb_size = OS_MAXSTR; int r_sz = 0; char buffer[OS_MAXSTR + 2]; char storage_buffer[OS_MAXSTR + 2]; char tmp_buffer[OS_MAXSTR + 2]; char *buffer_pt = NULL; /* Create PID file */ if (CreatePID(ARGV0, getpid()) < 0) { ErrorExit(PID_ERROR, ARGV0); } /* Initialize some variables */ memset(buffer, '\0', OS_MAXSTR + 2); memset(storage_buffer, '\0', OS_MAXSTR + 2); memset(tmp_buffer, '\0', OS_MAXSTR + 2); while (1) { /* If we fail, we need to return and close the socket */ if ((r_sz = OS_RecvTCPBuffer(client_socket, buffer, OS_MAXSTR - 2)) < 0) { close(client_socket); DeletePID(ARGV0); return; } /* We must have a new line at the end */ buffer_pt = strchr(buffer, '\n'); if (!buffer_pt) { /* Buffer is full */ if ((sb_size - r_sz) <= 2) { merror("%s: Full buffer receiving from: '%s'", ARGV0, srcip); sb_size = OS_MAXSTR; storage_buffer[0] = '\0'; continue; } strncat(storage_buffer, buffer, sb_size); sb_size -= r_sz; continue; } /* See if we received more than just one message */ if (*(buffer_pt + 1) != '\0') { *buffer_pt = '\0'; buffer_pt++; strncpy(tmp_buffer, buffer_pt, OS_MAXSTR); } /* Store everything in the storage_buffer * Check if buffer will be full */ if ((sb_size - r_sz) <= 2) { merror("%s: Full buffer receiving from: '%s'.", ARGV0, srcip); sb_size = OS_MAXSTR; storage_buffer[0] = '\0'; tmp_buffer[0] = '\0'; continue; } strncat(storage_buffer, buffer, sb_size); /* Remove carriage returns too */ buffer_pt = strchr(storage_buffer, '\r'); if (buffer_pt) { *buffer_pt = '\0'; } /* Remove syslog header */ if (storage_buffer[0] == '<') { buffer_pt = strchr(storage_buffer + 1, '>'); if (buffer_pt) { buffer_pt++; } else { buffer_pt = storage_buffer; } } else { buffer_pt = storage_buffer; } /* Send to the queue */ if (SendMSG(logr.m_queue, buffer_pt, srcip, SYSLOG_MQ) < 0) { merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } } /* Clean up the buffers */ if (tmp_buffer[0] != '\0') { strncpy(storage_buffer, tmp_buffer, OS_MAXSTR); sb_size = OS_MAXSTR - (strlen(storage_buffer) + 1); tmp_buffer[0] = '\0'; } else { storage_buffer[0] = '\0'; sb_size = OS_MAXSTR; } } }
/** void *AR_Forward(void *arg) v0.1 * Start of a new thread. Only returns * on unrecoverable errors. */ void *AR_Forward(void *arg) { int i = 0; int arq = 0; int agent_id = 0; int ar_location = 0; char msg_to_send[OS_SIZE_1024 +1]; char msg[OS_SIZE_1024 +1]; char *location = NULL; char *ar_location_str = NULL; char *ar_agent_id = NULL; char *tmp_str = NULL; /* Creating the unix queue */ if((arq = StartMQ(ARQUEUE, READ)) < 0) { ErrorExit(QUEUE_ERROR, ARGV0, ARQUEUE, strerror(errno)); } memset(msg, '\0', OS_SIZE_1024 +1); /* Daemon loop */ while(1) { if(OS_RecvUnix(arq, OS_SIZE_1024, msg)) { /* Always zeroing the location */ ar_location = 0; /* Getting the location */ location = msg; /* Location is going to be the agent name */ tmp_str = strchr(msg, ')'); if(!tmp_str) { merror(EXECD_INV_MSG, ARGV0, msg); continue; } *tmp_str = '\0'; /* Going after the ')' and space */ tmp_str += 2; /* Extracting the source ip */ tmp_str = strchr(tmp_str, ' '); if(!tmp_str) { merror(EXECD_INV_MSG, ARGV0, msg); continue; } tmp_str++; location++; /* Setting ar_location */ ar_location_str = tmp_str; if(*tmp_str == ALL_AGENTS_C) { ar_location|=ALL_AGENTS; } tmp_str++; if(*tmp_str == REMOTE_AGENT_C) { ar_location|=REMOTE_AGENT; } else if(*tmp_str == NO_AR_C) { ar_location|=NO_AR_MSG; } tmp_str++; if(*tmp_str == SPECIFIC_AGENT_C) { ar_location|=SPECIFIC_AGENT; } /*** Extracting the active response location ***/ tmp_str = strchr(ar_location_str, ' '); if(!tmp_str) { merror(EXECD_INV_MSG, ARGV0, msg); continue; } *tmp_str = '\0'; tmp_str++; /*** Extracting the agent id */ ar_agent_id = tmp_str; tmp_str = strchr(tmp_str, ' '); if(!tmp_str) { merror(EXECD_INV_MSG, ARGV0, msg); continue; } *tmp_str = '\0'; tmp_str++; /*** Creating the new message ***/ if(ar_location & NO_AR_MSG) { snprintf(msg_to_send, OS_SIZE_1024, "%s%s", CONTROL_HEADER, tmp_str); } else { snprintf(msg_to_send, OS_SIZE_1024, "%s%s%s", CONTROL_HEADER, EXECD_HEADER, tmp_str); } /* Lock use of keys */ key_lock(); /* Sending to ALL agents */ if(ar_location & ALL_AGENTS) { for(i = 0;i< keys.keysize; i++) { send_msg(i, msg_to_send); } } /* Send to the remote agent that generated the event */ else if((ar_location & REMOTE_AGENT) && (location != NULL)) { agent_id = OS_IsAllowedName(&keys, location); if(agent_id < 0) { key_unlock(); merror(AR_NOAGENT_ERROR, ARGV0, location); continue; } send_msg(agent_id, msg_to_send); } /* Send to a pre-defined agent */ else if(ar_location & SPECIFIC_AGENT) { ar_location++; agent_id = OS_IsAllowedID(&keys, ar_agent_id); if(agent_id < 0) { key_unlock(); merror(AR_NOAGENT_ERROR, ARGV0, ar_agent_id); continue; } send_msg(agent_id, msg_to_send); } /* Lock use of keys */ key_unlock(); } } }
/* Read Output of commands */ void *read_command(int pos, int *rc, int drop_it) { size_t cmd_size = 0; char *p; char str[OS_MAXSTR+1]; FILE *cmd_output; str[OS_MAXSTR]= '\0'; *rc = 0; debug2("%s: DEBUG: Running command '%s'", ARGV0, logff[pos].command); cmd_output = popen(logff[pos].command, "r"); if(!cmd_output) { merror("%s: ERROR: Unable to execute command: '%s'.", ARGV0, logff[pos].command); logff[pos].command = NULL; return (NULL); } snprintf(str, 256, "ossec: output: '%s': ", (NULL != logff[pos].alias) ? logff[pos].alias : logff[pos].command); cmd_size = strlen(str); while(fgets(str + cmd_size, OS_MAXSTR - OS_LOG_HEADER - 256, cmd_output) != NULL) { /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; } /* Removing empty lines. */ #ifdef WIN32 if(str[0] == '\r' && str[1] == '\0') { continue; } #endif if(str[0] == '\0') { continue; } debug2("%s: DEBUG: Reading command message: '%s'", ARGV0, str); /* Sending message to queue */ if(drop_it == 0) { if(SendMSG(logr_queue,str, (NULL != logff[pos].alias) ? logff[pos].alias : logff[pos].command, LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } continue; } pclose(cmd_output); return(NULL); }
/* Read multiline logs. */ void *read_multiline(int pos, int *rc, int drop_it) { int __ms = 0; int linecount; int linesgot = 0; size_t buffer_size = 0; char *p; char str[OS_MAXSTR + 1]; char buffer[OS_MAXSTR +1]; fpos_t fp_pos; buffer[0] = '\0'; buffer[OS_MAXSTR] = '\0'; str[OS_MAXSTR]= '\0'; *rc = 0; linecount = atoi(logff[pos].logformat); /* Getting initial file location */ fgetpos(logff[pos].fp, &fp_pos); while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) { linesgot++; /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; } /* If we didn't get the new line, because the * size is large, send what we got so far. */ else if(strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2)) { /* Message size > maximum allowed */ __ms = 1; } else { /* Message not complete. Return. */ debug1("%s: Message not complete. Trying again: '%s'", ARGV0,str); fsetpos(logff[pos].fp, &fp_pos); break; } #ifdef WIN32 if ((p = strrchr(str, '\r')) != NULL) { *p = '\0'; } #endif debug2("%s: DEBUG: Reading message: '%s'", ARGV0, str); /* Adding to buffer. */ buffer_size = strlen(buffer); if(buffer[0] != '\0') { buffer[buffer_size] = ' '; buffer_size++; } strncpy(buffer + buffer_size, str, OS_MAXSTR - buffer_size -2); if(linesgot < linecount) { continue; } /* Sending message to queue */ if(drop_it == 0) { if(SendMSG(logr_queue, buffer, logff[pos].file, LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } buffer[0] = '\0'; /* Incorrectly message size */ if(__ms) { merror("%s: Large message size: '%s'", ARGV0, str); while(fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL) { /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { break; } } __ms = 0; } fgetpos(logff[pos].fp, &fp_pos); continue; } return(NULL); }
/* Read syslog files/snort fast/apache files */ void *read_mysql_log(int pos, int *rc, int drop_it) { size_t str_len = 0; int need_clear = 0; char *p; char str[OS_MAXSTR + 1]; char buffer[OS_MAXSTR + 1]; str[OS_MAXSTR]= '\0'; *rc = 0; /* Getting new entry */ while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) { /* Getting buffer size */ str_len = strlen(str); /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; /* If need clear is set, we just get the line and ignore it. */ if(need_clear) { need_clear = 0; continue; } } else { need_clear = 1; } #ifdef WIN32 if ((p = strrchr(str, '\r')) != NULL) { *p = '\0'; } /* Looking for empty string (only on windows) */ if(str_len <= 2) { continue; } /* Windows can have comment on their logs */ if(str[0] == '#') { continue; } #endif /* Mysql messages have the following format: * 070823 21:01:30 xx */ if((str_len > 18) && (str[6] == ' ') && (str[9] == ':') && (str[12] == ':') && isdigit((int)str[0]) && isdigit((int)str[1]) && isdigit((int)str[2]) && isdigit((int)str[3]) && isdigit((int)str[4]) && isdigit((int)str[5]) && isdigit((int)str[7]) && isdigit((int)str[8])) { /* Saving last time */ strncpy(__mysql_last_time, str, 16); __mysql_last_time[15] = '\0'; /* Removing spaces and tabs */ p = str + 15; while(*p == ' ' || *p == '\t') { p++; } /* Valid MySQL message */ snprintf(buffer, OS_MAXSTR, "MySQL log: %s %s", __mysql_last_time, p); } /* Multiple events at the same second share the same * time stamp. * 0909 2020 2020 2020 20 */ else if((str_len > 10) && (__mysql_last_time[0] != '\0') && (str[0] == 0x09) && (str[1] == 0x09) && (str[2] == 0x20) && (str[3] == 0x20) && (str[4] == 0x20) && (str[5] == 0x20) && (str[6] == 0x20) && (str[7] == 0x20)) { p = str +2; /* Removing extra spaces and tabs */ while(*p == ' ' || *p == '\t') { p++; } /* Valid MySQL message */ snprintf(buffer, OS_MAXSTR, "MySQL log: %s %s", __mysql_last_time, p); } else { continue; } debug2("%s: DEBUG: Reading mysql messages: '%s'", ARGV0, buffer); /* Sending message to queue */ if(drop_it == 0) { if(SendMSG(logr_queue, buffer, logff[pos].file, MYSQL_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } continue; } return(NULL); }
int main_analysisd(int argc, char **argv) #endif { int c = 0, m_queue = 0, test_config = 0,run_foreground = 0; int debug_level = 0; char *dir = DEFAULTDIR; char *user = USER; char *group = GROUPGLOBAL; int uid = 0,gid = 0; char *cfg = DEFAULTCPATH; /* Setting the name */ OS_SetName(ARGV0); thishour = 0; today = 0; prev_year = 0; memset(prev_month, '\0', 4); hourly_alerts = 0; hourly_events = 0; hourly_syscheck = 0; hourly_firewall = 0; while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){ switch(c){ case 'V': print_version(); break; case 'h': help_analysisd(); break; case 'd': nowDebug(); debug_level = 1; break; case 'f': run_foreground = 1; break; case 'u': if(!optarg) ErrorExit("%s: -u needs an argument",ARGV0); user = optarg; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument",ARGV0); group = optarg; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); dir = optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; default: help_analysisd(); break; } } /* Check current debug_level * Command line setting takes precedence */ if (debug_level == 0) { /* Getting debug level */ debug_level = getDefine_Int("analysisd", "debug", 0, 2); while(debug_level != 0) { nowDebug(); debug_level--; } } /* Starting daemon */ debug1(STARTED_MSG,ARGV0); DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0)); /*Check if the user/group given are valid */ uid = Privsep_GetUser(user); gid = Privsep_GetGroup(group); if((uid < 0)||(gid < 0)) ErrorExit(USER_ERROR,ARGV0,user,group); /* Found user */ debug1(FOUND_USER, ARGV0); /* Initializing Active response */ AR_Init(); if(AR_ReadConfig(cfg) < 0) { ErrorExit(CONFIG_ERROR,ARGV0, cfg); } debug1(ASINIT, ARGV0); /* Reading configuration file */ if(GlobalConf(cfg) < 0) { ErrorExit(CONFIG_ERROR,ARGV0, cfg); } debug1(READ_CONFIG, ARGV0); /* Fixing Config.ar */ Config.ar = ar_flag; if(Config.ar == -1) Config.ar = 0; /* Getting servers hostname */ memset(__shost, '\0', 512); if(gethostname(__shost, 512 -1) != 0) { strncpy(__shost, OSSEC_SERVER, 512 -1); } else { char *_ltmp; /* Remove domain part if available */ _ltmp = strchr(__shost, '.'); if(_ltmp) *_ltmp = '\0'; } /* going on Daemon mode */ if(!test_config && !run_foreground) { nowDaemon(); goDaemon(); } /* Starting prelude */ #ifdef PRELUDE if(Config.prelude) { prelude_start(Config.prelude_profile, argc, argv); } #endif /* Starting zeromq */ #ifdef ZEROMQ_OUTPUT if(Config.zeromq_output) { zeromq_output_start(Config.zeromq_output_uri, argc, argv); } #endif /* Opening the Picviz socket */ if(Config.picviz) { OS_PicvizOpen(Config.picviz_socket); if(chown(Config.picviz_socket, uid, gid) == -1) { ErrorExit(CHOWN_ERROR, ARGV0, Config.picviz_socket); } } /* Setting the group */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* Chrooting */ if(Privsep_Chroot(dir) < 0) ErrorExit(CHROOT_ERROR,ARGV0,dir); nowChroot(); /* * Anonymous Section: Load rules, decoders, and lists * * As lists require two pass loading of rules that make use of list lookups * are created with blank database structs, and need to be filled in after * completion of all rules and lists. */ { { /* Initializing the decoders list */ OS_CreateOSDecoderList(); if(!Config.decoders) { /* Legacy loading */ /* Reading decoders */ if(!ReadDecodeXML(XML_DECODER)) { ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER); } /* Reading local ones. */ c = ReadDecodeXML(XML_LDECODER); if(!c) { if((c != -2)) ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER); } else { if(!test_config) verbose("%s: INFO: Reading local decoder file.", ARGV0); } } else { /* New loaded based on file speified in ossec.conf */ char **decodersfiles; decodersfiles = Config.decoders; while( decodersfiles && *decodersfiles) { if(!test_config) verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles); if(!ReadDecodeXML(*decodersfiles)) ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles); free(*decodersfiles); decodersfiles++; } } /* Load decoders */ SetDecodeXML(); } { /* Load Lists */ /* Initializing the lists of list struct */ Lists_OP_CreateLists(); /* Load each list into list struct */ { char **listfiles; listfiles = Config.lists; while(listfiles && *listfiles) { if(!test_config) verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles); if(Lists_OP_LoadList(*listfiles) < 0) ErrorExit(LISTS_ERROR, ARGV0, *listfiles); free(*listfiles); listfiles++; } free(Config.lists); Config.lists = NULL; } } { /* Load Rules */ /* Creating the rules list */ Rules_OP_CreateRules(); /* Reading the rules */ { char **rulesfiles; rulesfiles = Config.includes; while(rulesfiles && *rulesfiles) { if(!test_config) verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles); if(Rules_OP_ReadRules(*rulesfiles) < 0) ErrorExit(RULES_ERROR, ARGV0, *rulesfiles); free(*rulesfiles); rulesfiles++; } free(Config.includes); Config.includes = NULL; } /* Find all rules with that require list lookups and attache the * the correct list struct to the rule. This keeps rules from having to * search thought the list of lists for the correct file during rule evaluation. */ OS_ListLoadRules(); } } /* Fixing the levels/accuracy */ { int total_rules; RuleNode *tmp_node = OS_GetFirstRule(); total_rules = _setlevels(tmp_node, 0); if(!test_config) verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules); } /* Creating a rules hash (for reading alerts from other servers). */ { RuleNode *tmp_node = OS_GetFirstRule(); Config.g_rules_hash = OSHash_Create(); if(!Config.g_rules_hash) { ErrorExit(MEM_ERROR, ARGV0); } AddHash_Rule(tmp_node); } /* Ignored files on syscheck */ { char **files; files = Config.syscheck_ignore; while(files && *files) { if(!test_config) verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files); files++; } } /* Checking if log_fw is enabled. */ Config.logfw = getDefine_Int("analysisd", "log_fw", 0, 1); /* Success on the configuration test */ if(test_config) exit(0); /* Verbose message */ debug1(PRIVSEP_MSG, ARGV0, dir, user); /* Signal manipulation */ StartSIG(ARGV0); /* Setting the user */ if(Privsep_SetUser(uid) < 0) ErrorExit(SETUID_ERROR,ARGV0,user); /* Creating the PID file */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); /* Setting the queue */ if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0) ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); /* White list */ if(Config.white_list == NULL) { if(Config.ar) verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0); } else { if(Config.ar) { os_ip **wl; int wlc = 0; wl = Config.white_list; while(*wl) { verbose("%s: INFO: White listing IP: '%s'",ARGV0, (*wl)->ip); wl++;wlc++; } verbose("%s: INFO: %d IPs in the white list for active response.", ARGV0, wlc); } } /* Hostname White list */ if(Config.hostname_white_list == NULL) { if(Config.ar) verbose("%s: INFO: No Hostname in the white list for active reponse.", ARGV0); } else { if(Config.ar) { int wlc = 0; OSMatch **wl; wl = Config.hostname_white_list; while(*wl) { char **tmp_pts = (*wl)->patterns; while(*tmp_pts) { verbose("%s: INFO: White listing Hostname: '%s'",ARGV0,*tmp_pts); wlc++; tmp_pts++; } wl++; } verbose("%s: INFO: %d Hostname(s) in the white list for active response.", ARGV0, wlc); } } /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); /* Going to main loop */ OS_ReadMSG(m_queue); if (Config.picviz) { OS_PicvizClose(); } exit(0); }
/* main: v0.3: 2005/04/04 */ int main(int argc, char **argv) { int c; int debug_level = 0; int test_config = 0,run_foreground = 0; int accept_manager_commands = 0; const char *cfg = DEFAULTCPATH; /* Setuping up random */ #ifndef WIN32 #ifdef __OpenBSD__ srandomdev(); #else srandom((unsigned int)time(0)); #endif #else srandom(time(0)) #endif /* Setting the name */ OS_SetName(ARGV0); while((c = getopt(argc, argv, "Vtdhfc:")) != -1) { switch(c) { case 'V': print_version(); break; case 'h': help_logcollector(); break; case 'd': nowDebug(); debug_level = 1; break; case 'f': run_foreground = 1; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; default: help_logcollector(); break; } } /* Check current debug_level * Command line setting takes precedence */ if (debug_level == 0) { /* Getting debug level */ debug_level = getDefine_Int("logcollector", "debug", 0, 2); while(debug_level != 0) { nowDebug(); debug_level--; } } debug1(STARTED_MSG,ARGV0); accept_manager_commands = getDefine_Int("logcollector", "remote_commands", 0, 1); /* Reading config file */ if(LogCollectorConfig(cfg, accept_manager_commands) < 0) ErrorExit(CONFIG_ERROR, ARGV0, cfg); /* Getting loop timeout */ loop_timeout = getDefine_Int("logcollector", "loop_timeout", 1, 120); open_file_attempts = getDefine_Int("logcollector", "open_attempts", 2, 998); /* Exit if test config */ if(test_config) exit(0); /* No file available to monitor -- continue */ if(logff == NULL) { os_calloc(2, sizeof(logreader), logff); logff[0].file = NULL; logff[0].ffile = NULL; logff[0].logformat = NULL; logff[0].fp = NULL; logff[1].file = NULL; logff[1].logformat = NULL; merror(NO_FILE, ARGV0); } /* Starting signal handler */ StartSIG(ARGV0); if (!run_foreground) { /* Going on daemon mode */ nowDaemon(); goDaemon(); } /* Creating PID file */ if(CreatePID(ARGV0, getpid()) < 0) merror(PID_ERROR, ARGV0); /* Waiting 6 seconds for the analysisd/agentd to settle */ debug1("%s: DEBUG: Waiting main daemons to settle.", ARGV0); sleep(6); /* Starting the queue. */ if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); /* Main loop */ LogCollectorStart(); }
/* Read syslog files/snort fast/apache files */ void *read_syslog(int pos, int *rc, int drop_it) { int __ms = 0; char *p; char str[OS_MAXSTR+1]; fpos_t fp_pos; str[OS_MAXSTR]= '\0'; *rc = 0; /* Getting initial file location */ fgetpos(logff[pos].fp, &fp_pos); while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) { /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { *p = '\0'; } /* If we didn't get the new line, because the * size is large, send what we got so far. */ else if(strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2)) { /* Message size > maximum allowed */ __ms = 1; } else { /* Message not complete. Return. */ debug1("%s: Message not complete. Trying again: '%s'", ARGV0,str); fsetpos(logff[pos].fp, &fp_pos); break; } #ifdef WIN32 if ((p = strrchr(str, '\r')) != NULL) { *p = '\0'; } /* Looking for empty string (only on windows) */ if(strlen(str) <= 2) { fgetpos(logff[pos].fp, &fp_pos); continue; } /* Windows can have comment on their logs */ if(str[0] == '#') { fgetpos(logff[pos].fp, &fp_pos); continue; } #endif debug2("%s: DEBUG: Reading syslog message: '%s'", ARGV0, str); /* Sending message to queue */ if(drop_it == 0) { if(SendMSG(logr_queue,str,logff[pos].file, LOCALFILE_MQ) < 0) { merror(QUEUE_SEND, ARGV0); if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } } } /* Incorrectly message size */ if(__ms) { merror("%s: Large message size: '%s'", ARGV0, str); while(fgets(str, OS_MAXSTR - 2, logff[pos].fp) != NULL) { /* Getting the last occurence of \n */ if ((p = strrchr(str, '\n')) != NULL) { break; } } __ms = 0; } fgetpos(logff[pos].fp, &fp_pos); continue; } return(NULL); }