1 /* @(#) $Id: ./src/analysisd/analysisd.c, 2012/07/26 dcid Exp $
4 /* Copyright (C) 2010-2012 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/en/licensing.html
18 * Available at http://www.ossec.net
23 * Responsible for correlation and log decoding.
27 #define ARGV0 "ossec-analysisd"
32 #include "alerts/alerts.h"
33 #include "alerts/getloglocation.h"
34 #include "os_execd/execd.h"
36 #include "os_regex/os_regex.h"
37 #include "os_net/os_net.h"
41 #include "active-response.h"
46 #include "eventinfo.h"
47 #include "analysisd.h"
56 #include "zeromq_output.h"
64 /* active response queue */
68 /** Internal Functions **/
69 void OS_ReadMSG(int m_queue);
70 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
73 /** External functions prototypes (only called here) **/
76 int GlobalConf(char * cfgfile);
80 void Rules_OP_CreateRules();
81 void Lists_OP_CreateLists();
82 int Rules_OP_ReadRules(char * cfgfile);
83 int _setlevels(RuleNode *node, int nnode);
84 int AddHash_Rule(RuleNode *node);
88 int OS_CleanMSG(char *msg, Eventinfo *lf);
93 int FTS(Eventinfo *lf);
94 int AddtoIGnore(Eventinfo *lf);
95 int IGnore(Eventinfo *lf);
96 int doDiff(RuleInfo *currently_rule, Eventinfo *lf);
100 void DecodeEvent(Eventinfo *lf);
101 int DecodeSyscheck(Eventinfo *lf);
102 int DecodeRootcheck(Eventinfo *lf);
103 int DecodeHostinfo(Eventinfo *lf);
107 int ReadDecodeXML(char *file);
111 /* For syscheckd (integrity checking) */
113 void RootcheckInit();
119 int Check_Hour(Eventinfo *lf);
130 /** int main(int argc, char **argv)
133 int main(int argc, char **argv)
135 int main_analysisd(int argc, char **argv)
138 int c = 0, m_queue = 0, test_config = 0,run_foreground = 0;
140 char *dir = DEFAULTDIR;
142 char *group = GROUPGLOBAL;
145 char *cfg = DEFAULTCPATH;
147 /* Setting the name */
153 memset(prev_month, '\0', 4);
159 while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
176 ErrorExit("%s: -u needs an argument",ARGV0);
181 ErrorExit("%s: -g needs an argument",ARGV0);
186 ErrorExit("%s: -D needs an argument",ARGV0);
191 ErrorExit("%s: -c needs an argument",ARGV0);
204 /* Check current debug_level
205 * Command line setting takes precedence
207 if (debug_level == 0)
209 /* Getting debug level */
210 debug_level = getDefine_Int("analysisd", "debug", 0, 2);
211 while(debug_level != 0)
219 /* Starting daemon */
220 debug1(STARTED_MSG,ARGV0);
221 DEBUG_MSG("%s: DEBUG: Starting on debug mode - %d ", ARGV0, (int)time(0));
224 /*Check if the user/group given are valid */
225 uid = Privsep_GetUser(user);
226 gid = Privsep_GetGroup(group);
227 if((uid < 0)||(gid < 0))
228 ErrorExit(USER_ERROR,ARGV0,user,group);
232 debug1(FOUND_USER, ARGV0);
235 /* Initializing Active response */
237 if(AR_ReadConfig(test_config, cfg) < 0)
239 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
241 debug1(ASINIT, ARGV0);
244 /* Reading configuration file */
245 if(GlobalConf(cfg) < 0)
247 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
250 debug1(READ_CONFIG, ARGV0);
253 /* Fixing Config.ar */
259 /* Getting servers hostname */
260 memset(__shost, '\0', 512);
261 if(gethostname(__shost, 512 -1) != 0)
263 strncpy(__shost, OSSEC_SERVER, 512 -1);
269 /* Remove domain part if available */
270 _ltmp = strchr(__shost, '.');
275 /* going on Daemon mode */
276 if(!test_config && !run_foreground)
283 /* Starting prelude */
287 prelude_start(Config.prelude_profile, argc, argv);
291 /* Starting zeromq */
293 if(Config.zeromq_output)
295 zeromq_output_start(Config.zeromq_output_uri, argc, argv);
299 /* Opening the Picviz socket */
302 OS_PicvizOpen(Config.picviz_socket);
303 chown(Config.picviz_socket, uid, gid);
306 /* Setting the group */
307 if(Privsep_SetGroup(gid) < 0)
308 ErrorExit(SETGID_ERROR,ARGV0,group);
311 if(Privsep_Chroot(dir) < 0)
312 ErrorExit(CHROOT_ERROR,ARGV0,dir);
320 * Anonymous Section: Load rules, decoders, and lists
322 * As lists require two pass loading of rules that make use of list lookups
323 * are created with blank database structs, and need to be filled in after
324 * completion of all rules and lists.
328 /* Initializing the decoders list */
329 OS_CreateOSDecoderList();
332 { /* Legacy loading */
333 /* Reading decoders */
334 if(!ReadDecodeXML(XML_DECODER))
336 ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
339 /* Reading local ones. */
340 c = ReadDecodeXML(XML_LDECODER);
344 ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER);
349 verbose("%s: INFO: Reading local decoder file.", ARGV0);
353 { /* New loaded based on file speified in ossec.conf */
354 char **decodersfiles;
355 decodersfiles = Config.decoders;
356 while( decodersfiles && *decodersfiles)
359 verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
360 if(!ReadDecodeXML(*decodersfiles))
361 ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
363 free(*decodersfiles);
372 /* Initializing the lists of list struct */
373 Lists_OP_CreateLists();
374 /* Load each list into list struct */
377 listfiles = Config.lists;
378 while(listfiles && *listfiles)
381 verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
382 if(Lists_OP_LoadList(*listfiles) < 0)
383 ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
392 /* Creating the rules list */
393 Rules_OP_CreateRules();
395 /* Reading the rules */
398 rulesfiles = Config.includes;
399 while(rulesfiles && *rulesfiles)
402 verbose("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
403 if(Rules_OP_ReadRules(*rulesfiles) < 0)
404 ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
410 free(Config.includes);
411 Config.includes = NULL;
414 /* Find all rules with that require list lookups and attache the
415 * the correct list struct to the rule. This keeps rules from having to
416 * search thought the list of lists for the correct file during rule evaluation.
423 /* Fixing the levels/accuracy */
426 RuleNode *tmp_node = OS_GetFirstRule();
428 total_rules = _setlevels(tmp_node, 0);
430 verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
435 /* Creating a rules hash (for reading alerts from other servers). */
437 RuleNode *tmp_node = OS_GetFirstRule();
438 Config.g_rules_hash = OSHash_Create();
439 if(!Config.g_rules_hash)
441 ErrorExit(MEM_ERROR, ARGV0);
443 AddHash_Rule(tmp_node);
448 /* Ignored files on syscheck */
451 files = Config.syscheck_ignore;
452 while(files && *files)
455 verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
461 /* Checking if log_fw is enabled. */
462 Config.logfw = getDefine_Int("analysisd",
467 /* Success on the configuration test */
472 /* Verbose message */
473 debug1(PRIVSEP_MSG, ARGV0, dir, user);
476 /* Signal manipulation */
480 /* Setting the user */
481 if(Privsep_SetUser(uid) < 0)
482 ErrorExit(SETUID_ERROR,ARGV0,user);
485 /* Creating the PID file */
486 if(CreatePID(ARGV0, getpid()) < 0)
487 ErrorExit(PID_ERROR,ARGV0);
490 /* Setting the queue */
491 if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0)
492 ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
496 if(Config.white_list == NULL)
499 verbose("%s: INFO: No IP in the white list for active reponse.", ARGV0);
507 wl = Config.white_list;
510 verbose("%s: INFO: White listing IP: '%s'",ARGV0, (*wl)->ip);
513 verbose("%s: INFO: %d IPs in the white list for active response.",
518 /* Hostname White list */
519 if(Config.hostname_white_list == NULL)
522 verbose("%s: INFO: No Hostname in the white list for active reponse.",
532 wl = Config.hostname_white_list;
535 char **tmp_pts = (*wl)->patterns;
538 verbose("%s: INFO: White listing Hostname: '%s'",ARGV0,*tmp_pts);
544 verbose("%s: INFO: %d Hostname(s) in the white list for active response.",
550 /* Start up message */
551 verbose(STARTUP_MSG, ARGV0, (int)getpid());
554 /* Going to main loop */
569 * Main function. Receives the messages(events)
570 * and analyze them all.
573 void OS_ReadMSG(int m_queue)
575 void OS_ReadMSG_analysisd(int m_queue)
579 char msg[OS_MAXSTR +1];
582 RuleInfo *stats_rule;
585 /* Null to global currently pointers */
586 currently_rule = NULL;
588 /* Initiating the logs */
592 /* Initiating the integrity database */
596 /* Initializing Rootcheck */
600 /* Initializing host info */
604 /* Creating the event list */
605 OS_CreateEventList(Config.memorysize);
608 /* Initiating the FTS list */
611 ErrorExit(FTS_LIST_ERROR, ARGV0);
615 /* Starting the active response queues */
618 /* Waiting the ARQ to settle .. */
623 if(Config.ar & REMOTE_AR)
625 if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
627 merror(ARQ_ERROR, ARGV0);
629 /* If LOCAL_AR is set, keep it there */
630 if(Config.ar & LOCAL_AR)
642 verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
647 /* Only for LOCAL_ONLY installs */
648 if(Config.ar & REMOTE_AR)
650 if(Config.ar & LOCAL_AR)
662 if(Config.ar & LOCAL_AR)
664 if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0)
666 merror(ARQ_ERROR, ARGV0);
668 /* If REMOTE_AR is set, keep it there */
669 if(Config.ar & REMOTE_AR)
672 Config.ar|=REMOTE_AR;
681 verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
685 debug1("%s: DEBUG: Active response Init completed.", ARGV0);
688 /* Getting currently time before starting */
692 /* Starting the hourly/weekly stats */
697 /* Initializing stats rules */
698 stats_rule = zerorulemember(
705 ErrorExit(MEM_ERROR, ARGV0);
707 stats_rule->group = "stats,";
708 stats_rule->comment = "Excessive number of events (above normal).";
712 /* Doing some cleanup */
713 memset(msg, '\0', OS_MAXSTR +1);
716 /* Initializing the logs */
718 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
720 ErrorExit(MEM_ERROR, ARGV0);
721 lf->year = prev_year;
722 strncpy(lf->mon, prev_month, 3);
725 if(OS_GetLogLocation(lf) < 0)
727 ErrorExit("%s: Error allocating log files", ARGV0);
734 debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0);
736 if(Config.custom_alert_output)
737 debug1("%s: INFO: Custom output found.!",ARGV0);
742 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
744 /* This shouldn't happen .. */
747 ErrorExit(MEM_ERROR,ARGV0);
750 DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0));
753 /* Receive message from queue */
754 if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg)))
756 RuleNode *rulenode_pt;
758 /* Getting the time we received the event */
762 /* Default values for the log info */
766 /* Checking for a valid message. */
769 merror(IMSG_ERROR, ARGV0, msg);
775 /* Message before extracting header */
776 DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg);
779 /* Clean the msg appropriately */
780 if(OS_CleanMSG(msg, lf) < 0)
782 merror(IMSG_ERROR,ARGV0, msg);
789 DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log);
792 /* Currently rule must be null in here */
793 currently_rule = NULL;
796 /** Checking the date/hour changes **/
798 /* Update the hour */
799 if(thishour != __crt_hour)
801 /* Search all the rules and print the number
802 * of alerts that each one fired.
805 thishour = __crt_hour;
807 /* Check if the date has changed */
812 /* Update the hourly stats (done daily) */
816 if(OS_GetLogLocation(lf) < 0)
818 ErrorExit("%s: Error allocating log files", ARGV0);
822 strncpy(prev_month, lf->mon, 3);
823 prev_year = lf->year;
828 /* Incrementing number of events received */
832 /*** Running decoders ***/
834 /* Integrity check from syscheck */
835 if(msg[0] == SYSCHECK_MQ)
839 if(!DecodeSyscheck(lf))
841 /* We don't process syscheck events further */
845 /* Getting log size */
846 lf->size = strlen(lf->log);
849 /* Rootcheck decoding */
850 else if(msg[0] == ROOTCHECK_MQ)
852 if(!DecodeRootcheck(lf))
854 /* We don't process rootcheck events further */
857 lf->size = strlen(lf->log);
860 /* Host information special decoder */
861 else if(msg[0] == HOSTINFO_MQ)
863 if(!DecodeHostinfo(lf))
865 /* We don't process hostinfo events further */
868 lf->size = strlen(lf->log);
871 /* Run the general Decoders */
874 /* Getting log size */
875 lf->size = strlen(lf->log);
882 if(lf->decoder_info->type == FIREWALL)
884 /* If we could not get any information from
885 * the log, just ignore it
898 /* We only check if the last message is
899 * duplicated on syslog.
901 else if(lf->decoder_info->type == SYSLOG)
903 /* Checking if the message is duplicated */
904 if(LastMsg_Stats(lf->full_log) == 1)
907 LastMsg_Change(lf->full_log);
914 if(Check_Hour(lf) == 1)
916 void *saved_rule = lf->generated_rule;
919 /* Saving previous log */
920 saved_log = lf->full_log;
922 lf->generated_rule = stats_rule;
923 lf->full_log = __stats_comment;
926 /* alert for statistical analysis */
927 if(stats_rule->alert_opts & DO_LOGALERT)
929 __crt_ftell = ftell(_aflog);
930 if(Config.custom_alert_output)
932 OS_CustomLog(lf,Config.custom_alert_output_format);
942 /* Set lf to the old values */
943 lf->generated_rule = saved_rule;
944 lf->full_log = saved_log;
949 /* Checking the rules */
950 DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
951 ARGV0, lf->decoder_info->type);
954 /* Looping all the rules */
955 rulenode_pt = OS_GetFirstRule();
958 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
965 if(lf->decoder_info->type == OSSEC_ALERT)
967 if(!lf->generated_rule)
972 /* We go ahead in here and process the alert. */
973 currently_rule = lf->generated_rule;
976 /* The categories must match */
977 else if(rulenode_pt->ruleinfo->category !=
978 lf->decoder_info->type)
983 /* Checking each rule. */
984 else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
992 if(currently_rule->level == 0)
998 /* Checking ignore time */
999 if(currently_rule->ignore_time)
1001 if(currently_rule->time_ignored == 0)
1003 currently_rule->time_ignored = lf->time;
1005 /* If the currently time - the time the rule was ignored
1006 * is less than the time it should be ignored,
1007 * leave (do not alert again).
1009 else if((lf->time - currently_rule->time_ignored)
1010 < currently_rule->ignore_time)
1016 currently_rule->time_ignored = lf->time;
1021 /* Pointer to the rule that generated it */
1022 lf->generated_rule = currently_rule;
1025 /* Checking if we should ignore it */
1026 if(currently_rule->ckignore && IGnore(lf))
1029 lf->generated_rule = NULL;
1034 /* Checking if we need to add to ignore list */
1035 if(currently_rule->ignore)
1041 /* Log the alert if configured to ... */
1042 if(currently_rule->alert_opts & DO_LOGALERT)
1044 __crt_ftell = ftell(_aflog);
1046 if(Config.custom_alert_output)
1048 OS_CustomLog(lf,Config.custom_alert_output_format);
1057 /* Log to prelude */
1061 if(Config.prelude_log_level <= currently_rule->level)
1069 #ifdef ZEROMQ_OUTPUT
1070 if(Config.zeromq_output)
1072 zeromq_output_event(lf);
1084 /* Execute an active response */
1085 if(currently_rule->ar)
1088 active_response **rule_ar;
1090 rule_ar = currently_rule->ar;
1095 if((*rule_ar)->ar_cmd->expect & USERNAME)
1098 !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$"))
1101 merror(CRAFTED_USER, ARGV0, lf->dstuser);
1105 if((*rule_ar)->ar_cmd->expect & SRCIP)
1108 !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$"))
1111 merror(CRAFTED_IP, ARGV0, lf->srcip);
1115 if((*rule_ar)->ar_cmd->expect & FILENAME)
1125 OS_Exec(&execdq, &arq, lf, *rule_ar);
1132 /* Copy the structure to the state memory of if_matched_sid */
1133 if(currently_rule->sid_prev_matched)
1135 if(!OSList_AddData(currently_rule->sid_prev_matched, lf))
1137 merror("%s: Unable to add data to sig list.", ARGV0);
1141 lf->sid_node_to_delete =
1142 currently_rule->sid_prev_matched->last_node;
1146 else if(currently_rule->group_prev_matched)
1150 while(i < currently_rule->group_prev_matched_sz)
1153 currently_rule->group_prev_matched[i],
1156 merror("%s: Unable to add data to grp list.",ARGV0);
1166 }while((rulenode_pt = rulenode_pt->next) != NULL);
1169 /* If configured to log all, do it */
1174 /* Cleaning the memory */
1178 /* Only clear the memory if the eventinfo was not
1179 * added to the stateful memory
1180 * -- message is free inside clean event --
1182 if(lf->generated_rule == NULL)
1195 /* CheckIfRuleMatch v0.1
1196 * Will check if the currently_rule matches the event information
1198 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
1203 * word match (fast regex),
1218 RuleInfo *currently_rule = curr_node->ruleinfo;
1224 merror("%s: Inconsistent state. currently rule NULL", ARGV0);
1230 if(full_output && !alert_only)
1231 print_out(" Trying rule: %d - %s", currently_rule->sigid,
1232 currently_rule->comment);
1236 /* Checking if any decoder pre-matched here */
1237 if(currently_rule->decoded_as &&
1238 currently_rule->decoded_as != lf->decoder_info->id)
1244 /* Checking program name */
1245 if(currently_rule->program_name)
1247 if(!lf->program_name)
1250 if(!OSMatch_Execute(lf->program_name,
1252 currently_rule->program_name))
1257 /* Checking for the id */
1258 if(currently_rule->id)
1265 if(!OSMatch_Execute(lf->id,
1267 currently_rule->id))
1275 /* Checking if any word to match exists */
1276 if(currently_rule->match)
1278 if(!OSMatch_Execute(lf->log, lf->size, currently_rule->match))
1284 /* Checking if exist any regex for this rule */
1285 if(currently_rule->regex)
1287 if(!OSRegex_Execute(lf->log, currently_rule->regex))
1292 /* Checking for actions */
1293 if(currently_rule->action)
1298 if(strcmp(currently_rule->action,lf->action) != 0)
1303 /* Checking for the url */
1304 if(currently_rule->url)
1311 if(!OSMatch_Execute(lf->url, strlen(lf->url), currently_rule->url))
1322 /* Getting tcp/ip packet information */
1323 if(currently_rule->alert_opts & DO_PACKETINFO)
1325 /* Checking for the srcip */
1326 if(currently_rule->srcip)
1333 if(!OS_IPFoundList(lf->srcip, currently_rule->srcip))
1342 /* Checking for the dstip */
1343 if(currently_rule->dstip)
1350 if(!OS_IPFoundList(lf->dstip, currently_rule->dstip))
1359 if(currently_rule->srcport)
1366 if(!OSMatch_Execute(lf->srcport,
1367 strlen(lf->srcport),
1368 currently_rule->srcport))
1376 if(currently_rule->dstport)
1383 if(!OSMatch_Execute(lf->dstport,
1384 strlen(lf->dstport),
1385 currently_rule->dstport))
1393 } /* END PACKET_INFO */
1396 /* Extra information from event */
1397 if(currently_rule->alert_opts & DO_EXTRAINFO)
1399 /* Checking compiled rule. */
1400 if(currently_rule->compiled_rule)
1402 if(!currently_rule->compiled_rule(lf))
1409 /* Checking if exist any user to match */
1410 if(currently_rule->user)
1414 if(!OSMatch_Execute(lf->dstuser,
1415 strlen(lf->dstuser),
1416 currently_rule->user))
1419 else if(lf->srcuser)
1421 if(!OSMatch_Execute(lf->srcuser,
1422 strlen(lf->srcuser),
1423 currently_rule->user))
1437 /* Checking if any rule related to the size exist */
1438 if(currently_rule->maxsize)
1440 if(lf->size < currently_rule->maxsize)
1445 /* Checking if we are in the right time */
1446 if(currently_rule->day_time)
1448 if(!OS_IsonTime(lf->hour, currently_rule->day_time))
1455 /* Checking week day */
1456 if(currently_rule->week_day)
1458 if(!OS_IsonDay(__crt_wday, currently_rule->week_day))
1465 /* Getting extra data */
1466 if(currently_rule->extra_data)
1471 if(!OSMatch_Execute(lf->data,
1473 currently_rule->extra_data))
1478 /* Checking hostname */
1479 if(currently_rule->hostname)
1484 if(!OSMatch_Execute(lf->hostname,
1485 strlen(lf->hostname),
1486 currently_rule->hostname))
1491 /* Checking for status */
1492 if(currently_rule->status)
1497 if(!OSMatch_Execute(lf->status,
1499 currently_rule->status))
1504 /* Do diff check. */
1505 if(currently_rule->context_opts & SAME_DODIFF)
1507 if(!doDiff(currently_rule, lf))
1514 /* Checking for the FTS flag */
1515 if(currently_rule->alert_opts & DO_FTS)
1518 if(lf->decoder_info->fts)
1520 if(lf->decoder_info->fts & FTS_DONE)
1522 /* We already did the fts in here. */
1536 if(currently_rule->lists != NULL)
1538 ListRule *list_holder=currently_rule->lists;
1541 switch(list_holder->field)
1546 if(!OS_DBSearch(list_holder,lf->srcip))
1552 if(!OS_DBSearch(list_holder,lf->srcport))
1558 if(!OS_DBSearch(list_holder,lf->dstip))
1564 if(!OS_DBSearch(list_holder,lf->dstport))
1570 if(!OS_DBSearch(list_holder,lf->srcuser))
1573 else if(lf->dstuser)
1575 if(!OS_DBSearch(list_holder,lf->dstuser))
1586 if(!OS_DBSearch(list_holder,lf->url))
1592 if(!OS_DBSearch(list_holder,lf->id))
1598 if(!OS_DBSearch(list_holder,lf->hostname))
1601 case RULE_PROGRAM_NAME:
1602 if(!lf->program_name)
1604 if(!OS_DBSearch(list_holder,lf->program_name))
1610 if(!OS_DBSearch(list_holder,lf->status))
1616 if(!OS_DBSearch(list_holder,lf->action))
1623 list_holder = list_holder->next;
1628 /* If it is a context rule, search for it */
1629 if(currently_rule->context == 1)
1631 if(!currently_rule->event_search(lf, currently_rule))
1636 if(full_output && !alert_only)
1637 print_out(" *Rule %d matched.", currently_rule->sigid);
1641 /* Search for dependent rules */
1642 if(curr_node->child)
1644 RuleNode *child_node = curr_node->child;
1645 RuleInfo *child_rule = NULL;
1648 if(full_output && !alert_only)
1649 print_out(" *Trying child rules.");
1654 child_rule = OS_CheckIfRuleMatch(lf, child_node);
1655 if(child_rule != NULL)
1660 child_node = child_node->next;
1665 /* If we are set to no alert, keep going */
1666 if(currently_rule->alert_opts & NO_ALERT)
1673 currently_rule->firedtimes++;
1675 return(currently_rule); /* Matched */
1679 /** void LoopRule(RuleNode *curr_node);
1680 * Update each rule and print it to the logs.
1682 void LoopRule(RuleNode *curr_node, FILE *flog)
1684 if(curr_node->ruleinfo->firedtimes)
1686 fprintf(flog, "%d-%d-%d-%d\n",
1688 curr_node->ruleinfo->sigid,
1689 curr_node->ruleinfo->level,
1690 curr_node->ruleinfo->firedtimes);
1691 curr_node->ruleinfo->firedtimes = 0;
1694 if(curr_node->child)
1696 RuleNode *child_node = curr_node->child;
1700 LoopRule(child_node, flog);
1701 child_node = child_node->next;
1708 /** void DumpLogstats();
1709 * Dump the hourly stats about each rule.
1713 RuleNode *rulenode_pt;
1714 char logfile[OS_FLSIZE +1];
1717 /* Opening log file */
1718 snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
1719 if(IsDir(logfile) == -1)
1720 if(mkdir(logfile,0770) == -1)
1722 merror(MKDIR_ERROR, ARGV0, logfile);
1726 snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year,prev_month);
1728 if(IsDir(logfile) == -1)
1729 if(mkdir(logfile,0770) == -1)
1731 merror(MKDIR_ERROR,ARGV0,logfile);
1736 /* Creating the logfile name */
1737 snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
1744 flog = fopen(logfile, "a");
1747 merror(FOPEN_ERROR, ARGV0, logfile);
1751 rulenode_pt = OS_GetFirstRule();
1755 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
1759 /* Looping on all the rules and printing the stats from them */
1762 LoopRule(rulenode_pt, flog);
1763 }while((rulenode_pt = rulenode_pt->next) != NULL);
1766 /* Print total for the hour */
1767 fprintf(flog, "%d--%d--%d--%d--%d\n\n",
1769 hourly_alerts, hourly_events, hourly_syscheck,hourly_firewall);
1772 hourly_syscheck = 0;
1773 hourly_firewall = 0;