-/* @(#) $Id: testrule.c,v 1.7 2009/08/25 11:30:57 dcid Exp $ */
+/* @(#) $Id$ */
/* Copyright (C) 2009 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
#define ARGV0 "ossec-testrule"
#endif
+
+
#include "shared.h"
#include "alerts/alerts.h"
#include "config.h"
#include "rules.h"
#include "stats.h"
+
#include "eventinfo.h"
#include "analysisd.h"
/** Internal Functions **/
-void OS_ReadMSG(int m_queue);
+void OS_ReadMSG(int m_queue, char *ut_str);
RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
/* 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);
*/
int main(int argc, char **argv)
{
+ int t_config = 0;
int c = 0, m_queue = 0;
+ char *ut_str = NULL;
+
char *dir = DEFAULTDIR;
char *user = USER;
char *group = GROUPGLOBAL;
today = 0;
prev_year = 0;
full_output = 0;
+ alert_only = 0;
+
active_responses = NULL;
memset(prev_month, '\0', 4);
- while((c = getopt(argc, argv, "Vfdhu:g:D:c:")) != -1){
+ while((c = getopt(argc, argv, "VatfdhU:u:g:D:c:")) != -1){
switch(c){
case 'V':
print_version();
break;
+ case 't':
+ t_config = 1;
+ break;
case 'h':
help(ARGV0);
break;
case 'd':
nowDebug();
break;
+ case 'U':
+ if(!optarg)
+ ErrorExit("%s: -U needs an argument",ARGV0);
+ ut_str = optarg;
+ break;
case 'u':
if(!optarg)
ErrorExit("%s: -u needs an argument",ARGV0);
ErrorExit("%s: -c needs an argument",ARGV0);
cfg = optarg;
break;
+ case 'a':
+ alert_only = 1;
+ break;
case 'f':
full_output = 1;
break;
}
+
+
/* Reading configuration file */
if(GlobalConf(cfg) < 0)
{
ErrorExit(CHROOT_ERROR,ARGV0,dir);
-
- /* Reading decoders */
- OS_CreateOSDecoderList();
- if(!ReadDecodeXML("etc/decoder.xml"))
+ /*
+ * Anonymous Section: Load rules, decoders, and lists
+ *
+ * As lists require two pass loading of rules that make use of list lookups
+ * are created with blank database structs, and need to be filled in after
+ * completion of all rules and lists.
+ */
{
- ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
- }
+ { /* Lad decders */
+ /* Initializing the decoders list */
+ OS_CreateOSDecoderList();
+
+ if(!Config.decoders)
+ { /* Legacy loading */
+ /* Reading decoders */
+ if(!ReadDecodeXML("etc/decoder.xml"))
+ {
+ ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
+ }
- c = ReadDecodeXML("etc/local_decoder.xml");
- if(!c)
- {
- if((c != -2))
- ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER);
- }
- SetDecodeXML();
+ /* Reading local ones. */
+ c = ReadDecodeXML("etc/local_decoder.xml");
+ if(!c)
+ {
+ if((c != -2))
+ ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER);
+ }
+ else
+ {
+ 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)
+ {
-
- /* Creating the rules list */
- Rules_OP_CreateRules();
+ verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
+ if(!ReadDecodeXML(*decodersfiles))
+ ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
+
+ free(*decodersfiles);
+ decodersfiles++;
+ }
+ }
-
- /* Reading the rules */
- {
- char **rulesfiles;
- rulesfiles = Config.includes;
- while(rulesfiles && *rulesfiles)
- {
- debug1("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
- if(Rules_OP_ReadRules(*rulesfiles) < 0)
- ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
-
- free(*rulesfiles);
- rulesfiles++;
+ /* Load decoders */
+ SetDecodeXML();
+ }
+ { /* Load Lists */
+ /* Initializing the lists of list struct */
+ Lists_OP_CreateLists();
+ /* Load each list into list struct */
+ {
+ char **listfiles;
+ listfiles = Config.lists;
+ while(listfiles && *listfiles)
+ {
+ verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
+ if(Lists_OP_LoadList(*listfiles) < 0)
+ ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
+ free(*listfiles);
+ listfiles++;
+ }
+ free(Config.lists);
+ Config.lists = NULL;
+ }
}
+ { /* Load Rules */
+ /* Creating the rules list */
+ Rules_OP_CreateRules();
+
+ /* Reading the rules */
+ {
+ char **rulesfiles;
+ rulesfiles = Config.includes;
+ while(rulesfiles && *rulesfiles)
+ {
+ debug1("%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;
+ free(Config.includes);
+ Config.includes = NULL;
+ }
+
+ /* Find all rules with that require list lookups and attache the
+ * the correct list struct to the rule. This keeps rules from having to
+ * search thought the list of lists for the correct file during rule evaluation.
+ */
+ OS_ListLoadRules();
+ }
}
-
+
/* Fixing the levels/accuracy */
{
}
+ if(t_config == 1)
+ {
+ exit(0);
+ }
+
/* Start up message */
verbose(STARTUP_MSG, ARGV0, getpid());
/* Going to main loop */
- OS_ReadMSG(m_queue);
+ OS_ReadMSG(m_queue, ut_str);
exit(0);
* Main function. Receives the messages(events)
* and analyze them all.
*/
-void OS_ReadMSG(int m_queue)
+void OS_ReadMSG(int m_queue, char *ut_str)
{
int i;
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)
+ {
+ /* XXX Break apart string */
+ ut_rulelevel = ut_str;
+ ut_alertlevel = strchr(ut_rulelevel, ':');
+ if(!ut_alertlevel)
+ {
+ ErrorExit("%s: -U requires the matching format to be "
+ "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
+ }
+ else
+ {
+ *ut_alertlevel = '\0';
+ ut_alertlevel++;
+ }
+ ut_decoder_name = strchr(ut_alertlevel, ':');
+ if(!ut_decoder_name)
+ {
+ ErrorExit("%s: -U requires the matching format to be "
+ "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
+ }
+ else
+ {
+ *ut_decoder_name = '\0';
+ ut_decoder_name++;
+ }
+ }
+
+ RuleInfoDetail *last_info_detail;
Eventinfo *lf;
}
+ __crt_ftell = 1;
+
/* Getting currently time before starting */
c_time = time(NULL);
memset(msg, '\0', OS_MAXSTR +1);
+ if(!alert_only)
print_out("%s: Type one log per line.\n", ARGV0);
/* Fixing the msg. */
- strncpy(msg, "1:a:", 5);
+ snprintf(msg, 15, "1:stdin:");
/* Receive message from queue */
- if(fgets(msg +4, OS_MAXSTR, stdin))
+ if(fgets(msg +8, OS_MAXSTR, stdin))
{
RuleNode *rulenode_pt;
/* Make sure we ignore blank lines. */
- if(strlen(msg) < 6)
+ if(strlen(msg) < 10)
{
continue;
}
- print_out("\n");
+ if(!alert_only)print_out("\n");
/* Default values for the log info */
#ifdef TESTRULE
- if(full_output)
+ if(full_output && !alert_only)
print_out("\n**Rule debugging:");
#endif
}
#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);
+ }
+ }
#endif
/* Log the alert if configured to ... */
if(currently_rule->alert_opts & DO_LOGALERT)
{
- print_out("**Alert to be generated.\n\n");
+ if(alert_only)
+ {
+ OS_LogOutput(lf);
+ __crt_ftell++;
+ }
+ else
+ {
+ print_out("**Alert to be generated.\n\n");
+ }
}
}while((rulenode_pt = rulenode_pt->next) != NULL);
+ if(ut_str)
+ {
+ /*setup exit code if we are doing unit testing*/
+ char holder[1024];
+ holder[1] = '\0';
+ exit_code = 3;
+ if(strcasecmp(ut_decoder_name, lf->decoder_info->name) == 0)
+ {
+ exit_code--;
+ snprintf(holder, 1023, "%d", currently_rule->sigid);
+ if(strcasecmp(ut_rulelevel, holder) == 0)
+ {
+ exit_code--;
+ snprintf(holder, 1023, "%d", currently_rule->level);
+ if(strcasecmp(ut_alertlevel, holder) == 0)
+ {
+ exit_code--;
+ printf("%d\n",exit_code);
+ }
+ }
+ }
+ }
+
/* Only clear the memory if the eventinfo was not
* added to the stateful memory
}
else
{
- exit(0);
+ exit(exit_code);
}
}
+ exit(exit_code);
return;
}
/* EOF */
+