1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
12 #include "eventinfo.h"
13 #include "compiled_rules/compiled_rules.h"
15 /* Global definition */
16 RuleInfo *currently_rule;
18 /* Change path for test rule */
21 #define RULEPATH "rules/"
25 static int getattributes(char **attributes,
28 int *maxsize, int *timeframe,
29 int *frequency, int *accuracy,
30 int *noalert, int *ignore_time, int *overwrite);
31 static int doesRuleExist(int sid, RuleNode *r_node);
32 static void Rule_AddAR(RuleInfo *config_rule);
33 static char *loadmemory(char *at, const char *str);
34 static void printRuleinfo(const RuleInfo *rule, int node);
36 /* Will initialize the rules list */
37 void Rules_OP_CreateRules()
39 /* Initialize the rule list */
45 /* Read the log rules */
46 int Rules_OP_ReadRules(const char *rulefile)
52 /* These are the available options for the rule configuration */
54 const char *xml_group = "group";
55 const char *xml_rule = "rule";
57 const char *xml_regex = "regex";
58 const char *xml_pcre2 = "pcre2";
59 const char *xml_match = "match";
60 const char *xml_match_pcre2 = "match_pcre2";
61 const char *xml_decoded = "decoded_as";
62 const char *xml_category = "category";
63 const char *xml_cve = "cve";
64 const char *xml_info = "info";
65 const char *xml_day_time = "time";
66 const char *xml_week_day = "weekday";
67 const char *xml_comment = "description";
68 const char *xml_ignore = "ignore";
69 const char *xml_check_if_ignored = "check_if_ignored";
71 const char *xml_srcip = "srcip";
72 const char *xml_srcgeoip = "srcgeoip";
73 const char *xml_srcport = "srcport";
74 const char *xml_srcgeoip_pcre2 = "srcgeoip_pcre2";
75 const char *xml_srcport_pcre2 = "srcport_pcre2";
76 const char *xml_dstip = "dstip";
77 const char *xml_dstgeoip = "dstgeoip";
78 const char *xml_dstport = "dstport";
79 const char *xml_user = "user";
80 const char *xml_url = "url";
81 const char *xml_id = "id";
82 const char *xml_data = "extra_data";
83 const char *xml_hostname = "hostname";
84 const char *xml_program_name = "program_name";
85 const char *xml_status = "status";
86 const char *xml_dstgeoip_pcre2 = "dstgeoip_pcre2";
87 const char *xml_dstport_pcre2 = "dstport_pcre2";
88 const char *xml_user_pcre2 = "user_pcre2";
89 const char *xml_url_pcre2 = "url_pcre2";
90 const char *xml_id_pcre2 = "id_pcre2";
91 const char *xml_data_pcre2 = "extra_data_pcre2";
92 const char *xml_hostname_pcre2 = "hostname_pcre2";
93 const char *xml_program_name_pcre2 = "program_name_pcre2";
94 const char *xml_status_pcre2 = "status_pcre2";
95 const char *xml_action = "action";
96 const char *xml_compiled = "compiled_rule";
97 const char *xml_field = "field";
98 const char *xml_name = "name";
101 const char *xml_list = "list";
102 const char *xml_list_lookup = "lookup";
103 const char *xml_list_field = "field";
104 const char *xml_list_cvalue = "check_value";
105 const char *xml_match_key = "match_key";
106 const char *xml_not_match_key = "not_match_key";
107 const char *xml_match_key_value = "match_key_value";
108 const char *xml_address_key = "address_match_key";
109 const char *xml_not_address_key = "not_address_match_key";
110 const char *xml_address_key_value = "address_match_key_value";
112 const char *xml_if_sid = "if_sid";
113 const char *xml_if_group = "if_group";
114 const char *xml_if_level = "if_level";
115 const char *xml_fts = "if_fts";
117 const char *xml_if_matched_regex = "if_matched_regex";
118 const char *xml_if_matched_group = "if_matched_group";
119 const char *xml_if_matched_sid = "if_matched_sid";
121 const char *xml_same_source_ip = "same_source_ip";
122 const char *xml_same_src_port = "same_src_port";
123 const char *xml_same_dst_port = "same_dst_port";
124 const char *xml_same_user = "same_user";
125 const char *xml_same_location = "same_location";
126 const char *xml_same_id = "same_id";
127 const char *xml_dodiff = "check_diff";
129 const char *xml_different_url = "different_url";
130 const char *xml_different_srcip = "different_srcip";
131 const char *xml_different_srcgeoip = "different_srcgeoip";
133 const char *xml_notsame_source_ip = "not_same_source_ip";
134 const char *xml_notsame_user = "not_same_user";
135 const char *xml_notsame_agent = "not_same_agent";
136 const char *xml_notsame_id = "not_same_id";
138 const char *xml_options = "options";
143 int default_timeframe = 360;
145 /* If no directory in the rulefile, add the default */
146 if ((strchr(rulefile, '/')) == NULL) {
147 /* Build the rule file name + path */
148 i = strlen(RULEPATH) + strlen(rulefile) + 2;
149 rulepath = (char *)calloc(i, sizeof(char));
151 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
153 snprintf(rulepath, i, "%s/%s", RULEPATH, rulefile);
155 os_strdup(rulefile, rulepath);
156 debug1("%s is the rulefile", rulefile);
157 debug1("Not modifing the rule path");
163 if (OS_ReadXML(rulepath, &xml) < 0) {
164 merror(XML_ERROR, ARGV0, rulepath, xml.err, xml.err_line);
168 debug2("%s: DEBUG: read xml for rule.", ARGV0);
170 /* Apply any variable found */
171 if (OS_ApplyVariables(&xml) != 0) {
172 merror(XML_ERROR_VAR, ARGV0, rulepath, xml.err);
176 debug2("%s: DEBUG: XML Variables applied.", ARGV0);
178 /* Get the root elements */
179 node = OS_GetElementsbyNode(&xml, NULL);
181 merror(CONFIG_ERROR, ARGV0, rulepath);
187 /* Zero the rule memory -- not used anymore */
190 /* Get default time frame */
191 default_timeframe = getDefine_Int("analysisd",
195 /* Check if there is any invalid global option */
197 if (node[i]->element) {
198 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])) {
208 merror("rules_op: Invalid root element '%s'."
209 "Only the group name is allowed", node[i]->element);
214 merror(XML_READ_ERROR, ARGV0);
224 XML_NODE rule = NULL;
228 /* Get all rules for a global group */
229 rule = OS_GetElementsbyNode(&xml, node[i]);
231 merror("%s: Group '%s' without any rule.",
232 ARGV0, node[i]->element);
238 RuleInfo *config_ruleinfo = NULL;
240 /* Check if the rule element is correct */
241 if ((!rule[j]->element) ||
242 (strcasecmp(rule[j]->element, xml_rule) != 0)) {
243 merror("%s: Invalid configuration. '%s' is not "
244 "a valid element.", ARGV0, rule[j]->element);
249 /* Check for the attributes of the rule */
250 if ((!rule[j]->attributes) || (!rule[j]->values)) {
251 merror("%s: Invalid rule '%d'. You must specify"
252 " an ID and a level at least.", ARGV0, j);
257 /* Attribute block */
259 int id = -1, level = -1, maxsize = 0, timeframe = 0;
260 int frequency = 0, accuracy = 1, noalert = 0, ignore_time = 0;
263 /* Get default timeframe */
264 timeframe = default_timeframe;
266 if (getattributes(rule[j]->attributes, rule[j]->values,
267 &id, &level, &maxsize, &timeframe,
268 &frequency, &accuracy, &noalert,
269 &ignore_time, &overwrite) < 0) {
270 merror("%s: Invalid attribute for rule.", ARGV0);
275 if ((id == -1) || (level == -1)) {
276 merror("%s: No rule id or level specified for "
277 "rule '%d'.", ARGV0, j);
282 if (overwrite != 1 && doesRuleExist(id, NULL)) {
283 merror("%s: Duplicate rule ID:%d", ARGV0, id);
288 /* Allocate memory and initialize structure */
289 config_ruleinfo = zerorulemember(id, level, maxsize,
290 frequency, timeframe,
291 noalert, ignore_time, overwrite);
293 /* If rule is 0, set it to level 99 to have high priority.
294 * Set it to 0 again later.
296 if (config_ruleinfo->level == 0) {
297 config_ruleinfo->level = 99;
300 /* Each level now is going to be multiplied by 100.
301 * If the accuracy is set to 0 we don't multiply,
302 * so it will be at the end of the list. We will
303 * divide by 100 later.
306 config_ruleinfo->level *= 100;
309 if (config_ruleinfo->maxsize > 0) {
310 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
311 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
315 } /* end attributes/memory allocation block */
317 /* Here we can assign the group name to the rule.
318 * The level is correct so the rule is probably going to
321 os_strdup(node[i]->values[0], config_ruleinfo->group);
323 /* Rule elements block */
328 int count_info_detail = 0;
329 RuleInfoDetail *last_info_detail = NULL;
333 char *match_pcre2 = NULL;
335 char *url_pcre2 = NULL;
336 char *if_matched_regex = NULL;
337 char *if_matched_group = NULL;
340 char *srcport = NULL;
341 char *dstport = NULL;
342 char *srcgeoip = NULL;
343 char *dstgeoip = NULL;
346 char *hostname = NULL;
347 char *extra_data = NULL;
348 char *program_name = NULL;
350 char *user_pcre2 = NULL;
351 char *id_pcre2 = NULL;
352 char *srcport_pcre2 = NULL;
353 char *dstport_pcre2 = NULL;
354 char *srcgeoip_pcre2 = NULL;
355 char *dstgeoip_pcre2 = NULL;
357 char *status_pcre2 = NULL;
358 char *hostname_pcre2 = NULL;
359 char *extra_data_pcre2 = NULL;
360 char *program_name_pcre2 = NULL;
362 XML_NODE rule_opt = NULL;
363 rule_opt = OS_GetElementsbyNode(&xml, rule[j]);
364 if (rule_opt == NULL) {
365 merror("%s: Rule '%d' without any option. "
366 "It may lead to false positives and some "
367 "other problems for the system. Exiting.",
368 ARGV0, config_ruleinfo->sigid);
373 while (rule_opt[k]) {
374 if ((!rule_opt[k]->element) || (!rule_opt[k]->content)) {
376 } else if (strcasecmp(rule_opt[k]->element, xml_regex) == 0) {
379 rule_opt[k]->content);
380 } else if (strcasecmp(rule_opt[k]->element, xml_pcre2) == 0) {
383 rule_opt[k]->content);
384 } else if (strcasecmp(rule_opt[k]->element, xml_match) == 0) {
387 rule_opt[k]->content);
388 } else if (strcasecmp(rule_opt[k]->element, xml_match_pcre2) == 0) {
390 loadmemory(match_pcre2,
391 rule_opt[k]->content);
392 } else if (strcasecmp(rule_opt[k]->element, xml_decoded) == 0) {
393 config_ruleinfo->decoded_as =
394 getDecoderfromlist(rule_opt[k]->content);
396 if (config_ruleinfo->decoded_as == 0) {
397 merror("%s: Invalid decoder name: '%s'.",
398 ARGV0, rule_opt[k]->content);
402 } else if (strcasecmp(rule_opt[k]->element, xml_cve) == 0) {
403 if (config_ruleinfo->info_details == NULL) {
404 config_ruleinfo->info_details = zeroinfodetails(RULEINFODETAIL_CVE,
405 rule_opt[k]->content);
407 for (last_info_detail = config_ruleinfo->info_details;
408 last_info_detail->next != NULL;
409 last_info_detail = last_info_detail->next) {
412 /* Silently Drop info messages if their are more then MAX_RULEINFODETAIL */
413 if (count_info_detail <= MAX_RULEINFODETAIL) {
414 last_info_detail->next = zeroinfodetails(RULEINFODETAIL_CVE,
415 rule_opt[k]->content);
419 /* keep old methods for now */
420 config_ruleinfo->cve =
421 loadmemory(config_ruleinfo->cve,
422 rule_opt[k]->content);
423 } else if (strcasecmp(rule_opt[k]->element, xml_info) == 0) {
425 info_type = get_info_attributes(rule_opt[k]->attributes,
426 rule_opt[k]->values);
427 debug1("info_type = %d", info_type);
429 if (config_ruleinfo->info_details == NULL) {
430 config_ruleinfo->info_details = zeroinfodetails(info_type,
431 rule_opt[k]->content);
433 for (last_info_detail = config_ruleinfo->info_details;
434 last_info_detail->next != NULL;
435 last_info_detail = last_info_detail->next) {
438 /* Silently Drop info messages if their are more then MAX_RULEINFODETAIL */
439 if (count_info_detail <= MAX_RULEINFODETAIL) {
440 last_info_detail->next = zeroinfodetails(info_type, rule_opt[k]->content);
445 /* keep old methods for now */
446 config_ruleinfo->info =
447 loadmemory(config_ruleinfo->info,
448 rule_opt[k]->content);
449 } else if (strcasecmp(rule_opt[k]->element, xml_day_time) == 0) {
450 config_ruleinfo->day_time =
451 OS_IsValidTime(rule_opt[k]->content);
452 if (!config_ruleinfo->day_time) {
453 merror(INVALID_CONFIG, ARGV0,
454 rule_opt[k]->element,
455 rule_opt[k]->content);
459 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
460 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
462 } else if (strcasecmp(rule_opt[k]->element, xml_week_day) == 0) {
463 config_ruleinfo->week_day =
464 OS_IsValidDay(rule_opt[k]->content);
466 if (!config_ruleinfo->week_day) {
467 merror(INVALID_CONFIG, ARGV0,
468 rule_opt[k]->element,
469 rule_opt[k]->content);
472 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
473 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
475 } else if (strcasecmp(rule_opt[k]->element, xml_group) == 0) {
476 config_ruleinfo->group =
477 loadmemory(config_ruleinfo->group,
478 rule_opt[k]->content);
479 } else if (strcasecmp(rule_opt[k]->element, xml_comment) == 0) {
482 newline = strchr(rule_opt[k]->content, '\n');
487 config_ruleinfo->comment =
488 loadmemory(config_ruleinfo->comment,
489 rule_opt[k]->content);
490 } else if (strcasecmp(rule_opt[k]->element, xml_srcip) == 0) {
491 unsigned int ip_s = 0;
493 /* Getting size of source ip list */
494 while (config_ruleinfo->srcip &&
495 config_ruleinfo->srcip[ip_s]) {
499 config_ruleinfo->srcip =
500 (os_ip **) realloc(config_ruleinfo->srcip,
501 (ip_s + 2) * sizeof(os_ip *));
504 /* Allocating memory for the individual entries */
505 os_calloc(1, sizeof(os_ip),
506 config_ruleinfo->srcip[ip_s]);
507 config_ruleinfo->srcip[ip_s + 1] = NULL;
510 /* Checking if the ip is valid */
511 if (!OS_IsValidIP(rule_opt[k]->content,
512 config_ruleinfo->srcip[ip_s])) {
513 merror(INVALID_IP, ARGV0, rule_opt[k]->content);
517 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
518 config_ruleinfo->alert_opts |= DO_PACKETINFO;
520 } else if (strcasecmp(rule_opt[k]->element, xml_dstip) == 0) {
521 unsigned int ip_s = 0;
523 /* Getting size of source ip list */
524 while (config_ruleinfo->dstip &&
525 config_ruleinfo->dstip[ip_s]) {
529 config_ruleinfo->dstip =
530 (os_ip **) realloc(config_ruleinfo->dstip,
531 (ip_s + 2) * sizeof(os_ip *));
534 /* Allocating memory for the individual entries */
535 os_calloc(1, sizeof(os_ip),
536 config_ruleinfo->dstip[ip_s]);
537 config_ruleinfo->dstip[ip_s + 1] = NULL;
540 /* Checking if the ip is valid */
541 if (!OS_IsValidIP(rule_opt[k]->content,
542 config_ruleinfo->dstip[ip_s])) {
543 merror(INVALID_IP, ARGV0, rule_opt[k]->content);
547 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
548 config_ruleinfo->alert_opts |= DO_PACKETINFO;
550 } else if (strcasecmp(rule_opt[k]->element, xml_user) == 0) {
553 rule_opt[k]->content);
555 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
556 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
558 } else if(strcasecmp(rule_opt[k]->element,xml_srcgeoip)==0) {
561 rule_opt[k]->content);
563 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
564 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
565 } else if(strcasecmp(rule_opt[k]->element,xml_dstgeoip)==0) {
568 rule_opt[k]->content);
570 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
571 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
572 } else if (strcasecmp(rule_opt[k]->element, xml_id) == 0) {
575 rule_opt[k]->content);
576 } else if (strcasecmp(rule_opt[k]->element, xml_srcport) == 0) {
579 rule_opt[k]->content);
580 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
581 config_ruleinfo->alert_opts |= DO_PACKETINFO;
583 } else if (strcasecmp(rule_opt[k]->element, xml_dstport) == 0) {
586 rule_opt[k]->content);
588 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
589 config_ruleinfo->alert_opts |= DO_PACKETINFO;
591 } else if (strcasecmp(rule_opt[k]->element, xml_status) == 0) {
594 rule_opt[k]->content);
596 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
597 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
599 } else if (strcasecmp(rule_opt[k]->element, xml_hostname) == 0) {
602 rule_opt[k]->content);
604 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
605 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
607 } else if (strcasecmp(rule_opt[k]->element, xml_data) == 0) {
609 loadmemory(extra_data,
610 rule_opt[k]->content);
612 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
613 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
615 } else if (strcasecmp(rule_opt[k]->element,
616 xml_program_name) == 0) {
618 loadmemory(program_name,
619 rule_opt[k]->content);
620 } else if (strcasecmp(rule_opt[k]->element, xml_user_pcre2) == 0) {
622 loadmemory(user_pcre2,
623 rule_opt[k]->content);
625 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
626 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
628 } else if(strcasecmp(rule_opt[k]->element,xml_srcgeoip_pcre2)==0) {
630 loadmemory(srcgeoip_pcre2,
631 rule_opt[k]->content);
633 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
634 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
635 } else if(strcasecmp(rule_opt[k]->element,xml_dstgeoip_pcre2)==0) {
637 loadmemory(dstgeoip_pcre2,
638 rule_opt[k]->content);
640 if(!(config_ruleinfo->alert_opts & DO_EXTRAINFO))
641 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
642 } else if (strcasecmp(rule_opt[k]->element, xml_id_pcre2) == 0) {
645 rule_opt[k]->content);
646 } else if (strcasecmp(rule_opt[k]->element, xml_srcport_pcre2) == 0) {
648 loadmemory(srcport_pcre2,
649 rule_opt[k]->content);
650 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
651 config_ruleinfo->alert_opts |= DO_PACKETINFO;
653 } else if (strcasecmp(rule_opt[k]->element, xml_dstport_pcre2) == 0) {
655 loadmemory(dstport_pcre2,
656 rule_opt[k]->content);
658 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
659 config_ruleinfo->alert_opts |= DO_PACKETINFO;
661 } else if (strcasecmp(rule_opt[k]->element, xml_status_pcre2) == 0) {
663 loadmemory(status_pcre2,
664 rule_opt[k]->content);
666 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
667 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
669 } else if (strcasecmp(rule_opt[k]->element, xml_hostname_pcre2) == 0) {
671 loadmemory(hostname_pcre2,
672 rule_opt[k]->content);
674 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
675 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
677 } else if (strcasecmp(rule_opt[k]->element, xml_data_pcre2) == 0) {
679 loadmemory(extra_data_pcre2,
680 rule_opt[k]->content);
682 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
683 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
685 } else if (strcasecmp(rule_opt[k]->element,
686 xml_program_name_pcre2) == 0) {
688 loadmemory(program_name_pcre2,
689 rule_opt[k]->content);
690 } else if (strcasecmp(rule_opt[k]->element, xml_action) == 0) {
691 config_ruleinfo->action =
692 loadmemory(config_ruleinfo->action,
693 rule_opt[k]->content);
694 } else if (strcasecmp(rule_opt[k]->element, xml_field) == 0) {
695 if (rule_opt[k]->attributes[0]) {
696 os_calloc(1, sizeof(FieldInfo), config_ruleinfo->fields[ifield]);
698 if (strcasecmp(rule_opt[k]->attributes[0], xml_name) == 0) {
699 config_ruleinfo->fields[ifield]->name = loadmemory(config_ruleinfo->fields[ifield]->name, rule_opt[k]->values[0]);
701 merror("%s: Bad attribute '%s' for field.", ARGV0, rule_opt[k]->attributes[0]);
705 merror("%s: No such attribute '%s' for field.", ARGV0, xml_name);
709 os_calloc(1, sizeof(OSRegex), config_ruleinfo->fields[ifield]->regex);
711 if (!OSRegex_Compile(rule_opt[k]->content, config_ruleinfo->fields[ifield]->regex, 0)) {
712 merror(REGEX_COMPILE, ARGV0, rule_opt[k]->content, config_ruleinfo->fields[ifield]->regex->error);
718 } else if (strcasecmp(rule_opt[k]->element, xml_list) == 0) {
719 debug1("-> %s == %s", rule_opt[k]->element, xml_list);
720 if (rule_opt[k]->attributes && rule_opt[k]->values && rule_opt[k]->content) {
721 int list_att_num = 0;
723 OSMatch *matcher = NULL;
724 int lookup_type = LR_STRING_MATCH;
725 while (rule_opt[k]->attributes[list_att_num]) {
726 if (strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_lookup) == 0) {
727 if (strcasecmp(rule_opt[k]->values[list_att_num], xml_match_key) == 0) {
728 lookup_type = LR_STRING_MATCH;
729 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_not_match_key) == 0) {
730 lookup_type = LR_STRING_NOT_MATCH;
731 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_match_key_value) == 0) {
732 lookup_type = LR_STRING_MATCH_VALUE;
733 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_address_key) == 0) {
734 lookup_type = LR_ADDRESS_MATCH;
735 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_not_address_key) == 0) {
736 lookup_type = LR_ADDRESS_NOT_MATCH;
737 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_address_key_value) == 0) {
738 lookup_type = LR_ADDRESS_MATCH_VALUE;
740 merror(INVALID_CONFIG, ARGV0,
741 rule_opt[k]->element,
742 rule_opt[k]->content);
743 merror("%s: List match lookup=\"%s\" is not valid.",
744 ARGV0, rule_opt[k]->values[list_att_num]);
747 } else if (strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_field) == 0) {
748 if (strcasecmp(rule_opt[k]->values[list_att_num], xml_srcip) == 0) {
749 rule_type = RULE_SRCIP;
750 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_srcport) == 0) {
751 rule_type = RULE_SRCPORT;
752 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_dstip) == 0) {
753 rule_type = RULE_DSTIP;
754 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_dstport) == 0) {
755 rule_type = RULE_DSTPORT;
756 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_user) == 0) {
757 rule_type = RULE_USER;
758 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_url) == 0) {
759 rule_type = RULE_URL;
760 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_id) == 0) {
762 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_hostname) == 0) {
763 rule_type = RULE_HOSTNAME;
764 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_program_name) == 0) {
765 rule_type = RULE_PROGRAM_NAME;
766 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_status) == 0) {
767 rule_type = RULE_STATUS;
768 } else if (strcasecmp(rule_opt[k]->values[list_att_num], xml_action) == 0) {
769 rule_type = RULE_ACTION;
771 merror(INVALID_CONFIG, ARGV0,
772 rule_opt[k]->element,
773 rule_opt[k]->content);
774 merror("%s: List match field=\"%s\" is not valid.",
775 ARGV0, rule_opt[k]->values[list_att_num]);
778 } else if (strcasecmp(rule_opt[k]->attributes[list_att_num], xml_list_cvalue) == 0) {
779 os_calloc(1, sizeof(OSMatch), matcher);
780 if (!OSMatch_Compile(rule_opt[k]->values[list_att_num], matcher, 0)) {
781 merror(INVALID_CONFIG, ARGV0,
782 rule_opt[k]->element,
783 rule_opt[k]->content);
784 merror(REGEX_COMPILE,
786 rule_opt[k]->values[list_att_num],
791 merror("%s:List field=\"%s\" is not valid", ARGV0,
792 rule_opt[k]->values[list_att_num]);
793 merror(INVALID_CONFIG, ARGV0,
794 rule_opt[k]->element, rule_opt[k]->content);
799 if (rule_type == 0) {
800 merror("%s:List requires the field=\"\" Attrubute", ARGV0);
801 merror(INVALID_CONFIG, ARGV0,
802 rule_opt[k]->element, rule_opt[k]->content);
806 /* Wow it's all ready - this seems too complex to get to this point */
807 config_ruleinfo->lists = OS_AddListRule(config_ruleinfo->lists,
810 rule_opt[k]->content,
812 if (config_ruleinfo->lists == NULL) {
813 merror("%s: List error: Could not load %s", ARGV0, rule_opt[k]->content);
817 merror("%s:List must have a correctly formatted field attribute",
819 merror(INVALID_CONFIG,
821 rule_opt[k]->element,
822 rule_opt[k]->content);
825 /* xml_list eval is done */
826 } else if (strcasecmp(rule_opt[k]->element, xml_url) == 0) {
829 rule_opt[k]->content);
830 } else if (strcasecmp(rule_opt[k]->element, xml_url_pcre2) == 0) {
832 loadmemory(url_pcre2,
833 rule_opt[k]->content);
834 } else if (strcasecmp(rule_opt[k]->element, xml_compiled) == 0) {
837 while (compiled_rules_name[it_id]) {
838 if (strcmp(compiled_rules_name[it_id],
839 rule_opt[k]->content) == 0) {
845 /* Checking if the name is valid */
846 if (!compiled_rules_name[it_id]) {
847 merror("%s: ERROR: Compiled rule not found: '%s'",
848 ARGV0, rule_opt[k]->content);
849 merror(INVALID_CONFIG, ARGV0,
850 rule_opt[k]->element, rule_opt[k]->content);
855 config_ruleinfo->compiled_rule = (void *(*)(void *)) compiled_rules_list[it_id];
856 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
857 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
861 else if (strcasecmp(rule_opt[k]->element, xml_category) == 0) {
862 if (strcmp(rule_opt[k]->content, "firewall") == 0) {
863 config_ruleinfo->category = FIREWALL;
864 } else if (strcmp(rule_opt[k]->content, "ids") == 0) {
865 config_ruleinfo->category = IDS;
866 } else if (strcmp(rule_opt[k]->content, "syslog") == 0) {
867 config_ruleinfo->category = SYSLOG;
868 } else if (strcmp(rule_opt[k]->content, "web-log") == 0) {
869 config_ruleinfo->category = WEBLOG;
870 } else if (strcmp(rule_opt[k]->content, "squid") == 0) {
871 config_ruleinfo->category = SQUID;
872 } else if (strcmp(rule_opt[k]->content, "windows") == 0) {
873 config_ruleinfo->category = DECODER_WINDOWS;
874 } else if (strcmp(rule_opt[k]->content, "ossec") == 0) {
875 config_ruleinfo->category = OSSEC_RL;
877 merror(INVALID_CAT, ARGV0, rule_opt[k]->content);
880 } else if (strcasecmp(rule_opt[k]->element, xml_if_sid) == 0) {
881 config_ruleinfo->if_sid =
882 loadmemory(config_ruleinfo->if_sid,
883 rule_opt[k]->content);
884 } else if (strcasecmp(rule_opt[k]->element, xml_if_level) == 0) {
885 if (!OS_StrIsNum(rule_opt[k]->content)) {
886 merror(INVALID_CONFIG, ARGV0,
888 rule_opt[k]->content);
892 config_ruleinfo->if_level =
893 loadmemory(config_ruleinfo->if_level,
894 rule_opt[k]->content);
895 } else if (strcasecmp(rule_opt[k]->element, xml_if_group) == 0) {
896 config_ruleinfo->if_group =
897 loadmemory(config_ruleinfo->if_group,
898 rule_opt[k]->content);
899 } else if (strcasecmp(rule_opt[k]->element,
900 xml_if_matched_regex) == 0) {
901 config_ruleinfo->context = 1;
903 loadmemory(if_matched_regex,
904 rule_opt[k]->content);
905 } else if (strcasecmp(rule_opt[k]->element,
906 xml_if_matched_group) == 0) {
907 config_ruleinfo->context = 1;
909 loadmemory(if_matched_group,
910 rule_opt[k]->content);
911 } else if (strcasecmp(rule_opt[k]->element,
912 xml_if_matched_sid) == 0) {
913 config_ruleinfo->context = 1;
914 if (!OS_StrIsNum(rule_opt[k]->content)) {
915 merror(INVALID_CONFIG, ARGV0,
917 rule_opt[k]->content);
920 config_ruleinfo->if_matched_sid =
921 atoi(rule_opt[k]->content);
923 } else if (strcasecmp(rule_opt[k]->element,
924 xml_same_source_ip) == 0) {
925 config_ruleinfo->context_opts |= SAME_SRCIP;
926 } else if (strcasecmp(rule_opt[k]->element,
927 xml_same_src_port) == 0) {
928 config_ruleinfo->context_opts |= SAME_SRCPORT;
930 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
931 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
933 } else if (strcasecmp(rule_opt[k]->element,
935 config_ruleinfo->context = 1;
936 config_ruleinfo->context_opts |= SAME_DODIFF;
937 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
938 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
940 } else if (strcasecmp(rule_opt[k]->element,
941 xml_same_dst_port) == 0) {
942 config_ruleinfo->context_opts |= SAME_DSTPORT;
944 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
945 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
947 } else if (strcasecmp(rule_opt[k]->element,
948 xml_notsame_source_ip) == 0) {
949 config_ruleinfo->context_opts &= NOT_SAME_SRCIP;
950 } else if (strcmp(rule_opt[k]->element, xml_same_id) == 0) {
951 config_ruleinfo->context_opts |= SAME_ID;
952 } else if (strcmp(rule_opt[k]->element,
953 xml_different_url) == 0) {
954 config_ruleinfo->context_opts |= DIFFERENT_URL;
956 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
957 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
959 } else if(strcmp(rule_opt[k]->element,
960 xml_different_srcip) == 0) {
961 config_ruleinfo->context_opts|= DIFFERENT_SRCIP;
963 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
964 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
965 } else if(strcmp(rule_opt[k]->element,
966 xml_different_srcgeoip) == 0) {
967 config_ruleinfo->context_opts|= DIFFERENT_SRCGEOIP;
969 if(!(config_ruleinfo->alert_opts & SAME_EXTRAINFO))
970 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
971 } else if (strcmp(rule_opt[k]->element, xml_notsame_id) == 0) {
972 config_ruleinfo->context_opts &= NOT_SAME_ID;
973 } else if (strcasecmp(rule_opt[k]->element,
975 config_ruleinfo->alert_opts |= DO_FTS;
976 } else if (strcasecmp(rule_opt[k]->element,
977 xml_same_user) == 0) {
978 config_ruleinfo->context_opts |= SAME_USER;
980 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
981 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
983 } else if (strcasecmp(rule_opt[k]->element,
984 xml_notsame_user) == 0) {
985 config_ruleinfo->context_opts &= NOT_SAME_USER;
986 } else if (strcasecmp(rule_opt[k]->element,
987 xml_same_location) == 0) {
988 config_ruleinfo->context_opts |= SAME_LOCATION;
989 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
990 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
992 } else if (strcasecmp(rule_opt[k]->element,
993 xml_notsame_agent) == 0) {
994 config_ruleinfo->context_opts &= NOT_SAME_AGENT;
995 } else if (strcasecmp(rule_opt[k]->element,
997 if (strcmp("alert_by_email",
998 rule_opt[k]->content) == 0) {
999 if (!(config_ruleinfo->alert_opts & DO_MAILALERT)) {
1000 config_ruleinfo->alert_opts |= DO_MAILALERT;
1002 } else if (strcmp("no_email_alert",
1003 rule_opt[k]->content) == 0) {
1004 if (config_ruleinfo->alert_opts & DO_MAILALERT) {
1005 config_ruleinfo->alert_opts &= 0xfff - DO_MAILALERT;
1007 } else if (strcmp("log_alert",
1008 rule_opt[k]->content) == 0) {
1009 if (!(config_ruleinfo->alert_opts & DO_LOGALERT)) {
1010 config_ruleinfo->alert_opts |= DO_LOGALERT;
1012 } else if (strcmp("no_log", rule_opt[k]->content) == 0) {
1013 if (config_ruleinfo->alert_opts & DO_LOGALERT) {
1014 config_ruleinfo->alert_opts &= 0xfff - DO_LOGALERT;
1016 } else if (strcmp("no_ar", rule_opt[k]->content) == 0) {
1017 if (!(config_ruleinfo->alert_opts & NO_AR)) {
1018 config_ruleinfo->alert_opts |= NO_AR;
1021 merror(XML_VALUEERR, ARGV0, xml_options,
1022 rule_opt[k]->content);
1024 merror("%s: Invalid option '%s' for "
1025 "rule '%d'.", ARGV0, rule_opt[k]->element,
1026 config_ruleinfo->sigid);
1030 } else if (strcasecmp(rule_opt[k]->element,
1032 if (strstr(rule_opt[k]->content, "user") != NULL) {
1033 config_ruleinfo->ignore |= FTS_DSTUSER;
1035 if (strstr(rule_opt[k]->content, "srcip") != NULL) {
1036 config_ruleinfo->ignore |= FTS_SRCIP;
1038 if (strstr(rule_opt[k]->content, "dstip") != NULL) {
1039 config_ruleinfo->ignore |= FTS_DSTIP;
1041 if (strstr(rule_opt[k]->content, "id") != NULL) {
1042 config_ruleinfo->ignore |= FTS_ID;
1044 if (strstr(rule_opt[k]->content, "location") != NULL) {
1045 config_ruleinfo->ignore |= FTS_LOCATION;
1047 if (strstr(rule_opt[k]->content, "data") != NULL) {
1048 config_ruleinfo->ignore |= FTS_DATA;
1050 if (strstr(rule_opt[k]->content, "name") != NULL) {
1051 config_ruleinfo->ignore |= FTS_NAME;
1054 if (!config_ruleinfo->ignore) {
1055 merror("%s: Wrong ignore option: '%s'",
1057 rule_opt[k]->content);
1060 } else if (strcasecmp(rule_opt[k]->element,
1061 xml_check_if_ignored) == 0) {
1062 if (strstr(rule_opt[k]->content, "user") != NULL) {
1063 config_ruleinfo->ckignore |= FTS_DSTUSER;
1065 if (strstr(rule_opt[k]->content, "srcip") != NULL) {
1066 config_ruleinfo->ckignore |= FTS_SRCIP;
1068 if (strstr(rule_opt[k]->content, "dstip") != NULL) {
1069 config_ruleinfo->ckignore |= FTS_DSTIP;
1071 if (strstr(rule_opt[k]->content, "id") != NULL) {
1072 config_ruleinfo->ckignore |= FTS_ID;
1074 if (strstr(rule_opt[k]->content, "location") != NULL) {
1075 config_ruleinfo->ckignore |= FTS_LOCATION;
1077 if (strstr(rule_opt[k]->content, "data") != NULL) {
1078 config_ruleinfo->ckignore |= FTS_DATA;
1080 if (strstr(rule_opt[k]->content, "name") != NULL) {
1081 config_ruleinfo->ckignore |= FTS_NAME;
1084 if (!config_ruleinfo->ckignore) {
1085 merror("%s: Wrong check_if_ignored option: '%s'",
1087 rule_opt[k]->content);
1091 merror("%s: Invalid option '%s' for "
1092 "rule '%d'.", ARGV0, rule_opt[k]->element,
1093 config_ruleinfo->sigid);
1100 /* Check for valid use of frequency */
1101 if ((config_ruleinfo->context_opts ||
1102 config_ruleinfo->frequency) &&
1103 !config_ruleinfo->context) {
1104 merror("%s: Invalid use of frequency/context options. "
1105 "Missing if_matched on rule '%d'.",
1106 ARGV0, config_ruleinfo->sigid);
1111 /* If if_matched_group we must have a if_sid or if_group */
1112 if (if_matched_group) {
1113 if (!config_ruleinfo->if_sid && !config_ruleinfo->if_group) {
1114 os_strdup(if_matched_group,
1115 config_ruleinfo->if_group);
1119 /* If_matched_sid, we need to get the if_sid */
1120 if (config_ruleinfo->if_matched_sid &&
1121 !config_ruleinfo->if_sid &&
1122 !config_ruleinfo->if_group) {
1123 os_calloc(16, sizeof(char), config_ruleinfo->if_sid);
1124 snprintf(config_ruleinfo->if_sid, 15, "%d",
1125 config_ruleinfo->if_matched_sid);
1128 /* Check the regexes */
1130 os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex);
1131 if (!OSRegex_Compile(regex, config_ruleinfo->regex, 0)) {
1132 merror(REGEX_COMPILE, ARGV0, regex,
1133 config_ruleinfo->regex->error);
1141 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->pcre2);
1142 if (!OSPcre2_Compile(pcre2, config_ruleinfo->pcre2, PCRE2_CASELESS)) {
1143 merror(REGEX_COMPILE, ARGV0, pcre2,
1144 config_ruleinfo->pcre2->error);
1153 os_calloc(1, sizeof(OSMatch), config_ruleinfo->match);
1154 if (!OSMatch_Compile(match, config_ruleinfo->match, 0)) {
1155 merror(REGEX_COMPILE, ARGV0, match,
1156 config_ruleinfo->match->error);
1162 else if (match_pcre2) {
1163 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->match_pcre2);
1164 if (!OSPcre2_Compile(match_pcre2, config_ruleinfo->match_pcre2, PCRE2_CASELESS)) {
1165 merror(REGEX_COMPILE, ARGV0, match_pcre2,
1166 config_ruleinfo->match_pcre2->error);
1175 os_calloc(1, sizeof(OSMatch), config_ruleinfo->id);
1176 if (!OSMatch_Compile(id, config_ruleinfo->id, 0)) {
1177 merror(REGEX_COMPILE, ARGV0, id,
1178 config_ruleinfo->id->error);
1185 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->id_pcre2);
1186 if (!OSPcre2_Compile(id_pcre2, config_ruleinfo->id_pcre2, PCRE2_CASELESS)) {
1187 merror(REGEX_COMPILE, ARGV0, id,
1188 config_ruleinfo->id_pcre2->error);
1197 os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport);
1198 if (!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0)) {
1199 merror(REGEX_COMPILE, ARGV0, srcport,
1200 config_ruleinfo->id->error);
1206 if (srcport_pcre2) {
1207 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->srcport_pcre2);
1208 if (!OSPcre2_Compile(srcport_pcre2, config_ruleinfo->srcport_pcre2, PCRE2_CASELESS)) {
1209 merror(REGEX_COMPILE, ARGV0, srcport_pcre2,
1210 config_ruleinfo->id->error);
1213 free(srcport_pcre2);
1214 srcport_pcre2 = NULL;
1219 os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport);
1220 if (!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0)) {
1221 merror(REGEX_COMPILE, ARGV0, dstport,
1222 config_ruleinfo->id->error);
1228 else if (dstport_pcre2) {
1229 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->dstport_pcre2);
1230 if (!OSPcre2_Compile(dstport_pcre2, config_ruleinfo->dstport_pcre2, PCRE2_CASELESS)) {
1231 merror(REGEX_COMPILE, ARGV0, dstport_pcre2,
1232 config_ruleinfo->id->error);
1235 free(dstport_pcre2);
1236 dstport_pcre2 = NULL;
1241 os_calloc(1, sizeof(OSMatch), config_ruleinfo->status);
1242 if (!OSMatch_Compile(status, config_ruleinfo->status, 0)) {
1243 merror(REGEX_COMPILE, ARGV0, status,
1244 config_ruleinfo->status->error);
1250 else if (status_pcre2) {
1251 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->status_pcre2);
1252 if (!OSPcre2_Compile(status_pcre2, config_ruleinfo->status_pcre2, PCRE2_CASELESS)) {
1253 merror(REGEX_COMPILE, ARGV0, status_pcre2,
1254 config_ruleinfo->status_pcre2->error);
1258 status_pcre2 = NULL;
1261 /* Add in hostname */
1263 os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname);
1264 if (!OSMatch_Compile(hostname, config_ruleinfo->hostname, 0)) {
1265 merror(REGEX_COMPILE, ARGV0, hostname,
1266 config_ruleinfo->hostname->error);
1272 else if (hostname_pcre2) {
1273 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->hostname_pcre2);
1274 if (!OSPcre2_Compile(hostname_pcre2, config_ruleinfo->hostname_pcre2, PCRE2_CASELESS)) {
1275 merror(REGEX_COMPILE, ARGV0, hostname_pcre2,
1276 config_ruleinfo->hostname_pcre2->error);
1279 free(hostname_pcre2);
1280 hostname_pcre2 = NULL;
1283 /* Add extra data */
1285 os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data);
1286 if (!OSMatch_Compile(extra_data,
1287 config_ruleinfo->extra_data, 0)) {
1288 merror(REGEX_COMPILE, ARGV0, extra_data,
1289 config_ruleinfo->extra_data->error);
1295 else if (extra_data_pcre2) {
1296 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->extra_data_pcre2);
1297 if (!OSPcre2_Compile(extra_data_pcre2,
1298 config_ruleinfo->extra_data_pcre2, PCRE2_CASELESS)) {
1299 merror(REGEX_COMPILE, ARGV0, extra_data_pcre2,
1300 config_ruleinfo->extra_data_pcre2->error);
1303 free(extra_data_pcre2);
1304 extra_data_pcre2 = NULL;
1307 /* Add in program name */
1309 os_calloc(1, sizeof(OSMatch), config_ruleinfo->program_name);
1310 if (!OSMatch_Compile(program_name,
1311 config_ruleinfo->program_name, 0)) {
1312 merror(REGEX_COMPILE, ARGV0, program_name,
1313 config_ruleinfo->program_name->error);
1317 program_name = NULL;
1319 else if (program_name_pcre2) {
1320 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->program_name_pcre2);
1321 if (!OSPcre2_Compile(program_name_pcre2,
1322 config_ruleinfo->program_name_pcre2, PCRE2_CASELESS)) {
1323 merror(REGEX_COMPILE, ARGV0, program_name_pcre2,
1324 config_ruleinfo->program_name_pcre2->error);
1327 free(program_name_pcre2);
1328 program_name_pcre2 = NULL;
1333 os_calloc(1, sizeof(OSMatch), config_ruleinfo->user);
1334 if (!OSMatch_Compile(user, config_ruleinfo->user, 0)) {
1335 merror(REGEX_COMPILE, ARGV0, user,
1336 config_ruleinfo->user->error);
1342 else if (user_pcre2) {
1343 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->user_pcre2);
1344 if (!OSPcre2_Compile(user_pcre2, config_ruleinfo->user_pcre2, PCRE2_CASELESS)) {
1345 merror(REGEX_COMPILE, ARGV0, user_pcre2,
1346 config_ruleinfo->user_pcre2->error);
1353 /* Adding in srcgeoip */
1355 os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcgeoip);
1356 if(!OSMatch_Compile(srcgeoip, config_ruleinfo->srcgeoip, 0)) {
1357 merror(REGEX_COMPILE, ARGV0, srcgeoip,
1358 config_ruleinfo->srcgeoip->error);
1364 else if(srcgeoip_pcre2) {
1365 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->srcgeoip_pcre2);
1366 if(!OSPcre2_Compile(srcgeoip_pcre2, config_ruleinfo->srcgeoip_pcre2, PCRE2_CASELESS)) {
1367 merror(REGEX_COMPILE, ARGV0, srcgeoip_pcre2,
1368 config_ruleinfo->srcgeoip_pcre2->error);
1371 free(srcgeoip_pcre2);
1372 srcgeoip_pcre2 = NULL;
1376 /* Adding in dstgeoip */
1378 os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstgeoip);
1379 if(!OSMatch_Compile(dstgeoip, config_ruleinfo->dstgeoip, 0)) {
1380 merror(REGEX_COMPILE, ARGV0, dstgeoip,
1381 config_ruleinfo->dstgeoip->error);
1387 else if(dstgeoip_pcre2) {
1388 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->dstgeoip_pcre2);
1389 if(!OSPcre2_Compile(dstgeoip_pcre2, config_ruleinfo->dstgeoip_pcre2, PCRE2_CASELESS)) {
1390 merror(REGEX_COMPILE, ARGV0, dstgeoip_pcre2,
1391 config_ruleinfo->dstgeoip_pcre2->error);
1394 free(dstgeoip_pcre2);
1395 dstgeoip_pcre2 = NULL;
1401 os_calloc(1, sizeof(OSMatch), config_ruleinfo->url);
1402 if (!OSMatch_Compile(url, config_ruleinfo->url, 0)) {
1403 merror(REGEX_COMPILE, ARGV0, url,
1404 config_ruleinfo->url->error);
1410 else if (url_pcre2) {
1411 os_calloc(1, sizeof(OSPcre2), config_ruleinfo->url_pcre2);
1412 if (!OSPcre2_Compile(url_pcre2, config_ruleinfo->url_pcre2, PCRE2_CASELESS)) {
1413 merror(REGEX_COMPILE, ARGV0, url_pcre2,
1414 config_ruleinfo->url_pcre2->error);
1421 /* Add matched_group */
1422 if (if_matched_group) {
1423 os_calloc(1, sizeof(OSMatch),
1424 config_ruleinfo->if_matched_group);
1426 if (!OSMatch_Compile(if_matched_group,
1427 config_ruleinfo->if_matched_group,
1429 merror(REGEX_COMPILE, ARGV0, if_matched_group,
1430 config_ruleinfo->if_matched_group->error);
1433 free(if_matched_group);
1434 if_matched_group = NULL;
1437 /* Add matched_regex */
1438 if (if_matched_regex) {
1439 os_calloc(1, sizeof(OSRegex),
1440 config_ruleinfo->if_matched_regex);
1441 if (!OSRegex_Compile(if_matched_regex,
1442 config_ruleinfo->if_matched_regex, 0)) {
1443 merror(REGEX_COMPILE, ARGV0, if_matched_regex,
1444 config_ruleinfo->if_matched_regex->error);
1447 free(if_matched_regex);
1448 if_matched_regex = NULL;
1450 OS_ClearNode(rule_opt);
1451 } /* end of elements block */
1453 /* Assign an active response to the rule */
1454 Rule_AddAR(config_ruleinfo);
1456 j++; /* next rule */
1458 /* Create the last_events if necessary */
1459 if (config_ruleinfo->context) {
1461 os_calloc(MAX_LAST_EVENTS + 1, sizeof(char *),
1462 config_ruleinfo->last_events);
1464 /* Zero each entry */
1465 for (; ii <= MAX_LAST_EVENTS; ii++) {
1466 config_ruleinfo->last_events[ii] = NULL;
1470 /* Add the rule to the rules list.
1471 * Only the template rules are supposed
1472 * to be at the top level. All others
1473 * will be a "child" of someone.
1475 if (config_ruleinfo->sigid < 10) {
1476 OS_AddRule(config_ruleinfo);
1477 } else if (config_ruleinfo->alert_opts & DO_OVERWRITE) {
1478 if (!OS_AddRuleInfo(NULL, config_ruleinfo,
1479 config_ruleinfo->sigid)) {
1480 merror("%s: Overwrite rule '%d' not found.",
1481 ARGV0, config_ruleinfo->sigid);
1486 OS_AddChild(config_ruleinfo);
1489 /* Clean what we do not need */
1490 if (config_ruleinfo->if_group) {
1491 free(config_ruleinfo->if_group);
1492 config_ruleinfo->if_group = NULL;
1495 /* Set the event_search pointer */
1496 if (config_ruleinfo->if_matched_sid) {
1497 config_ruleinfo->event_search = (void *(*)(void *, void *))
1500 /* Mark rules that match this id */
1501 OS_MarkID(NULL, config_ruleinfo);
1504 /* Mark the rules that match if_matched_group */
1505 else if (config_ruleinfo->if_matched_group) {
1507 config_ruleinfo->group_search = OSList_Create();
1508 if (!config_ruleinfo->group_search) {
1509 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
1512 /* Mark rules that match this group */
1513 OS_MarkGroup(NULL, config_ruleinfo);
1515 /* Set function pointer */
1516 config_ruleinfo->event_search = (void *(*)(void *, void *))
1518 } else if (config_ruleinfo->context) {
1519 if ((config_ruleinfo->context == 1) &&
1520 (config_ruleinfo->context_opts & SAME_DODIFF)) {
1521 config_ruleinfo->context = 0;
1523 config_ruleinfo->event_search = (void *(*)(void *, void *))
1528 } /* while(rule[j]) */
1532 } /* while (node[i]) */
1534 /* Clean global node */
1540 RuleNode *dbg_node = OS_GetFirstRule();
1542 if (dbg_node->child) {
1543 RuleNode *child_node = dbg_node->child;
1545 printf("** Child Node for %d **\n", dbg_node->ruleinfo->sigid);
1546 while (child_node) {
1547 child_node = child_node->next;
1550 dbg_node = dbg_node->next;
1555 /* Done over here */
1559 /* Allocate memory at "*at" and copy *str to it.
1560 * If *at already exist, realloc the memory and cat str on it.
1561 * Returns the new string
1563 static char *loadmemory(char *at, const char *str)
1567 if ((strsize = strlen(str)) < OS_SIZE_2048) {
1568 at = (char *) calloc(strsize + 1, sizeof(char));
1570 merror(MEM_ERROR, ARGV0, errno, strerror(errno));
1573 strncpy(at, str, strsize);
1576 merror(SIZE_ERROR, ARGV0, str);
1580 /* at is not null. Need to reallocate its memory and copy str to it */
1581 size_t strsize = strlen(str);
1582 size_t atsize = strlen(at);
1583 size_t finalsize = atsize + strsize + 1;
1585 if ((atsize > OS_SIZE_2048) || (strsize > OS_SIZE_2048)) {
1586 merror(SIZE_ERROR, ARGV0, str);
1590 at = (char *) realloc(at, (finalsize) * sizeof(char));
1593 merror(MEM_ERROR, ARGV0, errno, strerror(errno));
1597 strncat(at, str, strsize);
1598 at[finalsize - 1] = '\0';
1605 RuleInfoDetail *zeroinfodetails(int type, const char *data)
1607 RuleInfoDetail *info_details_pt = NULL;
1609 info_details_pt = (RuleInfoDetail *)calloc(1, sizeof(RuleInfoDetail));
1611 if (info_details_pt == NULL) {
1612 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
1615 info_details_pt->type = type;
1616 os_strdup(data, info_details_pt->data);
1617 info_details_pt->next = NULL;
1619 return (info_details_pt);
1622 RuleInfo *zerorulemember(int id, int level,
1623 int maxsize, int frequency,
1624 int timeframe, int noalert,
1625 int ignore_time, int overwrite)
1627 RuleInfo *ruleinfo_pt = NULL;
1629 /* Allocate memory for structure */
1630 ruleinfo_pt = (RuleInfo *)calloc(1, sizeof(RuleInfo));
1632 if (ruleinfo_pt == NULL) {
1633 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
1636 /* Default values */
1637 ruleinfo_pt->level = level;
1639 /* Default category is syslog */
1640 ruleinfo_pt->category = SYSLOG;
1642 ruleinfo_pt->ar = NULL;
1644 ruleinfo_pt->context = 0;
1646 ruleinfo_pt->sigid = id;
1647 ruleinfo_pt->firedtimes = 0;
1648 ruleinfo_pt->maxsize = maxsize;
1649 ruleinfo_pt->frequency = frequency;
1650 if (ruleinfo_pt->frequency > _max_freq) {
1651 _max_freq = ruleinfo_pt->frequency;
1653 ruleinfo_pt->ignore_time = ignore_time;
1654 ruleinfo_pt->timeframe = timeframe;
1655 ruleinfo_pt->time_ignored = 0;
1657 ruleinfo_pt->context_opts = 0;
1658 ruleinfo_pt->alert_opts = 0;
1659 ruleinfo_pt->ignore = 0;
1660 ruleinfo_pt->ckignore = 0;
1663 ruleinfo_pt->alert_opts |= NO_ALERT;
1665 if (Config.mailbylevel <= level) {
1666 ruleinfo_pt->alert_opts |= DO_MAILALERT;
1668 if (Config.logbylevel <= level) {
1669 ruleinfo_pt->alert_opts |= DO_LOGALERT;
1672 /* Overwrite a rule */
1674 ruleinfo_pt->alert_opts |= DO_OVERWRITE;
1677 ruleinfo_pt->day_time = NULL;
1678 ruleinfo_pt->week_day = NULL;
1680 ruleinfo_pt->group = NULL;
1681 ruleinfo_pt->regex = NULL;
1682 ruleinfo_pt->match = NULL;
1683 ruleinfo_pt->decoded_as = 0;
1685 ruleinfo_pt->comment = NULL;
1686 ruleinfo_pt->info = NULL;
1687 ruleinfo_pt->cve = NULL;
1688 ruleinfo_pt->info_details = NULL;
1690 ruleinfo_pt->if_sid = NULL;
1691 ruleinfo_pt->if_group = NULL;
1692 ruleinfo_pt->if_level = NULL;
1694 ruleinfo_pt->if_matched_regex = NULL;
1695 ruleinfo_pt->if_matched_group = NULL;
1696 ruleinfo_pt->if_matched_sid = 0;
1698 ruleinfo_pt->user = NULL;
1699 ruleinfo_pt->srcip = NULL;
1700 ruleinfo_pt->srcport = NULL;
1701 ruleinfo_pt->dstip = NULL;
1702 ruleinfo_pt->dstport = NULL;
1703 ruleinfo_pt->url = NULL;
1704 ruleinfo_pt->id = NULL;
1705 ruleinfo_pt->status = NULL;
1706 ruleinfo_pt->hostname = NULL;
1707 ruleinfo_pt->program_name = NULL;
1708 ruleinfo_pt->action = NULL;
1709 os_calloc(Config.decoder_order_size, sizeof(FieldInfo*), ruleinfo_pt->fields);
1712 /* Zero last matched events */
1713 ruleinfo_pt->__frequency = 0;
1714 ruleinfo_pt->last_events = NULL;
1716 /* Zeroing the list of previous matches */
1717 ruleinfo_pt->sid_prev_matched = NULL;
1718 ruleinfo_pt->group_prev_matched = NULL;
1720 ruleinfo_pt->sid_search = NULL;
1721 ruleinfo_pt->group_search = NULL;
1723 ruleinfo_pt->event_search = NULL;
1724 ruleinfo_pt->compiled_rule = NULL;
1725 ruleinfo_pt->lists = NULL;
1727 return (ruleinfo_pt);
1730 int get_info_attributes(char **attributes, char **values)
1732 const char *xml_type = "type";
1736 return (RULEINFODETAIL_TEXT);
1739 while (attributes[k]) {
1741 merror("rules_op: Entry info type \"%s\" does not have a value",
1744 } else if (strcasecmp(attributes[k], xml_type) == 0) {
1745 if (strcmp(values[k], "text") == 0) {
1746 return (RULEINFODETAIL_TEXT);
1747 } else if (strcmp(values[k], "link") == 0) {
1748 return (RULEINFODETAIL_LINK);
1749 } else if (strcmp(values[k], "cve") == 0) {
1750 return (RULEINFODETAIL_CVE);
1751 } else if (strcmp(values[k], "osvdb") == 0) {
1752 return (RULEINFODETAIL_OSVDB);
1756 return (RULEINFODETAIL_TEXT);
1759 /* Get the attributes */
1760 static int getattributes(char **attributes, char **values,
1761 int *id, int *level,
1762 int *maxsize, int *timeframe,
1763 int *frequency, int *accuracy,
1764 int *noalert, int *ignore_time, int *overwrite)
1768 const char *xml_id = "id";
1769 const char *xml_level = "level";
1770 const char *xml_maxsize = "maxsize";
1771 const char *xml_timeframe = "timeframe";
1772 const char *xml_frequency = "frequency";
1773 const char *xml_accuracy = "accuracy";
1774 const char *xml_noalert = "noalert";
1775 const char *xml_ignore_time = "ignore";
1776 const char *xml_overwrite = "overwrite";
1778 /* Get attributes */
1779 while (attributes[k]) {
1781 merror("rules_op: Attribute \"%s\" without value."
1786 else if (strcasecmp(attributes[k], xml_id) == 0) {
1787 if (OS_StrIsNum(values[k])) {
1788 sscanf(values[k], "%6d", id);
1790 merror("rules_op: Invalid rule id: %s. "
1797 else if (strcasecmp(attributes[k], xml_level) == 0) {
1798 if (OS_StrIsNum(values[k])) {
1799 sscanf(values[k], "%4d", level);
1801 merror("rules_op: Invalid level: %s. "
1808 else if (strcasecmp(attributes[k], xml_maxsize) == 0) {
1809 if (OS_StrIsNum(values[k])) {
1810 sscanf(values[k], "%4d", maxsize);
1812 merror("rules_op: Invalid maxsize: %s. "
1819 else if (strcasecmp(attributes[k], xml_timeframe) == 0) {
1820 if (OS_StrIsNum(values[k])) {
1821 sscanf(values[k], "%5d", timeframe);
1823 merror("rules_op: Invalid timeframe: %s. "
1830 else if (strcasecmp(attributes[k], xml_frequency) == 0) {
1831 if (OS_StrIsNum(values[k])) {
1832 sscanf(values[k], "%4d", frequency);
1834 merror("rules_op: Invalid frequency: %s. "
1841 else if (strcasecmp(attributes[k], xml_accuracy) == 0) {
1842 if (OS_StrIsNum(values[k])) {
1843 sscanf(values[k], "%4d", accuracy);
1845 merror("rules_op: Invalid accuracy: %s. "
1851 /* Rule ignore_time */
1852 else if (strcasecmp(attributes[k], xml_ignore_time) == 0) {
1853 if (OS_StrIsNum(values[k])) {
1854 sscanf(values[k], "%6d", ignore_time);
1856 merror("rules_op: Invalid ignore_time: %s. "
1863 else if (strcasecmp(attributes[k], xml_noalert) == 0) {
1865 } else if (strcasecmp(attributes[k], xml_overwrite) == 0) {
1866 if (strcmp(values[k], "yes") == 0) {
1868 } else if (strcmp(values[k], "no") == 0) {
1871 merror("rules_op: Invalid overwrite: %s. "
1872 "Can only by 'yes' or 'no'.", values[k]);
1876 merror("rules_op: Invalid attribute \"%s\". "
1877 "Only id, level, maxsize, accuracy, noalert and timeframe "
1878 "are allowed.", attributes[k]);
1886 /* Bind active responses to a rule */
1887 static void Rule_AddAR(RuleInfo *rule_config)
1889 unsigned int rule_ar_size = 0;
1891 int rule_real_level = 0;
1893 OSListNode *my_ars_node;
1895 /* Set the correct levels
1896 * We play internally with the rules, to set
1897 * the priorities... Rules with 0 of accuracy,
1898 * receive a low level and go down in the list
1900 if (rule_config->level == 9900) {
1901 rule_real_level = 0;
1904 else if (rule_config->level >= 100) {
1905 rule_real_level = rule_config->level / 100;
1908 /* No AR for ignored rules */
1909 if (rule_real_level == 0) {
1913 /* No AR when options no_ar is set */
1914 if (rule_config->alert_opts & NO_AR) {
1918 if (!active_responses) {
1922 /* Loop on all AR */
1923 my_ars_node = OSList_GetFirstNode(active_responses);
1924 while (my_ars_node) {
1925 active_response *my_ar;
1928 my_ar = (active_response *)my_ars_node->data;
1931 /* Check if the level for the ar is higher */
1933 if (rule_real_level >= my_ar->level) {
1938 /* Check if group matches */
1939 if (my_ar->rules_group) {
1940 if (OS_Regex(my_ar->rules_group, rule_config->group)) {
1945 /* Check if rule id matches */
1946 if (my_ar->rules_id) {
1948 char *str_pt = my_ar->rules_id;
1950 while (*str_pt != '\0') {
1951 /* We allow spaces in between */
1952 if (*str_pt == ' ') {
1957 /* If is digit, we get the value
1958 * and search for the next digit
1961 else if (isdigit((int)*str_pt)) {
1962 r_id = atoi(str_pt);
1964 /* mark to ar if id matches */
1965 if (r_id == rule_config->sigid) {
1969 str_pt = strchr(str_pt, ',');
1977 /* Check for duplicate commas */
1978 else if (*str_pt == ',') {
1987 } /* eof of rules_id */
1989 /* Bind AR to the rule */
1990 if (mark_to_ar == 1) {
1993 rule_config->ar = (active_response **) realloc(rule_config->ar,
1995 * sizeof(active_response *));
1997 /* Always set the last node to NULL */
1998 rule_config->ar[rule_ar_size - 1] = my_ar;
1999 rule_config->ar[rule_ar_size] = NULL;
2002 my_ars_node = OSList_GetNextNode(active_responses);
2008 static void printRuleinfo(const RuleInfo *rule, int node)
2010 debug1("%d : rule:%d, level %d, timeout: %d",
2017 /* Add rule to hash */
2018 int AddHash_Rule(RuleNode *node)
2023 snprintf(id_key, 14, "%d", node->ruleinfo->sigid);
2025 /* Add key to hash */
2026 OSHash_Add(Config.g_rules_hash, id_key, node->ruleinfo);
2028 AddHash_Rule(node->child);
2037 int _setlevels(RuleNode *node, int nnode)
2041 if (node->ruleinfo->level == 9900) {
2042 node->ruleinfo->level = 0;
2045 if (node->ruleinfo->level >= 100) {
2046 node->ruleinfo->level /= 100;
2051 /* Rule information */
2052 printRuleinfo(node->ruleinfo, nnode);
2056 chl_size = _setlevels(node->child, nnode + 1);
2067 /* Test if a rule id exists
2068 * return 1 if exists, otherwise 0
2070 static int doesRuleExist(int sid, RuleNode *r_node)
2072 /* Start from the beginning of the list by default */
2074 r_node = OS_GetFirstRule();
2078 /* Check if the sigid matches */
2079 if (r_node->ruleinfo->sigid == sid) {
2083 /* Check if the rule has a child */
2084 if (r_node->child) {
2085 /* Check recursively */
2086 if (doesRuleExist(sid, r_node->child)) {
2091 /* Go to the next rule */
2092 r_node = r_node->next;