1 /* @(#) $Id: rules.c,v 1.79 2009/11/04 18:45:37 dcid Exp $ */
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 3) 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
19 #include "eventinfo.h"
20 #include "compiled_rules/compiled_rules.h"
23 /* Chaging path for test rule. */
26 #define RULEPATH "rules/"
31 /* Internal functions */
32 int getattributes(char **attributes,
35 int *maxsize, int *timeframe,
36 int *frequency, int *accuracy,
37 int *noalert, int *ignore_time, int *overwrite);
40 void Rule_AddAR(RuleInfo *config_rule);
41 char *loadmemory(char *at, char *str);
42 int getDecoderfromlist(char *name);
48 /* Rules_OP_ReadRules, v0.1, 2005/07/04
49 * Will initialize the rules list
51 void Rules_OP_CreateRules()
54 /* Initializing the rule list */
62 /* Rules_OP_ReadRules, v0.3, 2005/03/21
64 * v0.3: Fixed many memory problems.
66 int Rules_OP_ReadRules(char * rulefile)
72 /* These are the available options for the rule configuration */
74 char *xml_group = "group";
75 char *xml_rule = "rule";
77 char *xml_regex = "regex";
78 char *xml_match = "match";
79 char *xml_decoded = "decoded_as";
80 char *xml_category = "category";
81 char *xml_cve = "cve";
82 char *xml_info = "info";
83 char *xml_day_time = "time";
84 char *xml_week_day = "weekday";
85 char *xml_comment = "description";
86 char *xml_ignore = "ignore";
87 char *xml_check_if_ignored = "check_if_ignored";
89 char *xml_srcip = "srcip";
90 char *xml_srcport = "srcport";
91 char *xml_dstip = "dstip";
92 char *xml_dstport = "dstport";
93 char *xml_user = "user";
94 char *xml_url = "url";
96 char *xml_data = "extra_data";
97 char *xml_hostname = "hostname";
98 char *xml_program_name = "program_name";
99 char *xml_status = "status";
100 char *xml_action = "action";
101 char *xml_compiled = "compiled_rule";
103 char *xml_if_sid = "if_sid";
104 char *xml_if_group = "if_group";
105 char *xml_if_level = "if_level";
106 char *xml_fts = "if_fts";
108 char *xml_if_matched_regex = "if_matched_regex";
109 char *xml_if_matched_group = "if_matched_group";
110 char *xml_if_matched_sid = "if_matched_sid";
112 char *xml_same_source_ip = "same_source_ip";
113 char *xml_same_src_port = "same_src_port";
114 char *xml_same_dst_port = "same_dst_port";
115 char *xml_same_user = "same_user";
116 char *xml_same_location = "same_location";
117 char *xml_same_id = "same_id";
119 char *xml_different_url = "different_url";
121 char *xml_notsame_source_ip = "not_same_source_ip";
122 char *xml_notsame_user = "not_same_user";
123 char *xml_notsame_agent = "not_same_agent";
124 char *xml_notsame_id = "not_same_id";
126 char *xml_options = "options";
131 int default_timeframe = 360;
134 /* Building the rule file name + path */
135 i = strlen(RULEPATH) + strlen(rulefile) + 2;
136 rulepath = (char *)calloc(i,sizeof(char));
139 ErrorExit(MEM_ERROR,ARGV0);
142 snprintf(rulepath,i,"%s/%s",RULEPATH,rulefile);
146 /* Reading the XML */
147 if(OS_ReadXML(rulepath,&xml) < 0)
149 merror(XML_ERROR, ARGV0, rulepath, xml.err, xml.err_line);
156 debug2("%s: DEBUG: read xml for rule.", ARGV0);
160 /* Applying any variable found */
161 if(OS_ApplyVariables(&xml) != 0)
163 merror(XML_ERROR_VAR, ARGV0, rulepath, xml.err);
169 debug2("%s: DEBUG: XML Variables applied.", ARGV0);
172 /* Getting the root elements */
173 node = OS_GetElementsbyNode(&xml,NULL);
176 merror(CONFIG_ERROR, ARGV0, rulepath);
182 /* Zeroing the rule memory -- not used anymore */
186 /* Getting default time frame */
187 default_timeframe = getDefine_Int("analysisd",
192 /* Checking if there is any invalid global option */
197 if(strcasecmp(node[i]->element,xml_group) != 0)
199 merror("rules_op: Invalid root element \"%s\"."
200 "Only \"group\" is allowed",node[i]->element);
204 if((!node[i]->attributes) || (!node[i]->values)||
205 (!node[i]->values[0]) || (!node[i]->attributes[0]) ||
206 (strcasecmp(node[i]->attributes[0],"name") != 0) ||
207 (node[i]->attributes[1]))
209 merror("rules_op: Invalid root element '%s'."
210 "Only the group name is allowed",node[i]->element);
217 merror(XML_READ_ERROR, ARGV0);
225 /* Getting the rules now */
229 XML_NODE rule = NULL;
233 /* Getting all rules for a global group */
234 rule = OS_GetElementsbyNode(&xml,node[i]);
237 merror("%s: Group '%s' without any rule.",
238 ARGV0, node[i]->element);
245 RuleInfo *config_ruleinfo = NULL;
248 /* Checking if the rule element is correct */
249 if((!rule[j]->element)||
250 (strcasecmp(rule[j]->element,xml_rule) != 0))
252 merror("%s: Invalid configuration. '%s' is not "
253 "a valid element.", ARGV0, rule[j]->element);
259 /* Checking for the attributes of the rule */
260 if((!rule[j]->attributes) || (!rule[j]->values))
262 merror("%s: Invalid rule '%d'. You must specify"
263 " an ID and a level at least.", ARGV0, j);
269 /* Attribute block */
271 int id = -1,level = -1,maxsize = 0,timeframe = 0;
272 int frequency = 0, accuracy = 1, noalert = 0, ignore_time = 0;
275 /* Getting default time frame */
276 timeframe = default_timeframe;
279 if(getattributes(rule[j]->attributes,rule[j]->values,
280 &id,&level,&maxsize,&timeframe,
281 &frequency,&accuracy,&noalert,
282 &ignore_time, &overwrite) < 0)
284 merror("%s: Invalid attribute for rule.", ARGV0);
289 if((id == -1) || (level == -1))
291 merror("%s: No rule id or level specified for "
292 "rule '%d'.",ARGV0, j);
297 /* Allocating memory and initializing structure */
298 config_ruleinfo = zerorulemember(id, level, maxsize,
300 noalert, ignore_time, overwrite);
303 /* If rule is 0, set it to level 99 to have high priority.
304 * set it to 0 again later
306 if(config_ruleinfo->level == 0)
307 config_ruleinfo->level = 99;
310 /* Each level now is going to be multiplied by 100.
311 * If the accuracy is set to 0 we don't multiply,
312 * so it will be at the end of the list. We will
313 * divide by 100 later.
317 config_ruleinfo->level *= 100;
320 if(config_ruleinfo->maxsize > 0)
322 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
324 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
328 } /* end attributes/memory allocation block */
331 /* Here we can assign the group name to the rule.
332 * The level is correct so the rule is probably going to
335 os_strdup(node[i]->values[0], config_ruleinfo->group);
338 /* Rule elements block */
344 char *if_matched_regex = NULL;
345 char *if_matched_group = NULL;
348 char *srcport = NULL;
349 char *dstport = NULL;
351 char *hostname = NULL;
352 char *extra_data = NULL;
353 char *program_name = NULL;
355 XML_NODE rule_opt = NULL;
356 rule_opt = OS_GetElementsbyNode(&xml,rule[j]);
359 merror("%s: Rule '%d' without any option. "
360 "It may lead to false positives and some "
361 "other problems for the system. Exiting.",
362 ARGV0, config_ruleinfo->sigid);
369 if((!rule_opt[k]->element)||(!rule_opt[k]->content))
371 else if(strcasecmp(rule_opt[k]->element,xml_regex)==0)
375 rule_opt[k]->content);
377 else if(strcasecmp(rule_opt[k]->element,xml_match)==0)
381 rule_opt[k]->content);
383 else if(strcasecmp(rule_opt[k]->element, xml_decoded)==0)
385 config_ruleinfo->decoded_as =
386 getDecoderfromlist(rule_opt[k]->content);
388 if(config_ruleinfo->decoded_as == 0)
390 merror("%s: Invalid decoder name: '%s'.",
391 ARGV0, rule_opt[k]->content);
396 else if(strcasecmp(rule_opt[k]->element,xml_info)==0)
398 config_ruleinfo->info=
399 loadmemory(config_ruleinfo->info,
400 rule_opt[k]->content);
402 else if(strcasecmp(rule_opt[k]->element,xml_day_time)==0)
404 config_ruleinfo->day_time =
405 OS_IsValidTime(rule_opt[k]->content);
406 if(!config_ruleinfo->day_time)
408 merror(INVALID_CONFIG, ARGV0,
409 rule_opt[k]->element,
410 rule_opt[k]->content);
414 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
415 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
417 else if(strcasecmp(rule_opt[k]->element,xml_week_day)==0)
419 config_ruleinfo->week_day =
420 OS_IsValidDay(rule_opt[k]->content);
422 if(!config_ruleinfo->week_day)
424 merror(INVALID_CONFIG, ARGV0,
425 rule_opt[k]->element,
426 rule_opt[k]->content);
429 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
430 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
432 else if(strcasecmp(rule_opt[k]->element,xml_group)==0)
434 config_ruleinfo->group =
435 loadmemory(config_ruleinfo->group,
436 rule_opt[k]->content);
438 else if(strcasecmp(rule_opt[k]->element,xml_cve)==0)
440 config_ruleinfo->cve=
441 loadmemory(config_ruleinfo->cve,
442 rule_opt[k]->content);
444 else if(strcasecmp(rule_opt[k]->element,xml_comment)==0)
448 newline = strchr(rule_opt[k]->content, '\n');
454 config_ruleinfo->comment=
455 loadmemory(config_ruleinfo->comment,
456 rule_opt[k]->content);
458 else if(strcasecmp(rule_opt[k]->element,xml_srcip)==0)
462 /* Getting size of source ip list */
463 while(config_ruleinfo->srcip &&
464 config_ruleinfo->srcip[ip_s])
469 config_ruleinfo->srcip =
470 realloc(config_ruleinfo->srcip,
471 (ip_s + 2) * sizeof(os_ip *));
474 /* Allocating memory for the individual entries */
475 os_calloc(1, sizeof(os_ip),
476 config_ruleinfo->srcip[ip_s]);
477 config_ruleinfo->srcip[ip_s +1] = NULL;
480 /* Checking if the ip is valid */
481 if(!OS_IsValidIP(rule_opt[k]->content,
482 config_ruleinfo->srcip[ip_s]))
484 merror(INVALID_IP, ARGV0, rule_opt[k]->content);
488 if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
489 config_ruleinfo->alert_opts |= DO_PACKETINFO;
491 else if(strcasecmp(rule_opt[k]->element,xml_dstip)==0)
495 /* Getting size of source ip list */
496 while(config_ruleinfo->dstip &&
497 config_ruleinfo->dstip[ip_s])
502 config_ruleinfo->dstip =
503 realloc(config_ruleinfo->dstip,
504 (ip_s + 2) * sizeof(os_ip *));
507 /* Allocating memory for the individual entries */
508 os_calloc(1, sizeof(os_ip),
509 config_ruleinfo->dstip[ip_s]);
510 config_ruleinfo->dstip[ip_s +1] = NULL;
513 /* Checking if the ip is valid */
514 if(!OS_IsValidIP(rule_opt[k]->content,
515 config_ruleinfo->dstip[ip_s]))
517 merror(INVALID_IP, ARGV0, rule_opt[k]->content);
521 if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
522 config_ruleinfo->alert_opts |= DO_PACKETINFO;
524 else if(strcasecmp(rule_opt[k]->element,xml_user)==0)
528 rule_opt[k]->content);
530 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
531 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
533 else if(strcasecmp(rule_opt[k]->element,xml_id)==0)
537 rule_opt[k]->content);
539 else if(strcasecmp(rule_opt[k]->element,xml_srcport)==0)
543 rule_opt[k]->content);
544 if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
545 config_ruleinfo->alert_opts |= DO_PACKETINFO;
547 else if(strcasecmp(rule_opt[k]->element,xml_dstport)==0)
551 rule_opt[k]->content);
553 if(!(config_ruleinfo->alert_opts & DO_PACKETINFO))
554 config_ruleinfo->alert_opts |= DO_PACKETINFO;
556 else if(strcasecmp(rule_opt[k]->element,xml_status)==0)
560 rule_opt[k]->content);
562 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
563 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
565 else if(strcasecmp(rule_opt[k]->element,xml_hostname)==0)
569 rule_opt[k]->content);
571 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
572 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
574 else if(strcasecmp(rule_opt[k]->element,xml_data)==0)
577 loadmemory(extra_data,
578 rule_opt[k]->content);
580 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
581 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
583 else if(strcasecmp(rule_opt[k]->element,
584 xml_program_name)==0)
587 loadmemory(program_name,
588 rule_opt[k]->content);
590 else if(strcasecmp(rule_opt[k]->element,xml_action)==0)
592 config_ruleinfo->action =
593 loadmemory(config_ruleinfo->action,
594 rule_opt[k]->content);
596 else if(strcasecmp(rule_opt[k]->element,xml_url)==0)
600 rule_opt[k]->content);
602 else if(strcasecmp(rule_opt[k]->element, xml_compiled)==0)
606 while(compiled_rules_name[it_id])
608 if(strcmp(compiled_rules_name[it_id],
609 rule_opt[k]->content) == 0)
614 /* checking if the name is valid. */
615 if(!compiled_rules_name[it_id])
617 merror("%s: ERROR: Compiled rule not found: '%s'",
618 ARGV0, rule_opt[k]->content);
619 merror(INVALID_CONFIG, ARGV0,
620 rule_opt[k]->element, rule_opt[k]->content);
625 config_ruleinfo->compiled_rule = compiled_rules_list[it_id];
626 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
627 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
630 /* We allow these four categories so far */
631 else if(strcasecmp(rule_opt[k]->element, xml_category)==0)
633 if(strcmp(rule_opt[k]->content, "firewall") == 0)
635 config_ruleinfo->category = FIREWALL;
637 else if(strcmp(rule_opt[k]->content, "ids") == 0)
639 config_ruleinfo->category = IDS;
641 else if(strcmp(rule_opt[k]->content, "syslog") == 0)
643 config_ruleinfo->category = SYSLOG;
645 else if(strcmp(rule_opt[k]->content, "web-log") == 0)
647 config_ruleinfo->category = WEBLOG;
649 else if(strcmp(rule_opt[k]->content, "squid") == 0)
651 config_ruleinfo->category = SQUID;
653 else if(strcmp(rule_opt[k]->content,"windows") == 0)
655 config_ruleinfo->category = WINDOWS;
657 else if(strcmp(rule_opt[k]->content,"ossec") == 0)
659 config_ruleinfo->category = OSSEC_RL;
663 merror(INVALID_CAT, ARGV0, rule_opt[k]->content);
667 else if(strcasecmp(rule_opt[k]->element,xml_if_sid)==0)
669 config_ruleinfo->if_sid=
670 loadmemory(config_ruleinfo->if_sid,
671 rule_opt[k]->content);
673 else if(strcasecmp(rule_opt[k]->element,xml_if_level)==0)
675 if(!OS_StrIsNum(rule_opt[k]->content))
677 merror(INVALID_CONFIG, ARGV0,
679 rule_opt[k]->content);
683 config_ruleinfo->if_level=
684 loadmemory(config_ruleinfo->if_level,
685 rule_opt[k]->content);
687 else if(strcasecmp(rule_opt[k]->element,xml_if_group)==0)
689 config_ruleinfo->if_group=
690 loadmemory(config_ruleinfo->if_group,
691 rule_opt[k]->content);
693 else if(strcasecmp(rule_opt[k]->element,
694 xml_if_matched_regex) == 0)
696 config_ruleinfo->context = 1;
698 loadmemory(if_matched_regex,
699 rule_opt[k]->content);
701 else if(strcasecmp(rule_opt[k]->element,
702 xml_if_matched_group) == 0)
704 config_ruleinfo->context = 1;
706 loadmemory(if_matched_group,
707 rule_opt[k]->content);
709 else if(strcasecmp(rule_opt[k]->element,
710 xml_if_matched_sid) == 0)
712 config_ruleinfo->context = 1;
713 if(!OS_StrIsNum(rule_opt[k]->content))
715 merror(INVALID_CONFIG, ARGV0,
717 rule_opt[k]->content);
720 config_ruleinfo->if_matched_sid =
721 atoi(rule_opt[k]->content);
724 else if(strcasecmp(rule_opt[k]->element,
725 xml_same_source_ip)==0)
727 config_ruleinfo->context_opts|= SAME_SRCIP;
729 else if(strcasecmp(rule_opt[k]->element,
730 xml_same_src_port)==0)
732 config_ruleinfo->context_opts|= SAME_SRCPORT;
734 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
735 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
737 else if(strcasecmp(rule_opt[k]->element,
738 xml_same_dst_port) == 0)
740 config_ruleinfo->context_opts|= SAME_DSTPORT;
742 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
743 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
745 else if(strcasecmp(rule_opt[k]->element,
746 xml_notsame_source_ip)==0)
748 config_ruleinfo->context_opts&= NOT_SAME_SRCIP;
750 else if(strcmp(rule_opt[k]->element, xml_same_id) == 0)
752 config_ruleinfo->context_opts|= SAME_ID;
754 else if(strcmp(rule_opt[k]->element,
755 xml_different_url) == 0)
757 config_ruleinfo->context_opts|= DIFFERENT_URL;
759 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
760 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
762 else if(strcmp(rule_opt[k]->element,xml_notsame_id) == 0)
764 config_ruleinfo->context_opts&= NOT_SAME_ID;
766 else if(strcasecmp(rule_opt[k]->element,
769 config_ruleinfo->alert_opts |= DO_FTS;
771 else if(strcasecmp(rule_opt[k]->element,
774 config_ruleinfo->context_opts|= SAME_USER;
776 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
777 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
779 else if(strcasecmp(rule_opt[k]->element,
780 xml_notsame_user)==0)
782 config_ruleinfo->context_opts&= NOT_SAME_USER;
784 else if(strcasecmp(rule_opt[k]->element,
785 xml_same_location)==0)
787 config_ruleinfo->context_opts|= SAME_LOCATION;
788 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
789 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
791 else if(strcasecmp(rule_opt[k]->element,
792 xml_notsame_agent)==0)
794 config_ruleinfo->context_opts&= NOT_SAME_AGENT;
796 else if(strcasecmp(rule_opt[k]->element,
799 if(strcmp("alert_by_email",
800 rule_opt[k]->content) == 0)
802 if(!(config_ruleinfo->alert_opts & DO_MAILALERT))
804 config_ruleinfo->alert_opts|= DO_MAILALERT;
807 else if(strcmp("no_email_alert",
808 rule_opt[k]->content) == 0)
810 if(config_ruleinfo->alert_opts & DO_MAILALERT)
812 config_ruleinfo->alert_opts&=0xfff-DO_MAILALERT;
815 else if(strcmp("log_alert",
816 rule_opt[k]->content) == 0)
818 if(!(config_ruleinfo->alert_opts & DO_LOGALERT))
820 config_ruleinfo->alert_opts|= DO_LOGALERT;
823 else if(strcmp("no_log", rule_opt[k]->content) == 0)
825 if(config_ruleinfo->alert_opts & DO_LOGALERT)
827 config_ruleinfo->alert_opts &=0xfff-DO_LOGALERT;
832 merror(XML_VALUEERR, ARGV0, xml_options,
833 rule_opt[k]->content);
835 merror("%s: Invalid option '%s' for "
836 "rule '%d'.",ARGV0, rule_opt[k]->element,
837 config_ruleinfo->sigid);
842 else if(strcasecmp(rule_opt[k]->element,
845 if(strstr(rule_opt[k]->content, "user") != NULL)
847 config_ruleinfo->ignore|=FTS_DSTUSER;
849 if(strstr(rule_opt[k]->content, "srcip") != NULL)
851 config_ruleinfo->ignore|=FTS_SRCIP;
853 if(strstr(rule_opt[k]->content, "dstip") != NULL)
855 config_ruleinfo->ignore|=FTS_DSTIP;
857 if(strstr(rule_opt[k]->content, "id") != NULL)
859 config_ruleinfo->ignore|=FTS_ID;
861 if(strstr(rule_opt[k]->content,"location")!= NULL)
863 config_ruleinfo->ignore|=FTS_LOCATION;
865 if(strstr(rule_opt[k]->content,"data")!= NULL)
867 config_ruleinfo->ignore|=FTS_DATA;
869 if(strstr(rule_opt[k]->content, "name") != NULL)
871 config_ruleinfo->ignore|=FTS_NAME;
874 if(!config_ruleinfo->ignore)
876 merror("%s: Wrong ignore option: '%s'",
878 rule_opt[k]->content);
882 else if(strcasecmp(rule_opt[k]->element,
883 xml_check_if_ignored) == 0)
885 if(strstr(rule_opt[k]->content, "user") != NULL)
887 config_ruleinfo->ckignore|=FTS_DSTUSER;
889 if(strstr(rule_opt[k]->content, "srcip") != NULL)
891 config_ruleinfo->ckignore|=FTS_SRCIP;
893 if(strstr(rule_opt[k]->content, "dstip") != NULL)
895 config_ruleinfo->ckignore|=FTS_DSTIP;
897 if(strstr(rule_opt[k]->content, "id") != NULL)
899 config_ruleinfo->ckignore|=FTS_ID;
901 if(strstr(rule_opt[k]->content,"location")!= NULL)
903 config_ruleinfo->ckignore|=FTS_LOCATION;
905 if(strstr(rule_opt[k]->content,"data")!= NULL)
907 config_ruleinfo->ignore|=FTS_DATA;
909 if(strstr(rule_opt[k]->content, "name") != NULL)
911 config_ruleinfo->ckignore|=FTS_NAME;
914 if(!config_ruleinfo->ckignore)
916 merror("%s: Wrong check_if_ignored option: '%s'",
918 rule_opt[k]->content);
924 merror("%s: Invalid option '%s' for "
925 "rule '%d'.",ARGV0, rule_opt[k]->element,
926 config_ruleinfo->sigid);
934 /* Checking for a valid use of frequency */
935 if((config_ruleinfo->context_opts ||
936 config_ruleinfo->frequency) &&
937 !config_ruleinfo->context)
939 merror("%s: Invalid use of frequency/context options. "
940 "Missing if_matched on rule '%d'.",
941 ARGV0, config_ruleinfo->sigid);
947 /* If if_matched_group we must have a if_sid or if_group */
950 if(!config_ruleinfo->if_sid && !config_ruleinfo->if_group)
952 os_strdup(if_matched_group,
953 config_ruleinfo->if_group);
957 /* If_matched_sid, we need to get the if_sid */
958 if(config_ruleinfo->if_matched_sid &&
959 !config_ruleinfo->if_sid &&
960 !config_ruleinfo->if_group)
962 os_calloc(16, sizeof(char), config_ruleinfo->if_sid);
963 snprintf(config_ruleinfo->if_sid, 15, "%d",
964 config_ruleinfo->if_matched_sid);
967 /* Checking the regexes */
970 os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex);
971 if(!OSRegex_Compile(regex, config_ruleinfo->regex, 0))
973 merror(REGEX_COMPILE, ARGV0, regex,
974 config_ruleinfo->regex->error);
981 /* Adding in match */
984 os_calloc(1, sizeof(OSMatch), config_ruleinfo->match);
985 if(!OSMatch_Compile(match, config_ruleinfo->match, 0))
987 merror(REGEX_COMPILE, ARGV0, match,
988 config_ruleinfo->match->error);
998 os_calloc(1, sizeof(OSMatch), config_ruleinfo->id);
999 if(!OSMatch_Compile(id, config_ruleinfo->id, 0))
1001 merror(REGEX_COMPILE, ARGV0, id,
1002 config_ruleinfo->id->error);
1009 /* Adding srcport */
1012 os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport);
1013 if(!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0))
1015 merror(REGEX_COMPILE, ARGV0, srcport,
1016 config_ruleinfo->id->error);
1023 /* Adding dstport */
1026 os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport);
1027 if(!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0))
1029 merror(REGEX_COMPILE, ARGV0, dstport,
1030 config_ruleinfo->id->error);
1037 /* Adding in status */
1040 os_calloc(1, sizeof(OSMatch), config_ruleinfo->status);
1041 if(!OSMatch_Compile(status, config_ruleinfo->status, 0))
1043 merror(REGEX_COMPILE, ARGV0, status,
1044 config_ruleinfo->status->error);
1051 /* Adding in hostname */
1054 os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname);
1055 if(!OSMatch_Compile(hostname, config_ruleinfo->hostname,0))
1057 merror(REGEX_COMPILE, ARGV0, hostname,
1058 config_ruleinfo->hostname->error);
1065 /* Adding extra data */
1068 os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data);
1069 if(!OSMatch_Compile(extra_data,
1070 config_ruleinfo->extra_data, 0))
1072 merror(REGEX_COMPILE, ARGV0, extra_data,
1073 config_ruleinfo->extra_data->error);
1080 /* Adding in program name */
1083 os_calloc(1,sizeof(OSMatch),config_ruleinfo->program_name);
1084 if(!OSMatch_Compile(program_name,
1085 config_ruleinfo->program_name,0))
1087 merror(REGEX_COMPILE, ARGV0, program_name,
1088 config_ruleinfo->program_name->error);
1092 program_name = NULL;
1095 /* Adding in user */
1098 os_calloc(1, sizeof(OSMatch), config_ruleinfo->user);
1099 if(!OSMatch_Compile(user, config_ruleinfo->user, 0))
1101 merror(REGEX_COMPILE, ARGV0, user,
1102 config_ruleinfo->user->error);
1112 os_calloc(1, sizeof(OSMatch), config_ruleinfo->url);
1113 if(!OSMatch_Compile(url, config_ruleinfo->url, 0))
1115 merror(REGEX_COMPILE, ARGV0, url,
1116 config_ruleinfo->url->error);
1123 /* Adding matched_group */
1124 if(if_matched_group)
1126 os_calloc(1, sizeof(OSMatch),
1127 config_ruleinfo->if_matched_group);
1129 if(!OSMatch_Compile(if_matched_group,
1130 config_ruleinfo->if_matched_group,
1133 merror(REGEX_COMPILE, ARGV0, if_matched_group,
1134 config_ruleinfo->if_matched_group->error);
1137 free(if_matched_group);
1138 if_matched_group = NULL;
1141 /* Adding matched_regex */
1142 if(if_matched_regex)
1144 os_calloc(1, sizeof(OSRegex),
1145 config_ruleinfo->if_matched_regex);
1146 if(!OSRegex_Compile(if_matched_regex,
1147 config_ruleinfo->if_matched_regex, 0))
1149 merror(REGEX_COMPILE, ARGV0, if_matched_regex,
1150 config_ruleinfo->if_matched_regex->error);
1153 free(if_matched_regex);
1154 if_matched_regex = NULL;
1156 } /* enf of elements block */
1159 /* Assigning an active response to the rule */
1160 Rule_AddAR(config_ruleinfo);
1162 j++; /* next rule */
1165 /* Creating the last_events if necessary */
1166 if(config_ruleinfo->context)
1169 os_calloc(MAX_LAST_EVENTS + 1, sizeof(char *),
1170 config_ruleinfo->last_events);
1172 /* Zeroing each entry */
1173 for(;ii<=MAX_LAST_EVENTS;ii++)
1175 config_ruleinfo->last_events[ii] = NULL;
1180 /* Adding the rule to the rules list.
1181 * Only the template rules are supposed
1182 * to be at the top level. All others
1183 * will be a "child" of someone.
1185 if(config_ruleinfo->sigid < 10)
1187 OS_AddRule(config_ruleinfo);
1189 else if(config_ruleinfo->alert_opts & DO_OVERWRITE)
1191 if(!OS_AddRuleInfo(NULL, config_ruleinfo,
1192 config_ruleinfo->sigid))
1194 merror("%s: Overwrite rule '%d' not found.",
1195 ARGV0, config_ruleinfo->sigid);
1202 OS_AddChild(config_ruleinfo);
1205 /* Cleaning what we do not need */
1206 if(config_ruleinfo->if_group)
1208 free(config_ruleinfo->if_group);
1209 config_ruleinfo->if_group = NULL;
1212 /* Setting the event_search pointer */
1213 if(config_ruleinfo->if_matched_sid)
1215 config_ruleinfo->event_search =
1216 (void *)Search_LastSids;
1218 /* Marking rules that match this id */
1219 OS_MarkID(NULL, config_ruleinfo);
1222 /* Marking the rules that match if_matched_group */
1223 else if(config_ruleinfo->if_matched_group)
1226 config_ruleinfo->group_search = OSList_Create();
1227 if(!config_ruleinfo->group_search)
1229 ErrorExit(MEM_ERROR, ARGV0);
1232 /* Marking rules that match this group */
1233 OS_MarkGroup(NULL, config_ruleinfo);
1235 /* Setting function pointer */
1236 config_ruleinfo->event_search =
1237 (void *)Search_LastGroups;
1239 else if(config_ruleinfo->context)
1241 config_ruleinfo->event_search =
1242 (void *)Search_LastEvents;
1245 } /* while(rule[j]) */
1249 } /* while (node[i]) */
1251 /* Cleaning global node */
1257 RuleNode *dbg_node = OS_GetFirstRule();
1262 RuleNode *child_node = dbg_node->child;
1264 printf("** Child Node for %d **\n",dbg_node->ruleinfo->sigid);
1267 child_node = child_node->next;
1270 dbg_node = dbg_node->next;
1275 /* Done over here */
1281 * Allocate memory at "*at" and copy *str to it.
1282 * If *at already exist, realloc the memory and cat str
1284 * It will return the new string
1286 char *loadmemory(char *at, char *str)
1291 if((strsize = strlen(str)) < OS_SIZE_2048)
1293 at = calloc(strsize+1,sizeof(char));
1296 merror(MEM_ERROR,ARGV0);
1299 strncpy(at,str,strsize);
1304 merror(SIZE_ERROR,ARGV0,str);
1308 else /*at is not null. Need to reallocat its memory and copy str to it*/
1310 int strsize = strlen(str);
1311 int atsize = strlen(at);
1312 int finalsize = atsize+strsize+1;
1314 if((atsize > OS_SIZE_2048) || (strsize > OS_SIZE_2048))
1316 merror(SIZE_ERROR,ARGV0,str);
1320 at = realloc(at, (finalsize)*sizeof(char));
1324 merror(MEM_ERROR,ARGV0);
1328 strncat(at,str,strsize);
1330 at[finalsize-1]='\0';
1338 RuleInfo *zerorulemember(int id, int level,
1339 int maxsize, int frequency,
1340 int timeframe, int noalert,
1341 int ignore_time, int overwrite)
1343 RuleInfo *ruleinfo_pt = NULL;
1345 /* Allocation memory for structure */
1346 ruleinfo_pt = (RuleInfo *)calloc(1,sizeof(RuleInfo));
1348 if(ruleinfo_pt == NULL)
1350 ErrorExit(MEM_ERROR,ARGV0);
1353 /* Default values */
1354 ruleinfo_pt->level = level;
1356 /* Default category is syslog */
1357 ruleinfo_pt->category = SYSLOG;
1359 ruleinfo_pt->ar = NULL;
1361 ruleinfo_pt->context = 0;
1363 ruleinfo_pt->sigid = id;
1364 ruleinfo_pt->firedtimes = 0;
1365 ruleinfo_pt->maxsize = maxsize;
1366 ruleinfo_pt->frequency = frequency;
1367 if(ruleinfo_pt->frequency > _max_freq)
1369 _max_freq = ruleinfo_pt->frequency;
1371 ruleinfo_pt->ignore_time = ignore_time;
1372 ruleinfo_pt->timeframe = timeframe;
1373 ruleinfo_pt->time_ignored = 0;
1375 ruleinfo_pt->context_opts = 0;
1376 ruleinfo_pt->alert_opts = 0;
1377 ruleinfo_pt->ignore = 0;
1378 ruleinfo_pt->ckignore = 0;
1382 ruleinfo_pt->alert_opts |= NO_ALERT;
1384 if(Config.mailbylevel <= level)
1385 ruleinfo_pt->alert_opts |= DO_MAILALERT;
1386 if(Config.logbylevel <= level)
1387 ruleinfo_pt->alert_opts |= DO_LOGALERT;
1389 /* Overwriting a rule */
1392 ruleinfo_pt->alert_opts |= DO_OVERWRITE;
1395 ruleinfo_pt->day_time = NULL;
1396 ruleinfo_pt->week_day = NULL;
1398 ruleinfo_pt->group = NULL;
1399 ruleinfo_pt->regex = NULL;
1400 ruleinfo_pt->match = NULL;
1401 ruleinfo_pt->decoded_as = 0;
1403 ruleinfo_pt->comment = NULL;
1404 ruleinfo_pt->info = NULL;
1405 ruleinfo_pt->cve = NULL;
1407 ruleinfo_pt->if_sid = NULL;
1408 ruleinfo_pt->if_group = NULL;
1409 ruleinfo_pt->if_level = NULL;
1411 ruleinfo_pt->if_matched_regex = NULL;
1412 ruleinfo_pt->if_matched_group = NULL;
1413 ruleinfo_pt->if_matched_sid = 0;
1415 ruleinfo_pt->user = NULL;
1416 ruleinfo_pt->srcip = NULL;
1417 ruleinfo_pt->srcport = NULL;
1418 ruleinfo_pt->dstip = NULL;
1419 ruleinfo_pt->dstport = NULL;
1420 ruleinfo_pt->url = NULL;
1421 ruleinfo_pt->id = NULL;
1422 ruleinfo_pt->status = NULL;
1423 ruleinfo_pt->hostname = NULL;
1424 ruleinfo_pt->program_name = NULL;
1425 ruleinfo_pt->action = NULL;
1427 /* Zeroing last matched events */
1428 ruleinfo_pt->__frequency = 0;
1429 ruleinfo_pt->last_events = NULL;
1431 /* zeroing the list of previous matches */
1432 ruleinfo_pt->sid_prev_matched = NULL;
1433 ruleinfo_pt->group_prev_matched = NULL;
1435 ruleinfo_pt->sid_search = NULL;
1436 ruleinfo_pt->group_search = NULL;
1438 ruleinfo_pt->event_search = NULL;
1439 ruleinfo_pt->compiled_rule = NULL;
1441 return(ruleinfo_pt);
1445 /* Get the attributes */
1446 int getattributes(char **attributes, char **values,
1447 int *id, int *level,
1448 int *maxsize, int *timeframe,
1449 int *frequency, int *accuracy,
1450 int *noalert, int *ignore_time, int *overwrite)
1454 char *xml_id = "id";
1455 char *xml_level = "level";
1456 char *xml_maxsize = "maxsize";
1457 char *xml_timeframe = "timeframe";
1458 char *xml_frequency = "frequency";
1459 char *xml_accuracy = "accuracy";
1460 char *xml_noalert = "noalert";
1461 char *xml_ignore_time = "ignore";
1462 char *xml_overwrite = "overwrite";
1465 /* Getting attributes */
1466 while(attributes[k])
1470 merror("rules_op: Attribute \"%s\" without value."
1474 /* Getting rule Id */
1475 else if(strcasecmp(attributes[k],xml_id) == 0)
1477 if(OS_StrIsNum(values[k]))
1479 sscanf(values[k],"%6d",id);
1483 merror("rules_op: Invalid rule id: %s. "
1490 else if(strcasecmp(attributes[k],xml_level) == 0)
1492 if(OS_StrIsNum(values[k]))
1494 sscanf(values[k],"%4d",level);
1498 merror("rules_op: Invalid level: %s. "
1504 /* Getting maxsize */
1505 else if(strcasecmp(attributes[k],xml_maxsize) == 0)
1507 if(OS_StrIsNum(values[k]))
1509 sscanf(values[k],"%4d",maxsize);
1513 merror("rules_op: Invalid maxsize: %s. "
1519 /* Getting timeframe */
1520 else if(strcasecmp(attributes[k],xml_timeframe) == 0)
1522 if(OS_StrIsNum(values[k]))
1524 sscanf(values[k],"%5d",timeframe);
1528 merror("rules_op: Invalid timeframe: %s. "
1534 /* Getting frequency */
1535 else if(strcasecmp(attributes[k],xml_frequency) == 0)
1537 if(OS_StrIsNum(values[k]))
1539 sscanf(values[k],"%4d",frequency);
1543 merror("rules_op: Invalid frequency: %s. "
1550 else if(strcasecmp(attributes[k],xml_accuracy) == 0)
1552 if(OS_StrIsNum(values[k]))
1554 sscanf(values[k],"%4d",accuracy);
1558 merror("rules_op: Invalid accuracy: %s. "
1564 /* Rule ignore_time */
1565 else if(strcasecmp(attributes[k],xml_ignore_time) == 0)
1567 if(OS_StrIsNum(values[k]))
1569 sscanf(values[k],"%6d",ignore_time);
1573 merror("rules_op: Invalid ignore_time: %s. "
1580 else if(strcasecmp(attributes[k],xml_noalert) == 0)
1584 else if(strcasecmp(attributes[k], xml_overwrite) == 0)
1586 if(strcmp(values[k], "yes") == 0)
1590 else if(strcmp(values[k], "no") == 0)
1596 merror("rules_op: Invalid overwrite: %s. "
1597 "Can only by 'yes' or 'no'.", values[k]);
1603 merror("rules_op: Invalid attribute \"%s\". "
1604 "Only id, level, maxsize, accuracy, noalert and timeframe "
1605 "are allowed.", attributes[k]);
1614 /* Bind active responses to the rule.
1617 void Rule_AddAR(RuleInfo *rule_config)
1619 int rule_ar_size = 0;
1621 int rule_real_level = 0;
1623 OSListNode *my_ars_node;
1626 /* Setting the correctly levels
1627 * We play internally with the rules, to set
1628 * the priorities... Rules with 0 of accuracy,
1629 * receive a low level and go down in the list
1631 if(rule_config->level == 9900)
1632 rule_real_level = 0;
1634 else if(rule_config->level >= 100)
1635 rule_real_level = rule_config->level/100;
1638 /* No AR for ignored rules */
1639 if(rule_real_level == 0)
1644 if(!active_responses)
1649 /* Looping on all AR */
1650 my_ars_node = OSList_GetFirstNode(active_responses);
1653 active_response *my_ar;
1656 my_ar = (active_response *)my_ars_node->data;
1659 /* Checking if the level for the ar is higher */
1662 if(rule_real_level >= my_ar->level)
1668 /* Checking if group matches */
1669 if(my_ar->rules_group)
1671 if(OS_Regex(my_ar->rules_group, rule_config->group))
1677 /* Checking if rule id matches */
1681 char *str_pt = my_ar->rules_id;
1683 while(*str_pt != '\0')
1685 /* We allow spaces in between */
1692 /* If is digit, we get the value
1693 * and search for the next digit
1696 else if(isdigit((int)*str_pt))
1698 r_id = atoi(str_pt);
1700 /* mark to ar if id matches */
1701 if(r_id == rule_config->sigid)
1706 str_pt = strchr(str_pt, ',');
1717 /* Checking for duplicate commas */
1718 else if(*str_pt == ',')
1729 } /* eof of rules_id */
1732 /* Bind AR to the rule */
1737 rule_config->ar = realloc(rule_config->ar,
1739 *sizeof(active_response *));
1741 /* Always set the last node to NULL */
1742 rule_config->ar[rule_ar_size - 1] = my_ar;
1743 rule_config->ar[rule_ar_size] = NULL;
1746 my_ars_node = OSList_GetNextNode(active_responses);
1754 void printRuleinfo(RuleInfo *rule, int node)
1756 debug1("%d : rule:%d, level %d, timeout: %d",
1765 /* Add Rule to hash. */
1766 int AddHash_Rule(RuleNode *node)
1773 snprintf(_id_key, 14, "%d", node->ruleinfo->sigid);
1774 os_strdup(_id_key, id_key);
1777 /* Adding key to hash. */
1778 OSHash_Add(Config.g_rules_hash, id_key, node->ruleinfo);
1781 AddHash_Rule(node->child);
1793 int _setlevels(RuleNode *node, int nnode)
1798 if(node->ruleinfo->level == 9900)
1799 node->ruleinfo->level = 0;
1801 if(node->ruleinfo->level >= 100)
1802 node->ruleinfo->level/=100;
1806 /* Rule information */
1807 printRuleinfo(node->ruleinfo, nnode);
1812 chl_size = _setlevels(node->child, nnode+1);