new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / testrule.c
old mode 100755 (executable)
new mode 100644 (file)
index 8062fec..c08fb48
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/analysisd/testrule.c, 2012/07/23 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All rights reserved.
  *
  * and/or modify it under the terms of the GNU General Public
  * 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.
  */
 
 #ifdef ARGV0
-   #undef ARGV0
-   #define ARGV0 "ossec-testrule"
+#undef ARGV0
+#define ARGV0 "ossec-testrule"
 #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"
 
 /** Internal Functions **/
-void OS_ReadMSG(int m_queue, char *ut_str);
-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();
-void Lists_OP_CreateLists();
-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 AddtoIGnore(Eventinfo *lf);
-int IGnore(Eventinfo *lf);
+void OS_ReadMSG(char *ut_str);
 
+/* Analysisd function */
+RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
 
-/* For decoders */
 void DecodeEvent(Eventinfo *lf);
 
-
-/* For Decoders */
-int ReadDecodeXML(char *file);
-int SetDecodeXML();
-
-
-void logtest_help(const char *prog)
+/* Print help statement */
+__attribute__((noreturn))
+static void help_logtest(void)
 {
-    print_out(" ");
-    print_out("%s %s - %s (%s)", __ossec_name, __version, __author, __contact);
-    print_out("%s", __site);
-    print_out(" ");
-    print_out("  %s: -[Vatfdh] [-U ut_str] [-u user] [-g group] [-c config] [-D dir]", prog);
+    print_header();
+    print_out("  %s: -[Vhdtva] [-c config] [-D dir] [-U rule:alert:decoder]", ARGV0);
     print_out("    -V          Version and license message");
-    print_out("    -a          Alerts output");
+    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("    -a          Alerts output");
     print_out("    -v          Verbose (full) output/rule debugging");
-    print_out("    -d          Execute in debug mode");
-    print_out("    -h          This help message");
-    print_out("    -U <rule:alert:decoder>   Unit test. Refer to contrib/ossec-testing/runtests.py");
-    print_out("    -u <user>   Run as 'user'");
-    print_out("    -g <group>  Run as 'group'");
-    print_out("    -c <config> Read the 'config' file");
-    print_out("    -D <dir>    Chroot to 'dir'");
+    print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
+    print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
+    print_out("    -U <rule:alert:decoder>  Unit test. Refer to contrib/ossec-testing/runtests.py");
     print_out(" ");
     exit(1);
 }
 
-
-
-/** int main(int argc, char **argv)
- */
 int main(int argc, char **argv)
 {
-    int t_config = 0;
-    int c = 0, m_queue = 0;
+    int test_config = 0;
+    int c = 0;
     char *ut_str = NULL;
-
-    char *dir = DEFAULTDIR;
-    // TODO: delete or implement
-    char *user __attribute__((unused)) = USER;
-    // TODO: delete or implement
-    char *group __attribute__((unused)) = GROUPGLOBAL;
-
-    char *cfg = DEFAULTCPATH;
-
-    /* Setting the name */
+    const char *dir = DEFAULTDIR;
+    const char *cfg = DEFAULTCPATH;
+    const char *user = USER;
+    const char *group = GROUPGLOBAL;
+    uid_t uid;
+    gid_t gid;
+    int quiet = 0;
+
+    /* Set the name */
     OS_SetName(ARGV0);
 
     thishour = 0;
@@ -141,91 +82,110 @@ int main(int argc, char **argv)
     active_responses = NULL;
     memset(prev_month, '\0', 4);
 
-    while((c = getopt(argc, argv, "VatvdhU:u:g:D:c:")) != -1){
-        switch(c){
-           case 'V':
-               print_version();
-               break;
+#ifdef LIBGEOIP_ENABLED
+    geoipdb = NULL;
+#endif
+
+    while ((c = getopt(argc, argv, "VatvdhU:D:c:q")) != -1) {
+        switch (c) {
+            case 'V':
+                print_version();
+                break;
             case 't':
-                t_config = 1;
+                test_config = 1;
                 break;
             case 'h':
-                logtest_help(ARGV0);
+                help_logtest();
                 break;
             case 'd':
                 nowDebug();
                 break;
             case 'U':
-                if(!optarg)
-                    ErrorExit("%s: -U needs an argument",ARGV0);
+                if (!optarg) {
+                    ErrorExit("%s: -U needs an argument", ARGV0);
+                }
                 ut_str = optarg;
                 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);
+                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 'a':
                 alert_only = 1;
                 break;
+            case 'q':
+                quiet = 1;
+                break;
             case 'v':
                 full_output = 1;
                 break;
             default:
-                logtest_help(ARGV0);
+                help_logtest();
                 break;
         }
-
     }
 
-
-
-
-    /* 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);
 
+#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: Unable to open GeoIP database from: %s (disabling GeoIP).", ARGV0, Config.geoipdb_file);
+        }
+    }
+#endif
 
-    /* Getting servers hostname */
+    /* Get server hostname */
     memset(__shost, '\0', 512);
-    if(gethostname(__shost, 512 -1) != 0)
-    {
-        strncpy(__shost, OSSEC_SERVER, 512 -1);
-    }
-    else
-    {
+    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';
+        }
     }
 
+    /* Check if the user/group given are valid */
+    uid = Privsep_GetUser(user);
+    gid = Privsep_GetGroup(group);
+    if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
+        ErrorExit(USER_ERROR, ARGV0, user, group);
+    }
 
