-/* @(#) $Id: analysisd.c,v 1.149 2009/11/20 16:11:46 dcid Exp $ */
-
-/* Copyright (C) 2009 Trend Micro Inc.
+/* Copyright (C) 2010-2012 Trend Micro Inc.
* All rights reserved.
*
* This program is a free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
- * License (version 3) as published by the FSF - Free Software
+ * License (version 2) as published by the FSF - Free Software
* Foundation.
- *
- * License details at the LICENSE file included with OSSEC or
- * online at: http://www.ossec.net/en/licensing.html
- */
-
-
-/* Part of the OSSEC
- * Available at http://www.ossec.net
*/
-
-/* ossec-analysisd.
- * Responsible for correlation and log decoding.
+/* ossec-analysisd
+ * Responsible for correlation and log decoding
*/
#ifndef ARGV0
- #define ARGV0 "ossec-analysisd"
+#define ARGV0 "ossec-analysisd"
#endif
#include "shared.h"
-
#include "alerts/alerts.h"
#include "alerts/getloglocation.h"
#include "os_execd/execd.h"
-
#include "os_regex/os_regex.h"
#include "os_net/os_net.h"
-
-
-/** Local headers **/
#include "active-response.h"
#include "config.h"
#include "rules.h"
#include "stats.h"
#include "eventinfo.h"
+#include "accumulator.h"
#include "analysisd.h"
+#include "fts.h"
+#include "cleanevent.h"
+#include "dodiff.h"
+#include "output/jsonout.h"
-#include "picviz.h"
-
-#ifdef PRELUDE
-#include "prelude.h"
+#ifdef PRELUDE_OUTPUT_ENABLED
+#include "output/prelude.h"
#endif
+#ifdef ZEROMQ_OUTPUT_ENABLED
+#include "output/zeromq.h"
+#endif
-/** Global data **/
-
-/* execd queue */
-int execdq = 0;
-
-/* active response queue */
-int arq = 0;
-
+#ifdef SQLITE_ENABLED
+#include "syscheck-sqlite.h"
+#endif
-/** Internal Functions **/
+/** Prototypes **/
void OS_ReadMSG(int m_queue);
RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
-
-
-/** External functions prototypes (only called here) **/
-
-/* For config */
-int GlobalConf(char * cfgfile);
-
-
-/* For rules */
-void Rules_OP_CreateRules();
-int Rules_OP_ReadRules(char * cfgfile);
-int _setlevels(RuleNode *node, int nnode);
-int AddHash_Rule(RuleNode *node);
-
-
-/* For cleanmsg */
-int OS_CleanMSG(char *msg, Eventinfo *lf);
-
-
-/* for FTS */
-int FTS_Init();
-int FTS(Eventinfo *lf);
-int AddtoIGnore(Eventinfo *lf);
-int IGnore(Eventinfo *lf);
-
+static void LoopRule(RuleNode *curr_node, FILE *flog);
/* For decoders */
void DecodeEvent(Eventinfo *lf);
int DecodeSyscheck(Eventinfo *lf);
int DecodeRootcheck(Eventinfo *lf);
int DecodeHostinfo(Eventinfo *lf);
-
-
-/* For Decoders */
-int ReadDecodeXML(char *file);
-int SetDecodeXML();
+/* For stats */
+static void DumpLogstats(void);
+
+/** Global definitions **/
+int today;
+int thishour;
+int prev_year;
+char prev_month[4];
+int __crt_hour;
+int __crt_wday;
+time_t c_time;
+char __shost[512];
+OSDecoderInfo *NULL_Decoder;
-/* For syscheckd (integrity checking) */
-void SyscheckInit();
-void RootcheckInit();
-void HostinfoInit();
+/* execd queue */
+static int execdq = 0;
+/* Active response queue */
+static int arq = 0;
-/* For stats */
-int Start_Hour();
-int Check_Hour(Eventinfo *lf);
-void Update_Hour();
-void DumpLogstats();
+static int hourly_alerts;
+static int hourly_events;
+static int hourly_syscheck;
+static int hourly_firewall;
-/* Hourly alerts */
-int hourly_alerts;
-int hourly_events;
-int hourly_syscheck;
-int hourly_firewall;
+/* Print help statement */
+__attribute__((noreturn))
+static void help_analysisd(void)
+{
+ print_header();
+ print_out(" %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
+ print_out(" -V Version and license message");
+ print_out(" -h This help message");
+ print_out(" -d Execute in debug mode. This parameter");
+ print_out(" can be specified multiple times");
+ print_out(" to increase the debug level.");
+ print_out(" -t Test configuration");
+ print_out(" -f Run in foreground");
+ print_out(" -u <user> User to run as (default: %s)", USER);
+ print_out(" -g <group> Group to run as (default: %s)", GROUPGLOBAL);
+ print_out(" -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
+ print_out(" -D <dir> Directory to chroot into (default: %s)", DEFAULTDIR);
+ print_out(" ");
+ exit(1);
+}
-/** int main(int argc, char **argv)
- */
-#ifndef TESTRULE
+#ifndef TESTRULE
int main(int argc, char **argv)
#else
+__attribute__((noreturn))
int main_analysisd(int argc, char **argv)
#endif
{
- int c = 0, m_queue = 0, test_config = 0,run_foreground = 0;
- char *dir = DEFAULTDIR;
- char *user = USER;
- char *group = GROUPGLOBAL;
- int uid = 0,gid = 0;
+ int c = 0, m_queue = 0, test_config = 0, run_foreground = 0;
+ int debug_level = 0;
+ const char *dir = DEFAULTDIR;
+ const char *user = USER;
+ const char *group = GROUPGLOBAL;
+ uid_t uid;
+ gid_t gid;
- char *cfg = DEFAULTCPATH;
+ const char *cfg = DEFAULTCPATH;
- /* Setting the name */
+ /* Set the name */
OS_SetName(ARGV0);
thishour = 0;
hourly_syscheck = 0;
hourly_firewall = 0;
- while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
- switch(c){
- case 'V':
- print_version();
- break;
+#ifdef LIBGEOIP_ENABLED
+ geoipdb = NULL;
+#endif
+
+
+ while ((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1) {
+ switch (c) {
+ case 'V':
+ print_version();
+ break;
case 'h':
- help(ARGV0);
+ 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);
+ if (!optarg) {
+ ErrorExit("%s: -u needs an argument", ARGV0);
+ }
user = optarg;
break;
case 'g':
- if(!optarg)
- ErrorExit("%s: -g needs an argument",ARGV0);
+ if (!optarg) {
+ ErrorExit("%s: -g needs an argument", ARGV0);
+ }
group = optarg;
break;
case 'D':
- if(!optarg)
- ErrorExit("%s: -D needs an argument",ARGV0);
+ if (!optarg) {
+ ErrorExit("%s: -D needs an argument", ARGV0);
+ }
dir = optarg;
+ break;
case 'c':
- if(!optarg)
- ErrorExit("%s: -c needs an argument",ARGV0);
+ if (!optarg) {
+ ErrorExit("%s: -c needs an argument", ARGV0);
+ }
cfg = optarg;
break;
case 't':
- test_config = 1;
+ test_config = 1;
break;
default:
- help(ARGV0);
+ help_analysisd();
break;
}
}
+ /* Check current debug_level
+ * Command line setting takes precedence
+ */
+ if (debug_level == 0) {
+ /* Get debug level */
+ debug_level = getDefine_Int("analysisd", "debug", 0, 2);
+ while (debug_level != 0) {
+ nowDebug();
+ debug_level--;
+ }
+ }
- /* Starting daemon */
- debug1(STARTED_MSG,ARGV0);
+ /* Start 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 */
+ /* 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);
-
+ if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
+ ErrorExit(USER_ERROR, ARGV0, user, group);
+ }
/* Found user */
debug1(FOUND_USER, ARGV0);
-
- /* Initializing Active response */
+ /* Initialize Active response */
AR_Init();
- if(AR_ReadConfig(test_config, cfg) < 0)
- {
- ErrorExit(CONFIG_ERROR,ARGV0, cfg);
+ 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);
+
+ /* Read configuration file */
+ if (GlobalConf(cfg) < 0) {
+ ErrorExit(CONFIG_ERROR, ARGV0, cfg);
}
debug1(READ_CONFIG, ARGV0);
-
- /* Fixing Config.ar */
+
+#ifdef LIBGEOIP_ENABLED
+ Config.geoip_jsonout = getDefine_Int("analysisd", "geoip_jsonout", 0, 1);
+
+ /* Opening GeoIP DB */
+ if(Config.geoipdb_file) {
+ geoipdb = GeoIP_open(Config.geoipdb_file, GEOIP_INDEX_CACHE);
+ if (geoipdb == NULL)
+ {
+ merror("%s: ERROR: Unable to open GeoIP database from: %s (disabling GeoIP).", ARGV0, Config.geoipdb_file);
+ }
+ }
+#endif
+
+
+
+ /* Fix Config.ar */
Config.ar = ar_flag;
- if(Config.ar == -1)
+ 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
- {
+
+ /* Get server's 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)
+ if (_ltmp) {
*_ltmp = '\0';
+ }
}
-
- /* going on Daemon mode */
- if(!test_config || !run_foreground)
- {
+
+ /* Continuing in Daemon mode */
+ if (!test_config && !run_foreground) {
nowDaemon();
goDaemon();
}
-
- /* Starting prelude */
- #ifdef PRELUDE
- if(Config.prelude)
- {
+#ifdef PRELUDE_OUTPUT_ENABLED
+ /* Start prelude */
+ if (Config.prelude) {
prelude_start(Config.prelude_profile, argc, argv);
}
- #endif
-
+#endif
- /* Opening the Picviz socket */
- if(Config.picviz)
- {
- OS_PicvizOpen(Config.picviz_socket);
- chown(Config.picviz_socket, uid, gid);
+#ifdef ZEROMQ_OUTPUT_ENABLED
+ /* Start zeromq */
+ if (Config.zeromq_output) {
+#if CZMQ_VERSION_MAJOR == 2
+ zeromq_output_start(Config.zeromq_output_uri);
+#elif CZMQ_VERSION_MAJOR >= 3
+ zeromq_output_start(Config.zeromq_output_uri, Config.zeromq_output_client_cert, Config.zeromq_output_server_cert);
+#endif
}
-
-
- /* Setting the group */
- if(Privsep_SetGroup(gid) < 0)
- ErrorExit(SETGID_ERROR,ARGV0,group);
-
- /* Chrooting */
- if(Privsep_Chroot(dir) < 0)
- ErrorExit(CHROOT_ERROR,ARGV0,dir);
+#endif
+ /* Set the group */
+ if (Privsep_SetGroup(gid) < 0) {
+ ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
+ }
+ /* Chroot */
+ if (Privsep_Chroot(dir) < 0) {
+ ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
+ }
nowChroot();
-
-
- /* Initializing the list */
- OS_CreateOSDecoderList();
-
+ Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", 8, MAX_DECODER_ORDER_SIZE);
- /* 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
+ /*
+ * Anonymous Section: Load rules, decoders, and lists
+ *
+ * As lists require two-pass loading of rules that makes use of lists, lookups
+ * are created with blank database structs, and need to be filled in after
+ * completion of all rules and lists.
+ */
{
- if(!test_config)
- verbose("%s: INFO: Reading local decoder file.", ARGV0);
- }
- SetDecodeXML();
+ {
+ /* Initialize the decoders list */
+ OS_CreateOSDecoderList();
+
+ if (!Config.decoders) {
+ /* Legacy loading */
+ /* Read decoders */
+ if (!ReadDecodeXML(XML_DECODER)) {
+ ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
+ }
-
- /* Creating the rules list */
- Rules_OP_CreateRules();
+ /* Read 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);
+ }
-
- /* Reading the rules */
- {
- char **rulesfiles;
- rulesfiles = Config.includes;
- while(rulesfiles && *rulesfiles)
+ free(*decodersfiles);
+ decodersfiles++;
+ }
+ }
+
+ /* Load decoders */
+ SetDecodeXML();
+ }
{
- 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++;
+ /* Load Lists */
+ /* Initialize 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;
+ }
}
- free(Config.includes);
- Config.includes = NULL;
+ {
+ /* Load Rules */
+ /* Create the rules list */
+ Rules_OP_CreateRules();
+
+ /* Read 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 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 */
+
+ /* Fix 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);
+ if (!test_config) {
+ verbose("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
+ }
}
-
-
- /* Creating a rules hash (for reading alerts from other servers). */
+ /* Create 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);
+ if (!Config.g_rules_hash) {
+ ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
}
AddHash_Rule(tmp_node);
}
-
-
/* Ignored files on syscheck */
{
char **files;
files = Config.syscheck_ignore;
- while(files && *files)
- {
- if(!test_config)
+ while (files && *files) {
+ if (!test_config) {
verbose("%s: INFO: Ignoring file: '%s'", ARGV0, *files);
- files++;
+ }
+ files++;
}
}
-
- /* Checking if log_fw is enabled. */
- Config.logfw = getDefine_Int("analysisd",
+ /* Check if log_fw is enabled */
+ Config.logfw = (u_int8_t) getDefine_Int("analysisd",
"log_fw",
0, 1);
-
/* Success on the configuration test */
- if(test_config)
+ if (test_config) {
exit(0);
+ }
-
/* Verbose message */
- debug1(PRIVSEP_MSG, ARGV0, dir, user);
-
+ debug1(CHROOT_MSG, ARGV0, dir);
+ debug1(PRIVSEP_MSG, ARGV0, user);
- /* Signal manipulation */
+ /* Signal manipulation */
StartSIG(ARGV0);
+ /* Set the user */
+ if (Privsep_SetUser(uid) < 0) {
+ ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
+ }
- /* 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);
-
+ /* Create the PID file */
+ if (CreatePID(ARGV0, getpid()) < 0) {
+ ErrorExit(PID_ERROR, ARGV0);
+ }
- /* Setting the queue */
- if((m_queue = StartMQ(DEFAULTQUEUE,READ)) < 0)
+ /* Set 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)
- {
+
+ /* allowlist */
+ if (Config.allow_list == NULL) {
+ if (Config.ar) {
+ verbose("%s: INFO: No IP in the allow list for active response.", 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++;
+ wl = Config.allow_list;
+ while (*wl) {
+ verbose("%s: INFO: Allow listing IP: '%s'", ARGV0, (*wl)->ip);
+ wl++;
+ wlc++;
}
- verbose("%s: INFO: %d IPs in the white list for active response.",
+ verbose("%s: INFO: %d IPs in the allow 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)
- {
+ /* Hostname allowlist */
+ if (Config.hostname_allow_list == NULL) {
+ if (Config.ar)
+ verbose("%s: INFO: No Hostname in the allow list for active response.",
+ 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++;
- }
+ char **wl;
+
+ wl = Config.hostname_allow_list;
+ while (*wl) {
+ verbose("%s: INFO: Allow listing Hostname: '%s'", ARGV0, *wl);
+ wlc++;
wl++;
}
- verbose("%s: INFO: %d Hostname(s) in the white list for active response.",
+ verbose("%s: INFO: %d Hostname(s) in the allow list for active response.",
ARGV0, wlc);
}
}
-
- /* Start up message */
+ /* Startup message */
verbose(STARTUP_MSG, ARGV0, (int)getpid());
-
- /* Going to main loop */
+ /* Going to main loop */
OS_ReadMSG(m_queue);
- if (Config.picviz)
- {
- OS_PicvizClose();
- }
-
exit(0);
-
}
-
-
-/* OS_ReadMSG.
- * Main function. Receives the messages(events)
- * and analyze them all.
- */
-#ifndef TESTRULE
+/* Main function. Receives the messages(events) and analyze them all */
+#ifndef TESTRULE
+__attribute__((noreturn))
void OS_ReadMSG(int m_queue)
#else
+__attribute__((noreturn))
void OS_ReadMSG_analysisd(int m_queue)
#endif
{
int i;
- char msg[OS_MAXSTR +1];
+ char msg[OS_MAXSTR + 1];
Eventinfo *lf;
- RuleInfo *stats_rule;
-
+ RuleInfo *stats_rule = NULL;
/* Null to global currently pointers */
currently_rule = NULL;
- /* Initiating the logs */
+ /* Initialize the logs */
OS_InitLog();
-
- /* Initiating the integrity database */
+ /* Initialize the integrity database */
SyscheckInit();
-
- /* Initializing Rootcheck */
+ /* Initialize Rootcheck */
RootcheckInit();
-
-
- /* Initializing host info */
+
+ /* Initialize host info */
HostinfoInit();
-
-
- /* Creating the event list */
- OS_CreateEventList(Config.memorysize);
+ /* Create the event list */
+ OS_CreateEventList(Config.memorysize);
- /* Initiating the FTS list */
- if(!FTS_Init())
- {
+ /* Initiate the FTS list */
+ if (!FTS_Init()) {
ErrorExit(FTS_LIST_ERROR, ARGV0);
}
-
- /* Starting the active response queues */
- if(Config.ar)
- {
- /* Waiting the ARQ to settle .. */
+ /* Initialize the Accumulator */
+ if (!Accumulate_Init()) {
+ merror("accumulator: ERROR: Initialization failed");
+ exit(1);
+ }
+
+ /* Start 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)
- {
+#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)
- {
+ if (Config.ar & LOCAL_AR) {
Config.ar = 0;
- Config.ar|=LOCAL_AR;
- }
- else
- {
+ Config.ar |= LOCAL_AR;
+ } else {
Config.ar = 0;
}
- }
- else
- {
+ } else {
verbose(CONN_TO, ARGV0, ARQUEUE, "active-response");
}
}
-
- #else
+#else
/* Only for LOCAL_ONLY installs */
- if(Config.ar & REMOTE_AR)
- {
- if(Config.ar & LOCAL_AR)
- {
+ if (Config.ar & REMOTE_AR) {
+ if (Config.ar & LOCAL_AR) {
Config.ar = 0;
- Config.ar|=LOCAL_AR;
- }
- else
- {
+ Config.ar |= LOCAL_AR;
+ } else {
Config.ar = 0;
}
}
- #endif
-
- if(Config.ar & LOCAL_AR)
- {
- if((execdq = StartMQ(EXECQUEUE, WRITE)) < 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)
- {
+ if (Config.ar & REMOTE_AR) {
Config.ar = 0;
- Config.ar|=REMOTE_AR;
- }
- else
- {
+ Config.ar |= REMOTE_AR;
+ } else {
Config.ar = 0;
}
- }
- else
- {
+ } else {
verbose(CONN_TO, ARGV0, EXECQUEUE, "exec");
}
}
}
debug1("%s: DEBUG: Active response Init completed.", ARGV0);
-
- /* Getting currently time before starting */
+ /* Get current time before starting */
c_time = time(NULL);
-
- /* Starting the hourly/weekly stats */
- if(Start_Hour() < 0)
+ /* Start the hourly/weekly stats */
+ if (Start_Hour() < 0) {
Config.stats = 0;
- else
- {
- /* Initializing stats rules */
+ } else {
+ /* Initialize stats rules */
stats_rule = zerorulemember(
- STATS_MODULE,
- Config.stats,
- 0,0,0,0,0,0);
+ STATS_MODULE,
+ Config.stats,
+ 0, 0, 0, 0, 0, 0);
- if(!stats_rule)
- {
- ErrorExit(MEM_ERROR, ARGV0);
+ if (!stats_rule) {
+ ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
}
stats_rule->group = "stats,";
stats_rule->comment = "Excessive number of events (above normal).";
}
+ /* Do some cleanup */
+ memset(msg, '\0', OS_MAXSTR + 1);
- /* Doing some cleanup */
- memset(msg, '\0', OS_MAXSTR +1);
-
-
- /* Initializing the logs */
+ /* Initialize the logs */
{
- lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
- if(!lf)
- ErrorExit(MEM_ERROR, ARGV0);
+ lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
+ if (!lf) {
+ ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
+ }
+ os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
lf->year = prev_year;
strncpy(lf->mon, prev_month, 3);
lf->day = today;
- if(OS_GetLogLocation(lf) < 0)
- {
+ 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);
-
+
+#ifdef SQLITE_ENABLED
+ /* Open the sqlite db */
+ extern sqlite3 *conn;
+ int s_error = 0;
+ if (Config.md5_allowlist) {
+ debug2("Opening md5_allowlist: %s", Config.md5_allowlist);
+ if((s_error = sqlite3_open(Config.md5_allowlist, &conn))) {
+ merror(INVALID_IGNORE_MD5DB, ARGV0, Config.md5_allowlist);
+ }
+
+ }
+#endif
+
+ 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);
+ while (1) {
+ lf = (Eventinfo *)calloc(1, sizeof(Eventinfo));
+ os_calloc(Config.decoder_order_size, sizeof(char*), lf->fields);
+
+ /* This shouldn't happen */
+ if (lf == NULL) {
+ ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
}
-
+
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)))
- {
+ if ((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg))) {
RuleNode *rulenode_pt;
- /* Getting the time we received the event */
+ /* Get 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)
- {
+ /* Check 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);
+ 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 */
+ /* Current rule must be null in here */
currently_rule = NULL;
-
- /** Checking the date/hour changes **/
+ /** Check the date/hour changes **/
/* Update the hour */
- if(thishour != __crt_hour)
- {
+ if (thishour != __crt_hour) {
/* Search all the rules and print the number
- * of alerts that each one fired.
+ * of alerts that each one fired
*/
DumpLogstats();
thishour = __crt_hour;
/* Check if the date has changed */
- if(today != lf->day)
- {
- if(Config.stats)
- {
+ if (today != lf->day) {
+ if (Config.stats) {
/* Update the hourly stats (done daily) */
Update_Hour();
}
- if(OS_GetLogLocation(lf) < 0)
- {
+ if (OS_GetLogLocation(lf) < 0) {
ErrorExit("%s: Error allocating log files", ARGV0);
}
prev_year = lf->year;
}
}
-
-
- /* Incrementing number of events received */
- hourly_events++;
- /*** Running decoders ***/
+ /* Increment number of events received */
+ hourly_events++;
+
+ /*** Run decoders ***/
/* Integrity check from syscheck */
- if(msg[0] == SYSCHECK_MQ)
- {
+ if (msg[0] == SYSCHECK_MQ) {
hourly_syscheck++;
-
- if(!DecodeSyscheck(lf))
- {
+
+ if (!DecodeSyscheck(lf)) {
/* We don't process syscheck events further */
goto CLMEM;
}
- /* Getting log size */
+ /* Get log size */
lf->size = strlen(lf->log);
}
/* Rootcheck decoding */
- else if(msg[0] == ROOTCHECK_MQ)
- {
- if(!DecodeRootcheck(lf))
- {
+ else if (msg[0] == ROOTCHECK_MQ) {
+ if (!DecodeRootcheck(lf)) {
/* We don't process rootcheck events further */
goto CLMEM;
}
}
/* Host information special decoder */
- else if(msg[0] == HOSTINFO_MQ)
- {
- if(!DecodeHostinfo(lf))
- {
+ 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 */
+ /* Run the general Decoders */
+ else {
+ /* Get 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 (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))
- {
+ hourly_firewall++;
+ if (Config.logfw) {
+ if (!FW_Log(lf)) {
goto CLMEM;
}
}
}
-
/* We only check if the last message is
- * duplicated on syslog.
+ * duplicated on syslog
*/
- else if(lf->decoder_info->type == SYSLOG)
- {
- /* Checking if the message is duplicated */
- if(LastMsg_Stats(lf->full_log) == 1)
+ else if (lf->decoder_info->type == SYSLOG) {
+ /* Check if the message is duplicated */
+ if (LastMsg_Stats(lf->full_log) == 1) {
goto CLMEM;
- else
+ } else {
LastMsg_Change(lf->full_log);
+ }
}
-
/* Stats checking */
- if(Config.stats)
- {
- if(Check_Hour(lf) == 1)
- {
- void *saved_rule = lf->generated_rule;
+ if (Config.stats) {
+ if (Check_Hour() == 1) {
+ RuleInfo *saved_rule = lf->generated_rule;
char *saved_log;
-
- /* Saving previous log */
+
+ /* Save 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)
- {
+ /* Alert for statistical analysis */
+ if (stats_rule->alert_opts & DO_LOGALERT) {
__crt_ftell = ftell(_aflog);
- OS_Log(lf);
- }
+ if (Config.custom_alert_output) {
+ OS_CustomLog(lf, Config.custom_alert_output_format);
+ } else {
+ OS_Log(lf);
+ }
+ /* Log to json file */
+ if (Config.jsonout_output) {
+ jsonout_output_event(lf);
+ }
+ }
/* Set lf to the old values */
lf->generated_rule = saved_rule;
}
}
+ /* Check the rules */
+ DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
+ ARGV0, lf->decoder_info->type);
- /* Checking the rules */
- DEBUG_MSG("%s: DEBUG: Checking the rules - %d ",
- ARGV0, lf->decoder_info->type);
-
-
- /* Looping all the rules */
+ /* Loop over all the rules */
rulenode_pt = OS_GetFirstRule();
- if(!rulenode_pt)
- {
+ if (!rulenode_pt) {
ErrorExit("%s: Rules in an inconsistent state. Exiting.",
- ARGV0);
+ ARGV0);
}
-
- do
- {
- if(lf->decoder_info->type == OSSEC_ALERT)
- {
- if(!lf->generated_rule)
- {
- goto CLMEM;
+ do {
+ if (lf->decoder_info->type == OSSEC_ALERT) {
+ if (!lf->generated_rule) {
+ goto CLMEM;
}
-
- /* We go ahead in here and process the alert. */
+
+ /* Process the alert */
currently_rule = lf->generated_rule;
}
-
- /* The categories must match */
- else if(rulenode_pt->ruleinfo->category !=
- lf->decoder_info->type)
- {
+
+ /* 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)
- {
+ /* Check each rule */
+ else if ((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
+ == NULL) {
continue;
}
-
/* Ignore level 0 */
- if(currently_rule->level == 0)
- {
+ if (currently_rule->level == 0) {
break;
}
-
- /* Checking ignore time */
- if(currently_rule->ignore_time)
- {
- if(currently_rule->time_ignored == 0)
- {
+ /* Check 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
+ /* If the current time - the time the rule was ignored
* is less than the time it should be ignored,
- * leave (do not alert again).
+ * leave (do not alert again)
*/
- else if((lf->time - currently_rule->time_ignored)
- < currently_rule->ignore_time)
- {
+ else if ((lf->time - currently_rule->time_ignored)
+ < currently_rule->ignore_time) {
break;
- }
- else
- {
+ } 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 */
+ /* Check if we should ignore it */
+ if (currently_rule->ckignore && IGnore(lf)) {
+ /* Ignore rule */
lf->generated_rule = NULL;
break;
}
-
-
- /* Checking if we need to add to ignore list */
- if(currently_rule->ignore)
- {
+
+ /* Check 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)
- {
+ /* Log the alert if configured to */
+ if (currently_rule->alert_opts & DO_LOGALERT) {
__crt_ftell = ftell(_aflog);
- OS_Log(lf);
- }
-
- /* Log to prelude */
- #ifdef PRELUDE
- if(Config.prelude)
- {
- if(Config.prelude_log_level <= currently_rule->level)
- {
- OS_PreludeLog(lf);
+ if (Config.custom_alert_output) {
+ OS_CustomLog(lf, Config.custom_alert_output_format);
+ } else {
+ OS_Log(lf);
+ }
+ /* Log to json file */
+ if (Config.jsonout_output) {
+ jsonout_output_event(lf);
}
}
- #endif
+#ifdef PRELUDE_OUTPUT_ENABLED
+ /* Log to prelude */
+ if (Config.prelude) {
+ if (Config.prelude_log_level <= currently_rule->level) {
+ OS_PreludeLog(lf);
+ }
+ }
+#endif
- /* Log to Picviz */
- if (Config.picviz)
- {
- OS_PicvizLog(lf);
+#ifdef ZEROMQ_OUTPUT_ENABLED
+ /* Log to zeromq */
+ if (Config.zeromq_output) {
+ zeromq_output_event(lf);
}
-
+#endif
+
/* Execute an active response */
- if(currently_rule->ar)
- {
+ if (currently_rule->ar) {
int do_ar;
active_response **rule_ar;
rule_ar = currently_rule->ar;
- while(*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)
+ 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)
+ 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);
+ if (do_ar && execdq > 0) {
+ 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))
- {
+ 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 =
+ } 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);
+ else if (currently_rule->group_prev_matched) {
+ unsigned int j = 0;
+
+ while (j < currently_rule->group_prev_matched_sz) {
+ if (!OSList_AddData(
+ currently_rule->group_prev_matched[j],
+ lf)) {
+ merror("%s: Unable to add data to grp list.", ARGV0);
}
- i++;
+ j++;
}
}
-
+
OS_AddEvent(lf);
break;
- }while((rulenode_pt = rulenode_pt->next) != NULL);
-
+ } while ((rulenode_pt = rulenode_pt->next) != NULL);
/* If configured to log all, do it */
- if(Config.logall)
+ if (Config.logall)
OS_Store(lf);
+ if (Config.logall_json)
+ jsonout_output_archive(lf);
-
- /* Cleaning the memory */
- CLMEM:
-
+CLMEM:
+ /** Cleaning the memory **/
/* Only clear the memory if the eventinfo was not
- * added to the stateful memory
+ * added to the stateful memory
* -- message is free inside clean event --
*/
- if(lf->generated_rule == NULL)
+ if (lf->generated_rule == NULL) {
Free_Eventinfo(lf);
-
- }
- else
- {
+ }
+ } else {
free(lf);
}
}
- return;
}
-
-/* CheckIfRuleMatch v0.1
- * Will check if the currently_rule matches the event information
- */
+/* Checks if the current_rule matches the event information */
RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node)
{
/* We check for:
* weekday,
* status,
*/
- RuleInfo *currently_rule = curr_node->ruleinfo;
-
-
+ RuleInfo *rule = curr_node->ruleinfo;
+ int i;
+
/* Can't be null */
- if(!currently_rule)
- {
+ if (!rule) {
merror("%s: Inconsistent state. currently rule NULL", ARGV0);
- return(NULL);
+ return (NULL);
}
-
- #ifdef TESTRULE
- if(full_output)
- print_out(" Trying rule: %d - %s", currently_rule->sigid,
- currently_rule->comment);
- #endif
-
-
- /* Checking if any decoder pre-matched here */
- if(currently_rule->decoded_as &&
- currently_rule->decoded_as != lf->decoder_info->id)
- {
- return(NULL);
+#ifdef TESTRULE
+ if (full_output && !alert_only)
+ print_out(" Trying rule: %d - %s", rule->sigid,
+ rule->comment);
+#endif
+
+ /* Check if any decoder pre-matched here */
+ if (rule->decoded_as &&
+ rule->decoded_as != lf->decoder_info->id) {
+ return (NULL);
}
-
-
-
- /* Checking program name */
- if(currently_rule->program_name)
- {
- if(!lf->program_name)
- return(NULL);
- if(!OSMatch_Execute(lf->program_name,
- lf->p_name_size,
- currently_rule->program_name))
- return(NULL);
+ /* Check program name */
+ if (rule->program_name) {
+ if (!lf->program_name) {
+ return (NULL);
+ }
+
+ if (!OSMatch_Execute(lf->program_name,
+ lf->p_name_size,
+ rule->program_name)) {
+ return (NULL);
+ }
}
+ else if (rule->program_name_pcre2) {
+ if (!lf->program_name) {
+ return (NULL);
+ }
+ if (!OSPcre2_Execute(lf->program_name,
+ rule->program_name_pcre2)) {
+ return (NULL);
+ }
+ }
- /* Checking for the id */
- if(currently_rule->id)
- {
- if(!lf->id)
- {
- return(NULL);
+ /* Check for the ID */
+ if (rule->id) {
+ if (!lf->id) {
+ return (NULL);
+ }
+
+ if (!OSMatch_Execute(lf->id,
+ strlen(lf->id),
+ rule->id)) {
+ return (NULL);
}
-
- if(!OSMatch_Execute(lf->id,
- strlen(lf->id),
- currently_rule->id))
- return(NULL);
}
-
+ else if (rule->id_pcre2) {
+ if (!lf->id) {
+ return (NULL);
+ }
- /* Checking if any word to match exists */
- if(currently_rule->match)
- {
- if(!OSMatch_Execute(lf->log, lf->size, currently_rule->match))
- return(NULL);
- }
+ if (!OSPcre2_Execute(lf->id,
+ rule->id_pcre2)) {
+ return (NULL);
+ }
+ }
+ /* Check if any word to match exists */
+ if (rule->match) {
+ if (!OSMatch_Execute(lf->log, lf->size, rule->match)) {
+ return (NULL);
+ }
+ }
+ else if (rule->match_pcre2) {
+ if (!OSPcre2_Execute(lf->log, rule->match_pcre2)) {
+ return (NULL);
+ }
+ }
-
- /* Checking if exist any regex for this rule */
- if(currently_rule->regex)
- {
- if(!OSRegex_Execute(lf->log, currently_rule->regex))
- return(NULL);
+ /* Check if exist any regex for this rule */
+ if (rule->regex) {
+ if (!OSRegex_Execute(lf->log, rule->regex)) {
+ return (NULL);
+ }
}
-
-
- /* Checking for actions */
- if(currently_rule->action)
- {
- if(!lf->action)
- return(NULL);
+ else if (rule->pcre2) {
+ if (!OSPcre2_Execute(lf->log, rule->pcre2)) {
+ return (NULL);
+ }
+ }
+
+ /* Check for actions */
+ if (rule->action) {
+ if (!lf->action) {
+ return (NULL);
+ }
- if(strcmp(currently_rule->action,lf->action) != 0)
- return(NULL);
+ if (strcmp(rule->action, lf->action) != 0) {
+ return (NULL);
+ }
}
-
- /* Checking for the url */
- if(currently_rule->url)
- {
- if(!lf->url)
- {
- return(NULL);
+ /* Checking for the URL */
+ if (rule->url) {
+ if (!lf->url) {
+ return (NULL);
}
-
- if(!OSMatch_Execute(lf->url, strlen(lf->url), currently_rule->url))
- {
- return(NULL);
+
+ if (!OSMatch_Execute(lf->url, strlen(lf->url), rule->url)) {
+ return (NULL);
}
}
+ if (rule->url_pcre2) {
+ if (!lf->url) {
+ return (NULL);
+ }
+ if (!OSPcre2_Execute(lf->url, rule->url_pcre2)) {
+ return (NULL);
+ }
+ }
+ /* Check for dynamic fields */
+
+ for (i = 0; i < Config.decoder_order_size && rule->fields[i]; i++) {
+ int j;
+
+ for (j = 0; j < Config.decoder_order_size; j++)
+ if (lf->decoder_info->fields[j])
+ if (strcasecmp(lf->decoder_info->fields[j], rule->fields[i]->name) == 0)
+ break;
- /* Getting tcp/ip packet information */
- if(currently_rule->alert_opts & DO_PACKETINFO)
- {
- /* Checking for the srcip */
- if(currently_rule->srcip)
- {
- if(!lf->srcip)
- {
- return(NULL);
+ if (j == Config.decoder_order_size)
+
+ return NULL;
+
+ if (!OSRegex_Execute(lf->fields[j], rule->fields[i]->regex))
+ return NULL;
+ }
+
+
+ /* Get TCP/IP packet information */
+ if (rule->alert_opts & DO_PACKETINFO) {
+ /* Check for the srcip */
+ if (rule->srcip) {
+ if (!lf->srcip) {
+ return (NULL);
}
- if(!OS_IPFoundList(lf->srcip, currently_rule->srcip))
- {
- return(NULL);
+ if (!OS_IPFoundList(lf->srcip, rule->srcip)) {
+ return (NULL);
}
}
- /* Checking for the dstip */
- if(currently_rule->dstip)
- {
- if(!lf->dstip)
- {
- return(NULL);
+ /* Check for the dstip */
+ if (rule->dstip) {
+ if (!lf->dstip) {
+ return (NULL);
}
- if(!OS_IPFoundList(lf->dstip, currently_rule->dstip))
- {
- return(NULL);
+ if (!OS_IPFoundList(lf->dstip, rule->dstip)) {
+ return (NULL);
}
}
- if(currently_rule->srcport)
- {
- if(!lf->srcport)
- {
- return(NULL);
+ if (rule->srcport) {
+ if (!lf->srcport) {
+ return (NULL);
}
-
- if(!OSMatch_Execute(lf->srcport,
- strlen(lf->srcport),
- currently_rule->srcport))
- {
- return(NULL);
+
+ if (!OSMatch_Execute(lf->srcport,
+ strlen(lf->srcport),
+ rule->srcport)) {
+ return (NULL);
}
}
- if(currently_rule->dstport)
- {
- if(!lf->dstport)
- {
- return(NULL);
+ else if (rule->srcport_pcre2) {
+ if (!lf->srcport) {
+ return (NULL);
}
-
- if(!OSMatch_Execute(lf->dstport,
- strlen(lf->dstport),
- currently_rule->dstport))
- {
- return(NULL);
+
+ if (!OSPcre2_Execute(lf->srcport,
+ rule->srcport_pcre2)) {
+ return (NULL);
+ }
+ }
+ if (rule->dstport) {
+ if (!lf->dstport) {
+ return (NULL);
+ }
+
+ if (!OSMatch_Execute(lf->dstport,
+ strlen(lf->dstport),
+ rule->dstport)) {
+ return (NULL);
+ }
+ }
+ else if (rule->dstport_pcre2) {
+ if (!lf->dstport) {
+ return (NULL);
+ }
+
+ if (!OSPcre2_Execute(lf->dstport,
+ rule->dstport_pcre2)) {
+ return (NULL);
}
}
} /* END PACKET_INFO */
-
/* Extra information from event */
- if(currently_rule->alert_opts & DO_EXTRAINFO)
- {
- /* Checking compiled rule. */
- if(currently_rule->compiled_rule)
- {
- if(!currently_rule->compiled_rule(lf))
- {
- return(NULL);
+ if (rule->alert_opts & DO_EXTRAINFO) {
+ /* Check compiled rule */
+ if (rule->compiled_rule) {
+ if (!rule->compiled_rule(lf)) {
+ return (NULL);
}
}
-
/* Checking if exist any user to match */
- if(currently_rule->user)
- {
- if(lf->dstuser)
- {
- if(!OSMatch_Execute(lf->dstuser,
- strlen(lf->dstuser),
- currently_rule->user))
- return(NULL);
+ if (rule->user) {
+ if (lf->dstuser) {
+ if (!OSMatch_Execute(lf->dstuser,
+ strlen(lf->dstuser),
+ rule->user)) {
+ return (NULL);
+ }
+ } else if (lf->srcuser) {
+ if (!OSMatch_Execute(lf->srcuser,
+ strlen(lf->srcuser),
+ rule->user)) {
+ return (NULL);
+ }
+ } else {
+ /* no user set */
+ return (NULL);
}
- else if(lf->srcuser)
- {
- if(!OSMatch_Execute(lf->srcuser,
- strlen(lf->srcuser),
- currently_rule->user))
+ }
+ else if (rule->user_pcre2) {
+ if (lf->dstuser) {
+ if (!OSPcre2_Execute(lf->dstuser,
+ rule->user_pcre2)) {
+ return (NULL);
+ }
+ } else if (lf->srcuser) {
+ if (!OSPcre2_Execute(lf->srcuser,
+ rule->user_pcre2)) {
+ return (NULL);
+ }
+ } else {
+ /* no user set */
+ return (NULL);
+ }
+ }
+
+ /* Adding checks for geoip. */
+ if(rule->srcgeoip) {
+ if(lf->srcgeoip) {
+ if(!OSMatch_Execute(lf->srcgeoip,
+ strlen(lf->srcgeoip),
+ rule->srcgeoip))
return(NULL);
+ } else {
+ return(NULL);
}
- else
- {
- /* no user set */
+ }
+ else if(rule->srcgeoip_pcre2) {
+ if(lf->srcgeoip) {
+ if(!OSPcre2_Execute(lf->srcgeoip,
+ rule->srcgeoip_pcre2))
+ return(NULL);
+ } else {
return(NULL);
}
}
- /* Checking if any rule related to the size exist */
- if(currently_rule->maxsize)
- {
- if(lf->size < currently_rule->maxsize)
+ if(rule->dstgeoip) {
+ if(lf->dstgeoip) {
+ if(!OSMatch_Execute(lf->dstgeoip,
+ strlen(lf->dstgeoip),
+ rule->dstgeoip))
+ return(NULL);
+ } else {
return(NULL);
+ }
+ }
+ else if(rule->dstgeoip_pcre2) {
+ if(lf->dstgeoip) {
+ if(!OSPcre2_Execute(lf->dstgeoip,
+ rule->dstgeoip_pcre2))
+ return(NULL);
+ } else {
+ return(NULL);
+ }
}
- /* Checking if we are in the right time */
- if(currently_rule->day_time)
- {
- if(!OS_IsonTime(lf->hour, currently_rule->day_time))
- {
- return(NULL);
+ /* Check if any rule related to the size exist */
+ if (rule->maxsize) {
+ if (lf->size < rule->maxsize) {
+ return (NULL);
}
}
+ /* Check if we are in the right time */
+ if (rule->day_time) {
+ if (!OS_IsonTime(lf->hour, rule->day_time)) {
+ return (NULL);
+ }
+ }
- /* Checking week day */
- if(currently_rule->week_day)
- {
- if(!OS_IsonDay(__crt_wday, currently_rule->week_day))
- {
- return(NULL);
+ /* Check week day */
+ if (rule->week_day) {
+ if (!OS_IsonDay(__crt_wday, rule->week_day)) {
+ return (NULL);
}
}
+ /* Get extra data */
+ if (rule->extra_data) {
+ if (!lf->data) {
+ return (NULL);
+ }
- /* Getting extra data */
- if(currently_rule->extra_data)
- {
- if(!lf->data)
- return(NULL);
+ if (!OSMatch_Execute(lf->data,
+ strlen(lf->data),
+ rule->extra_data)) {
+ return (NULL);
+ }
+ }
+ else if (rule->extra_data_pcre2) {
+ if (!lf->data) {
+ return (NULL);
+ }
- if(!OSMatch_Execute(lf->data,
- strlen(lf->data),
- currently_rule->extra_data))
- return(NULL);
+ if (!OSPcre2_Execute(lf->data,
+ rule->extra_data_pcre2)) {
+ return (NULL);
+ }
}
+ /* Check hostname */
+ if (rule->hostname) {
+ if (!lf->hostname) {
+ return (NULL);
+ }
- /* Checking hostname */
- if(currently_rule->hostname)
- {
- if(!lf->hostname)
- return(NULL);
+ if (!OSMatch_Execute(lf->hostname,
+ strlen(lf->hostname),
+ rule->hostname)) {
+ return (NULL);
+ }
+ }
+ else if (rule->hostname_pcre2) {
+ if (!lf->hostname) {
+ return (NULL);
+ }
- if(!OSMatch_Execute(lf->hostname,
- strlen(lf->hostname),
- currently_rule->hostname))
- return(NULL);
+ if (!OSPcre2_Execute(lf->hostname,
+ rule->hostname_pcre2)) {
+ return (NULL);
+ }
}
+ /* Check for status */
+ if (rule->status) {
+ if (!lf->status) {
+ return (NULL);
+ }
- /* Checking for status */
- if(currently_rule->status)
- {
- if(!lf->status)
- return(NULL);
+ if (!OSMatch_Execute(lf->status,
+ strlen(lf->status),
+ rule->status)) {
+ return (NULL);
+ }
+ }
+ else if (rule->status_pcre2) {
+ if (!lf->status) {
+ return (NULL);
+ }
- if(!OSMatch_Execute(lf->status,
- strlen(lf->status),
- currently_rule->status))
- return(NULL);
+ if (!OSPcre2_Execute(lf->status,
+ rule->status_pcre2)) {
+ return (NULL);
+ }
+ }
+
+
+ /* Do diff check */
+ if (rule->context_opts & SAME_DODIFF) {
+ if (!doDiff(rule, lf)) {
+ return (NULL);
+ }
}
}
-
- /* Checking for the FTS flag */
- if(currently_rule->alert_opts & DO_FTS)
- {
+ /* Check for the FTS flag */
+ if (rule->alert_opts & DO_FTS) {
/** FTS CHECKS **/
- if(lf->decoder_info->fts)
- {
- if(lf->decoder_info->fts & FTS_DONE)
- {
- /* We already did the fts in here. */
- }
- else if(!FTS(lf))
- {
- return(NULL);
+ if (lf->decoder_info->fts) {
+ if (lf->decoder_info->fts & FTS_DONE) {
+ /* We already did the fts in here */
+ } else if (!FTS(lf)) {
+ return (NULL);
}
+ } else {
+ return (NULL);
}
- else
- {
- return(NULL);
+ }
+
+ /* List lookups */
+ if (rule->lists != NULL) {
+ ListRule *list_holder = rule->lists;
+ while (list_holder) {
+ switch (list_holder->field) {
+ case RULE_SRCIP:
+ if (!lf->srcip) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->srcip)) {
+ return (NULL);
+ }
+ break;
+ case RULE_SRCPORT:
+ if (!lf->srcport) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->srcport)) {
+ return (NULL);
+ }
+ break;
+ case RULE_DSTIP:
+ if (!lf->dstip) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->dstip)) {
+ return (NULL);
+ }
+ break;
+ case RULE_DSTPORT:
+ if (!lf->dstport) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->dstport)) {
+ return (NULL);
+ }
+ break;
+ case RULE_USER:
+ if (lf->srcuser) {
+ if (!OS_DBSearch(list_holder, lf->srcuser)) {
+ return (NULL);
+ }
+ } else if (lf->dstuser) {
+ if (!OS_DBSearch(list_holder, lf->dstuser)) {
+ return (NULL);
+ }
+ } else {
+ return (NULL);
+ }
+ break;
+ case RULE_URL:
+ if (!lf->url) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->url)) {
+ return (NULL);
+ }
+ break;
+ case RULE_ID:
+ if (!lf->id) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->id)) {
+ return (NULL);
+ }
+ break;
+ case RULE_HOSTNAME:
+ if (!lf->hostname) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->hostname)) {
+ return (NULL);
+ }
+ break;
+ case RULE_PROGRAM_NAME:
+ if (!lf->program_name) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->program_name)) {
+ return (NULL);
+ }
+ break;
+ case RULE_STATUS:
+ if (!lf->status) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->status)) {
+ return (NULL);
+ }
+ break;
+ case RULE_ACTION:
+ if (!lf->action) {
+ return (NULL);
+ }
+ if (!OS_DBSearch(list_holder, lf->action)) {
+ return (NULL);
+ }
+ break;
+ default:
+ return (NULL);
+ }
+
+ list_holder = list_holder->next;
}
}
-
/* If it is a context rule, search for it */
- if(currently_rule->context == 1)
- {
- if(!currently_rule->event_search(lf, currently_rule))
- return(NULL);
+ if (rule->context == 1) {
+ if (!(rule->context_opts & SAME_DODIFF)) {
+ if (rule->event_search) {
+ if (!rule->event_search(lf, rule)) {
+ return (NULL);
+ }
+ }
+ }
}
- #ifdef TESTRULE
- if(full_output)
- print_out(" *Rule %d matched.", currently_rule->sigid);
- #endif
-
-
+#ifdef TESTRULE
+ if (full_output && !alert_only) {
+ print_out(" *Rule %d matched.", rule->sigid);
+ }
+#endif
+
/* Search for dependent rules */
- if(curr_node->child)
- {
+ if (curr_node->child) {
RuleNode *child_node = curr_node->child;
RuleInfo *child_rule = NULL;
-
- #ifdef TESTRULE
- if(full_output)
- print_out(" *Trying child rules.");
- #endif
-
- while(child_node)
- {
+
+#ifdef TESTRULE
+ if (full_output && !alert_only) {
+ print_out(" *Trying child rules.");
+ }
+#endif
+
+ while (child_node) {
child_rule = OS_CheckIfRuleMatch(lf, child_node);
- if(child_rule != NULL)
- {
- return(child_rule);
+ if (child_rule != NULL) {
+ return (child_rule);
}
-
+
child_node = child_node->next;
}
}
-
/* If we are set to no alert, keep going */
- if(currently_rule->alert_opts & NO_ALERT)
- {
- return(NULL);
+ if (rule->alert_opts & NO_ALERT) {
+ return (NULL);
}
-
hourly_alerts++;
- currently_rule->firedtimes++;
+ rule->firedtimes++;
- return(currently_rule); /* Matched */
+ return (rule); /* Matched */
}
-
-/** void LoopRule(RuleNode *curr_node);
- * Update each rule and print it to the logs.
- */
-void LoopRule(RuleNode *curr_node, FILE *flog)
+/* Update each rule and print it to the logs */
+static void LoopRule(RuleNode *curr_node, FILE *flog)
{
- if(curr_node->ruleinfo->firedtimes)
- {
- fprintf(flog, "%d-%d-%d-%d\n",
- thishour,
+ if (curr_node->ruleinfo->firedtimes) {
+ fprintf(flog, "%d-%d-%d-%d\n",
+ thishour,
curr_node->ruleinfo->sigid,
curr_node->ruleinfo->level,
curr_node->ruleinfo->firedtimes);
curr_node->ruleinfo->firedtimes = 0;
}
-
- if(curr_node->child)
- {
+
+ if (curr_node->child) {
RuleNode *child_node = curr_node->child;
- while(child_node)
- {
+ while (child_node) {
LoopRule(child_node, flog);
child_node = child_node->next;
}
return;
}
-
-/** void DumpLogstats();
- * Dump the hourly stats about each rule.
- */
-void DumpLogstats()
+/* Dump the hourly stats about each rule */
+static void DumpLogstats()
{
RuleNode *rulenode_pt;
- char logfile[OS_FLSIZE +1];
+ char logfile[OS_FLSIZE + 1];
FILE *flog;
- /* Opening log file */
+ /* Open log file */
snprintf(logfile, OS_FLSIZE, "%s/%d/", STATSAVED, prev_year);
- if(IsDir(logfile) == -1)
- if(mkdir(logfile,0770) == -1)
- {
- merror(MKDIR_ERROR, ARGV0, logfile);
+ if (IsDir(logfile) == -1)
+ if (mkdir(logfile, 0770) == -1) {
+ merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
return;
}
- snprintf(logfile,OS_FLSIZE,"%s/%d/%s", STATSAVED, prev_year,prev_month);
+ snprintf(logfile, OS_FLSIZE, "%s/%d/%s", STATSAVED, prev_year, prev_month);
- if(IsDir(logfile) == -1)
- if(mkdir(logfile,0770) == -1)
- {
- merror(MKDIR_ERROR,ARGV0,logfile);
+ if (IsDir(logfile) == -1)
+ if (mkdir(logfile, 0770) == -1) {
+ merror(MKDIR_ERROR, ARGV0, logfile, errno, strerror(errno));
return;
}
- /* Creating the logfile name */
- snprintf(logfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
- STATSAVED,
- prev_year,
- prev_month,
- "totals",
- today);
+ /* Creat the logfile name */
+ snprintf(logfile, OS_FLSIZE, "%s/%d/%s/ossec-%s-%02d.log",
+ STATSAVED,
+ prev_year,
+ prev_month,
+ "totals",
+ today);
flog = fopen(logfile, "a");
- if(!flog)
- {
- merror(FOPEN_ERROR, ARGV0, logfile);
+ if (!flog) {
+ merror(FOPEN_ERROR, ARGV0, logfile, errno, strerror(errno));
return;
}
rulenode_pt = OS_GetFirstRule();
- if(!rulenode_pt)
- {
+ if (!rulenode_pt) {
ErrorExit("%s: Rules in an inconsistent state. Exiting.",
- ARGV0);
+ ARGV0);
}
- /* Looping on all the rules and printing the stats from them */
- do
- {
- LoopRule(rulenode_pt, flog);
- }while((rulenode_pt = rulenode_pt->next) != NULL);
+ /* Loop over all the rules and print their stats */
+ do {
+ LoopRule(rulenode_pt, flog);
+ } while ((rulenode_pt = rulenode_pt->next) != NULL);
/* Print total for the hour */
fprintf(flog, "%d--%d--%d--%d--%d\n\n",
- thishour,
- hourly_alerts, hourly_events, hourly_syscheck,hourly_firewall);
+ thishour,
+ hourly_alerts, hourly_events, hourly_syscheck, hourly_firewall);
hourly_alerts = 0;
hourly_events = 0;
hourly_syscheck = 0;
hourly_firewall = 0;
-
+
fclose(flog);
}
-
-
-/* EOF */