3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
11 * License details at the LICENSE file included with OSSEC or
12 * online at: http://www.ossec.net/en/licensing.html
17 * Available at http://www.ossec.net
22 * Responsible for correlation and log decoding.
27 #define ARGV0 "ossec-testrule"
34 #include "alerts/alerts.h"
35 #include "alerts/getloglocation.h"
36 #include "os_execd/execd.h"
38 #include "os_regex/os_regex.h"
39 #include "os_net/os_net.h"
43 #include "active-response.h"
48 #include "eventinfo.h"
49 #include "analysisd.h"
53 /** Internal Functions **/
54 void OS_ReadMSG(int m_queue, char *ut_str);
55 RuleInfo *OS_CheckIfRuleMatch(Eventinfo *lf, RuleNode *curr_node);
58 /** External functions prototypes (only called here) **/
61 int GlobalConf(char * cfgfile);
65 void Rules_OP_CreateRules();
66 void Lists_OP_CreateLists();
67 int Rules_OP_ReadRules(char * cfgfile);
68 int _setlevels(RuleNode *node, int nnode);
69 int AddHash_Rule(RuleNode *node);
73 int OS_CleanMSG(char *msg, Eventinfo *lf);
78 int FTS(Eventinfo *lf);
79 int AddtoIGnore(Eventinfo *lf);
80 int IGnore(Eventinfo *lf);
84 void DecodeEvent(Eventinfo *lf);
85 int DecodeSyscheck(Eventinfo *lf);
86 int DecodeRootcheck(Eventinfo *lf);
87 int DecodeHostinfo(Eventinfo *lf);
91 int ReadDecodeXML(char *file);
97 /** int main(int argc, char **argv)
99 int main(int argc, char **argv)
102 int c = 0, m_queue = 0;
105 char *dir = DEFAULTDIR;
107 char *group = GROUPGLOBAL;
109 char *cfg = DEFAULTCPATH;
111 /* Setting the name */
120 active_responses = NULL;
121 memset(prev_month, '\0', 4);
123 while((c = getopt(argc, argv, "VatfdhU:u:g:D:c:")) != -1){
139 ErrorExit("%s: -U needs an argument",ARGV0);
144 ErrorExit("%s: -u needs an argument",ARGV0);
149 ErrorExit("%s: -g needs an argument",ARGV0);
154 ErrorExit("%s: -D needs an argument",ARGV0);
158 ErrorExit("%s: -c needs an argument",ARGV0);
177 /* Reading configuration file */
178 if(GlobalConf(cfg) < 0)
180 ErrorExit(CONFIG_ERROR,ARGV0, cfg);
183 debug1(READ_CONFIG, ARGV0);
187 /* Getting servers hostname */
188 memset(__shost, '\0', 512);
189 if(gethostname(__shost, 512 -1) != 0)
191 strncpy(__shost, OSSEC_SERVER, 512 -1);
197 /* Remove domain part if available */
198 _ltmp = strchr(__shost, '.');
206 ErrorExit(CHROOT_ERROR,ARGV0,dir);
210 * Anonymous Section: Load rules, decoders, and lists
212 * As lists require two pass loading of rules that make use of list lookups
213 * are created with blank database structs, and need to be filled in after
214 * completion of all rules and lists.
218 /* Initializing the decoders list */
219 OS_CreateOSDecoderList();
222 { /* Legacy loading */
223 /* Reading decoders */
224 if(!ReadDecodeXML("etc/decoder.xml"))
226 ErrorExit(CONFIG_ERROR, ARGV0, XML_DECODER);
229 /* Reading local ones. */
230 c = ReadDecodeXML("etc/local_decoder.xml");
234 ErrorExit(CONFIG_ERROR, ARGV0, XML_LDECODER);
238 verbose("%s: INFO: Reading local decoder file.", ARGV0);
242 { /* New loaded based on file speified in ossec.conf */
243 char **decodersfiles;
244 decodersfiles = Config.decoders;
245 while( decodersfiles && *decodersfiles)
248 verbose("%s: INFO: Reading decoder file %s.", ARGV0, *decodersfiles);
249 if(!ReadDecodeXML(*decodersfiles))
250 ErrorExit(CONFIG_ERROR, ARGV0, *decodersfiles);
252 free(*decodersfiles);
261 /* Initializing the lists of list struct */
262 Lists_OP_CreateLists();
263 /* Load each list into list struct */
266 listfiles = Config.lists;
267 while(listfiles && *listfiles)
269 verbose("%s: INFO: Reading loading the lists file: '%s'", ARGV0, *listfiles);
270 if(Lists_OP_LoadList(*listfiles) < 0)
271 ErrorExit(LISTS_ERROR, ARGV0, *listfiles);
280 /* Creating the rules list */
281 Rules_OP_CreateRules();
283 /* Reading the rules */
286 rulesfiles = Config.includes;
287 while(rulesfiles && *rulesfiles)
289 debug1("%s: INFO: Reading rules file: '%s'", ARGV0, *rulesfiles);
290 if(Rules_OP_ReadRules(*rulesfiles) < 0)
291 ErrorExit(RULES_ERROR, ARGV0, *rulesfiles);
297 free(Config.includes);
298 Config.includes = NULL;
301 /* Find all rules with that require list lookups and attache the
302 * the correct list struct to the rule. This keeps rules from having to
303 * search thought the list of lists for the correct file during rule evaluation.
310 /* Fixing the levels/accuracy */
313 RuleNode *tmp_node = OS_GetFirstRule();
315 total_rules = _setlevels(tmp_node, 0);
316 debug1("%s: INFO: Total rules enabled: '%d'", ARGV0, total_rules);
320 /* Creating a rules hash (for reading alerts from other servers). */
322 RuleNode *tmp_node = OS_GetFirstRule();
323 Config.g_rules_hash = OSHash_Create();
324 if(!Config.g_rules_hash)
326 ErrorExit(MEM_ERROR, ARGV0);
328 AddHash_Rule(tmp_node);
338 /* Start up message */
339 verbose(STARTUP_MSG, ARGV0, getpid());
342 /* Going to main loop */
343 OS_ReadMSG(m_queue, ut_str);
353 * Main function. Receives the messages(events)
354 * and analyze them all.
356 void OS_ReadMSG(int m_queue, char *ut_str)
359 char msg[OS_MAXSTR +1];
361 char *ut_alertlevel = NULL;
362 char *ut_rulelevel = NULL;
363 char *ut_decoder_name = NULL;
367 /* XXX Break apart string */
368 ut_rulelevel = ut_str;
369 ut_alertlevel = strchr(ut_rulelevel, ':');
372 ErrorExit("%s: -U requires the matching format to be "
373 "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
377 *ut_alertlevel = '\0';
380 ut_decoder_name = strchr(ut_alertlevel, ':');
383 ErrorExit("%s: -U requires the matching format to be "
384 "\"<rule_id>:<alert_level>:<decoder_name>\"", ARGV0);
388 *ut_decoder_name = '\0';
393 RuleInfoDetail *last_info_detail;
397 /* Null to global currently pointers */
398 currently_rule = NULL;
401 /* Creating the event list */
402 OS_CreateEventList(Config.memorysize);
405 /* Initiating the FTS list */
408 ErrorExit(FTS_LIST_ERROR, ARGV0);
415 /* Getting currently time before starting */
419 /* Doing some cleanup */
420 memset(msg, '\0', OS_MAXSTR +1);
424 print_out("%s: Type one log per line.\n", ARGV0);
430 lf = (Eventinfo *)calloc(1,sizeof(Eventinfo));
432 /* This shouldn't happen .. */
435 ErrorExit(MEM_ERROR,ARGV0);
439 /* Fixing the msg. */
440 snprintf(msg, 15, "1:stdin:");
444 /* Receive message from queue */
445 if(fgets(msg +8, OS_MAXSTR, stdin))
447 RuleNode *rulenode_pt;
449 /* Getting the time we received the event */
453 /* Removing new line. */
454 if(msg[strlen(msg) -1] == '\n')
455 msg[strlen(msg) -1] = '\0';
458 /* Make sure we ignore blank lines. */
465 if(!alert_only)print_out("\n");
468 /* Default values for the log info */
472 /* Clean the msg appropriately */
473 if(OS_CleanMSG(msg, lf) < 0)
475 merror(IMSG_ERROR,ARGV0,msg);
483 /* Currently rule must be null in here */
484 currently_rule = NULL;
487 /*** Running decoders ***/
489 /* Getting log size */
490 lf->size = strlen(lf->log);
493 /* Decoding event. */
497 /* Looping all the rules */
498 rulenode_pt = OS_GetFirstRule();
501 ErrorExit("%s: Rules in an inconsistent state. Exiting.",
507 if(full_output && !alert_only)
508 print_out("\n**Rule debugging:");
514 if(lf->decoder_info->type == OSSEC_ALERT)
516 if(!lf->generated_rule)
521 /* We go ahead in here and process the alert. */
522 currently_rule = lf->generated_rule;
525 /* The categories must match */
526 else if(rulenode_pt->ruleinfo->category !=
527 lf->decoder_info->type)
533 /* Checking each rule. */
534 else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt))
543 char *(ruleinfodetail_text[])={"Text","Link","CVE","OSVDB","BUGTRACKID"};
544 print_out("\n**Phase 3: Completed filtering (rules).");
545 print_out(" Rule id: '%d'", currently_rule->sigid);
546 print_out(" Level: '%d'", currently_rule->level);
547 print_out(" Description: '%s'",currently_rule->comment);
548 for (last_info_detail = currently_rule->info_details; last_info_detail != NULL; last_info_detail = last_info_detail->next)
550 print_out(" Info - %s: '%s'", ruleinfodetail_text[last_info_detail->type], last_info_detail->data);
558 if(currently_rule->level == 0)
564 /* Checking ignore time */
565 if(currently_rule->ignore_time)
567 if(currently_rule->time_ignored == 0)
569 currently_rule->time_ignored = lf->time;
571 /* If the currently time - the time the rule was ignored
572 * is less than the time it should be ignored,
573 * leave (do not alert again).
575 else if((lf->time - currently_rule->time_ignored)
576 < currently_rule->ignore_time)
582 currently_rule->time_ignored = 0;
586 /* Pointer to the rule that generated it */
587 lf->generated_rule = currently_rule;
590 /* Checking if we should ignore it */
591 if(currently_rule->ckignore && IGnore(lf))
594 lf->generated_rule = NULL;
598 /* Checking if we need to add to ignore list */
599 if(currently_rule->ignore)
605 /* Log the alert if configured to ... */
606 if(currently_rule->alert_opts & DO_LOGALERT)
615 print_out("**Alert to be generated.\n\n");
620 /* Copy the structure to the state memory of if_matched_sid */
621 if(currently_rule->sid_prev_matched)
623 if(!OSList_AddData(currently_rule->sid_prev_matched, lf))
625 merror("%s: Unable to add data to sig list.", ARGV0);
629 lf->sid_node_to_delete =
630 currently_rule->sid_prev_matched->last_node;
634 else if(currently_rule->group_prev_matched)
638 while(i < currently_rule->group_prev_matched_sz)
641 currently_rule->group_prev_matched[i],
644 merror("%s: Unable to add data to grp list.",ARGV0);
654 }while((rulenode_pt = rulenode_pt->next) != NULL);
658 /*setup exit code if we are doing unit testing*/
662 if(strcasecmp(ut_decoder_name, lf->decoder_info->name) == 0)
665 snprintf(holder, 1023, "%d", currently_rule->sigid);
666 if(strcasecmp(ut_rulelevel, holder) == 0)
669 snprintf(holder, 1023, "%d", currently_rule->level);
670 if(strcasecmp(ut_alertlevel, holder) == 0)
673 printf("%d\n",exit_code);
680 /* Only clear the memory if the eventinfo was not
681 * added to the stateful memory
682 * -- message is free inside clean event --
684 if(lf->generated_rule == NULL)