+    /* Set the group */
+    if (Privsep_SetGroup(gid) < 0) {
+        ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
+    }
 
-    if(chdir(dir) != 0)
-        ErrorExit(CHROOT_ERROR,ARGV0,dir);
+    /* Chroot */
+    if (Privsep_Chroot(dir) < 0) {
+        ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
+    }
+    nowChroot();
+
+    Config.decoder_order_size = (size_t)getDefine_Int("analysisd", "decoder_order_size", 8, MAX_DECODER_ORDER_SIZE);
 
 
     /*
@@ -236,40 +196,39 @@ int main(int argc, char **argv)
      * completion of all rules and lists.
      */
     {
-        { /* Lad decders */
-            /* Initializing the decoders list */
+        {
+            /* Load decoders */
+            /* Initialize the decoders list */
             OS_CreateOSDecoderList();
 
-            if(!Config.decoders)
-            { /* Legacy loading */
-                /* Reading decoders */
-                if(!ReadDecodeXML("etc/decoder.xml"))
-                {
+            if (!Config.decoders) {
+                /* Legacy loading */
+                /* Read decoders */
+                if (!ReadDecodeXML("etc/decoder.xml")) {
                     ErrorExit(CONFIG_ERROR, ARGV0,  XML_DECODER);
                 }
 
-                /* Reading local ones. */
+                /* Read local ones */
                 c = ReadDecodeXML("etc/local_decoder.xml");
-                if(!c)
-                {
-                    if((c != -2))
+                if (!c) {
+                    if ((c != -2)) {
                         ErrorExit(CONFIG_ERROR, ARGV0,  XML_LDECODER);
-                }
-                else
-                {
+                    }
+                } else {
                     verbose("%s: INFO: Reading local decoder file.", ARGV0);
                 }
-            }
-            else
-            { /* New loaded based on file speified in ossec.conf */
+            } else {
+                /* New loaded based on file specified in ossec.conf */
                 char **decodersfiles;
                 decodersfiles = Config.decoders;
-                while( decodersfiles && *decodersfiles)
-                {
+                while ( decodersfiles && *decodersfiles) {
 
-                    verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
-                    if(!ReadDecodeXML(*decodersfiles))
+                    if(!quiet) {
+                        verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
+                    }
+                    if (!ReadDecodeXML(*decodersfiles)) {
                         ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
+                    }
 
                     free(*decodersfiles);
                     decodersfiles++;
@@ -279,18 +238,19 @@ int main(int argc, char **argv)
             /* Load decoders */
             SetDecodeXML();
         }
-        { /* Load Lists */
-            /* Initializing the lists of list struct */
+        {
+            /* 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)
-                {
+                while (listfiles && *listfiles) {
                     verbose("%s: INFO: Reading the lists file: '%s'", ARGV0, *listfiles);
-                    if(Lists_OP_LoadList(*listfiles) < 0)
+                    if (Lists_OP_LoadList(*listfiles) < 0) {
                         ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
+                    }
                     free(*listfiles);
                     listfiles++;
                 }
@@ -298,19 +258,20 @@ int main(int argc, char **argv)
                 Config.lists = NULL;
             }
         }
-        { /* Load Rules */
-            /* Creating the rules list */
+        {
+            /* Load Rules */
+            /* Create the rules list */
             Rules_OP_CreateRules();
 
-            /* Reading the rules */
+            /* Read the rules */
             {
                 char **rulesfiles;
                 rulesfiles = Config.includes;
-                while(rulesfiles && *rulesfiles)
-                {
+                while (rulesfiles && *rulesfiles) {
                     debug1("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
-                    if(Rules_OP_ReadRules(*rulesfiles) < 0)
+                    if (Rules_OP_ReadRules(*rulesfiles) < 0) {
                         ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
+                    }
 
                     free(*rulesfiles);
                     rulesfiles++;
@@ -321,15 +282,15 @@ int main(int argc, char **argv)
             }
 
             /* 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.
+             * 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();
@@ -338,75 +299,60 @@ int main(int argc, char **argv)
         debug1("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
     }
 
-
-    /* Creating a rules hash (for reading alerts from other servers). */
+    /* 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);
+        if (!Config.g_rules_hash) {
+            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
         }
         AddHash_Rule(tmp_node);
     }
 
-
-    if(t_config == 1)
-    {
+    if (test_config == 1) {
         exit(0);
     }
 
+    /* Set the user */
+    if (Privsep_SetUser(uid) < 0) {
+        ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
+    }
 
     /* Start up message */
     verbose(STARTUP_MSG, ARGV0, getpid());
 
-
     /* Going to main loop */
-    OS_ReadMSG(m_queue, ut_str);
-
+    OS_ReadMSG(ut_str);
 
     exit(0);
-
 }
 
-
-
-/* OS_ReadMSG.
- * Main function. Receives the messages(events)
- * and analyze them all.
- */
-void OS_ReadMSG(int m_queue, char *ut_str)
+/* Receive the messages (events) and analyze them */
+__attribute__((noreturn))
+void OS_ReadMSG(char *ut_str)
 {
-    int i;
-    char msg[OS_MAXSTR +1];
+    char msg[OS_MAXSTR + 1];
     int exit_code = 0;
     char *ut_alertlevel = NULL;
     char *ut_rulelevel = NULL;
     char *ut_decoder_name = NULL;
 
-    if(ut_str)
-    {
+    if (ut_str) {
         /* XXX Break apart string */
         ut_rulelevel = ut_str;
         ut_alertlevel =  strchr(ut_rulelevel, ':');
-        if(!ut_alertlevel)
-        {
+        if (!ut_alertlevel) {
             ErrorExit("%s: -U requires the matching format to be "
                       "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
-        }
-        else
-        {
+        } else {
             *ut_alertlevel = '\0';
             ut_alertlevel++;
         }
         ut_decoder_name = strchr(ut_alertlevel, ':');
-        if(!ut_decoder_name)
-        {
+        if (!ut_decoder_name) {
             ErrorExit("%s: -U requires the matching format to be "
                       "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
-        }
-        else
-        {
+        } else {
             *ut_decoder_name = '\0';
             ut_decoder_name++;
         }
@@ -415,192 +361,164 @@ void OS_ReadMSG(int m_queue, char *ut_str)
     RuleInfoDetail *last_info_detail;
     Eventinfo *lf;
 
-
-    /* Null to global currently pointers */
+    /* Null global pointer to current rule */
     currently_rule = NULL;
 
-
-    /* Creating the event list */
+    /* 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);
     }
 
+    /* Initialize the Accumulator */
+    if (!Accumulate_Init()) {
+        merror("accumulator: ERROR: Initialization failed");
+        exit(1);
+    }
 
     __crt_ftell = 1;
 
-
-    /* Getting currently time before starting */
+    /* Get current time before starting */
     c_time = time(NULL);
 
+    /* Do some cleanup */
+    memset(msg, '\0', OS_MAXSTR + 1);
 
-    /* Doing some cleanup */
-    memset(msg, '\0', OS_MAXSTR +1);
-
-
-    if(!alert_only)
-    print_out("%s: Type one log per line.\n", ARGV0);
-
+    if (!alert_only) {
+        print_out("%s: Type one log per line.\n", ARGV0);
+    }
 
     /* Daemon loop */
-    while(1)
-    {
-        lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
+    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);
-        }
 
+        /* This shouldn't happen */
+        if (lf == NULL) {
+            ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
+        }
 
-        /* Fixing the msg. */
+        /* Fix the msg */
         snprintf(msg, 15, "1:stdin:");
 
-
-
         /* Receive message from queue */
-        if(fgets(msg +8, OS_MAXSTR -8, stdin))
-        {
+        if (fgets(msg + 8, OS_MAXSTR - 8, stdin)) {
             RuleNode *rulenode_pt;
 
-            /* Getting the time we received the event */
+            /* Get the time we received the event */
             c_time = time(NULL);
 
+            /* Remov newline */
+            if (msg[strlen(msg) - 1] == '\n') {
+                msg[strlen(msg) - 1] = '\0';
+            }
 
-            /* Removing new line. */
-            if(msg[strlen(msg) -1] == '\n')
-                msg[strlen(msg) -1] = '\0';
-
-
-            /* Make sure we ignore blank lines. */
-            if(strlen(msg) < 10)
-            {
+            /* Make sure we ignore blank lines */
+            if (strlen(msg) < 10) {
                 continue;
             }
 
-
-            if(!alert_only)print_out("\n");
-
+            if (!alert_only) {
+                print_out("\n");
+            }
 
             /* Default values for the log info */
             Zero_Eventinfo(lf);
 
-
             /* 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;
             }
 
-
-            /* Currently rule must be null in here */
+            /* Current rule must be null in here */
             currently_rule = NULL;
 
-
-            /***  Running decoders ***/
-
-            /* Getting log size */
+            /***  Run decoders ***/
+            /* Get log size */
             lf->size = strlen(lf->log);
 
-
-            /* Decoding event. */
+            /* Decode event */
             DecodeEvent(lf);
 
+            /* Run accumulator */
+            if ( lf->decoder_info->accumulate == 1 ) {
+                print_out("\n**ACCUMULATOR: LEVEL UP!!**\n");
+                lf = Accumulate(lf);
+            }
 
-            /* 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);
             }
 
-
-            #ifdef TESTRULE
-            if(full_output && !alert_only)
+#ifdef TESTRULE
+            if (full_output && !alert_only) {
                 print_out("\n**Rule debugging:");
-            #endif
-
+            }
+#endif
 
-            do
-            {
-                if(lf->decoder_info->type == OSSEC_ALERT)
-                {
-                    if(!lf->generated_rule)
-                    {
+            do {
+                if (lf->decoder_info->type == OSSEC_ALERT) {
+                    if (!lf->generated_rule) {
                         break;
                     }
 
-                    /* 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)
-                {
+                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;
                 }
 
-                #ifdef TESTRULE
-                if(!alert_only)
-                {
-                  char *(ruleinfodetail_text[])={"Text","Link","CVE","OSVDB","BUGTRACKID"};
-                  print_out("\n**Phase 3: Completed filtering (rules).");
-                  print_out("       Rule id: '%d'", currently_rule->sigid);
-                  print_out("       Level: '%d'", currently_rule->level);
-                  print_out("       Description: '%s'",currently_rule->comment);
-                  for (last_info_detail = currently_rule->info_details; last_info_detail != NULL; last_info_detail = last_info_detail->next)
-                  {
-                      print_out("       Info - %s: '%s'", ruleinfodetail_text[last_info_detail->type], last_info_detail->data);
-                  }
+#ifdef TESTRULE
+                if (!alert_only) {
+                    const char *(ruleinfodetail_text[]) = {"Text", "Link", "CVE", "OSVDB", "BUGTRACKID"};
+                    print_out("\n**Phase 3: Completed filtering (rules).");
+                    print_out("       Rule id: '%d'", currently_rule->sigid);
+                    print_out("       Level: '%d'", currently_rule->level);
+                    print_out("       Description: '%s'", currently_rule->comment);
+                    for (last_info_detail = currently_rule->info_details; last_info_detail != NULL; last_info_detail = last_info_detail->next) {
+                        print_out("       Info - %s: '%s'", ruleinfodetail_text[last_info_detail->type], last_info_detail->data);
+                    }
                 }
-                #endif
-
-
+#endif
 
                 /* 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).
+                     * 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 = 0;
                     }
                 }
@@ -609,114 +527,98 @@ void OS_ReadMSG(int m_queue, char *ut_str)
                 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)) {
                     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)
-                {
-                    if(alert_only)
-                    {
+                /* Log the alert if configured to */
+                if (currently_rule->alert_opts & DO_LOGALERT) {
+                    if (alert_only) {
                         OS_LogOutput(lf);
                         __crt_ftell++;
-                    }
-                    else
-                    {
+                    } else {
                         print_out("**Alert to be generated.\n\n");
                     }
                 }
 
-
                 /* 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
-                    {
+                    } 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 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);
+            } while ((rulenode_pt = rulenode_pt->next) != NULL);
 
-            if(ut_str)
-            {
-                /*setup exit code if we are doing unit testing*/
+            if (ut_str) {
+                /* Set up exit code if we are doing unit testing */
                 char holder[1024];
                 holder[1] = '\0';
                 exit_code = 3;
-                if(lf->decoder_info->name != NULL && strcasecmp(ut_decoder_name, lf->decoder_info->name) == 0)
-                {
+                print_out("lf->decoder_info->name: '%s'", lf->decoder_info->name);
+                print_out("ut_decoder_name       : '%s'", ut_decoder_name);
+                if (lf->decoder_info->name != NULL && strcasecmp(ut_decoder_name, lf->decoder_info->name) == 0) {
                     exit_code--;
+
+                    if (!currently_rule) {
+                        merror("%s: currently_rule not set!", ARGV0);
+                        exit(-1);
+                    }
                     snprintf(holder, 1023, "%d", currently_rule->sigid);
-                    if(strcasecmp(ut_rulelevel, holder) == 0)
-                    {
+                    if (strcasecmp(ut_rulelevel, holder) == 0) {
                         exit_code--;
                         snprintf(holder, 1023, "%d", currently_rule->level);
-                        if(strcasecmp(ut_alertlevel, holder) == 0)
-                        {
+                        if (strcasecmp(ut_alertlevel, holder) == 0) {
                             exit_code--;
-                            printf("%d\n",exit_code);
+                            printf("%d\n", exit_code);
                         }
                     }
+                } else if (lf->decoder_info->name != NULL) {
+                    print_out("decoder matched : '%s'", lf->decoder_info->name);
+                    print_out("decoder expected: '%s'", ut_decoder_name);
+                } else {
+                    print_out("decoder matched : 'NULL'");
                 }
             }
 
-
             /* 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)
+            if (lf->generated_rule == NULL) {
                 Free_Eventinfo(lf);
+            }
 
-        }
-        else
-        {
+        } else {
             exit(exit_code);
         }
     }
     exit(exit_code);
-    return;
 }
-
-
-
-/* EOF */
-