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 /* Change path for test rule */
15 #define RULEPATH "rules/"
19 static int _OS_GetRulesAttributes(char **attributes,
21 RuleInfo *ruleinfo_pt) __attribute__((nonnull));
22 static RuleInfo *_OS_AllocateRule(void);
25 /* Read the log rules */
26 int OS_ReadXMLRules(const char *rulefile,
27 void *(*ruleact_function)(RuleInfo *rule_1, void *data_1),
34 /* These are the available options for the rule configuration */
36 const char *xml_group = "group";
37 const char *xml_rule = "rule";
39 const char *xml_regex = "regex";
40 const char *xml_match = "match";
41 const char *xml_decoded = "decoded_as";
42 const char *xml_category = "category";
43 const char *xml_cve = "cve";
44 const char *xml_info = "info";
45 const char *xml_day_time = "time";
46 const char *xml_week_day = "weekday";
47 const char *xml_comment = "description";
48 const char *xml_ignore = "ignore";
49 const char *xml_check_if_ignored = "check_if_ignored";
51 const char *xml_srcip = "srcip";
52 const char *xml_srcport = "srcport";
53 const char *xml_dstip = "dstip";
54 const char *xml_dstport = "dstport";
55 const char *xml_user = "user";
56 const char *xml_url = "url";
57 const char *xml_id = "id";
58 const char *xml_data = "extra_data";
59 const char *xml_hostname = "hostname";
60 const char *xml_program_name = "program_name";
61 const char *xml_status = "status";
62 const char *xml_action = "action";
63 const char *xml_compiled = "compiled_rule";
65 const char *xml_if_sid = "if_sid";
66 const char *xml_if_group = "if_group";
67 const char *xml_if_level = "if_level";
68 const char *xml_fts = "if_fts";
70 const char *xml_if_matched_regex = "if_matched_regex";
71 const char *xml_if_matched_group = "if_matched_group";
72 const char *xml_if_matched_sid = "if_matched_sid";
74 const char *xml_same_source_ip = "same_source_ip";
75 const char *xml_same_src_port = "same_src_port";
76 const char *xml_same_dst_port = "same_dst_port";
77 const char *xml_same_user = "same_user";
78 const char *xml_same_location = "same_location";
79 const char *xml_same_id = "same_id";
80 const char *xml_dodiff = "check_diff";
82 const char *xml_different_url = "different_url";
84 const char *xml_notsame_source_ip = "not_same_source_ip";
85 const char *xml_notsame_user = "not_same_user";
86 const char *xml_notsame_agent = "not_same_agent";
87 const char *xml_notsame_id = "not_same_id";
89 const char *xml_options = "options";
95 /* If no directory in the rulefile, add the default */
96 if ((strchr(rulefile, '/')) == NULL) {
97 /* Build the rule file name + path */
98 i = strlen(RULEPATH) + strlen(rulefile) + 2;
99 rulepath = (char *)calloc(i, sizeof(char));
101 ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
103 snprintf(rulepath, i, "%s/%s", RULEPATH, rulefile);
105 os_strdup(rulefile, rulepath);
106 debug1("%s is the rulefile", rulefile);
107 debug1("Not modifing the rule path");
111 if (OS_ReadXML(rulepath, &xml) < 0) {
112 merror(XML_ERROR, __local_name, rulepath, xml.err, xml.err_line);
116 debug1("%s: DEBUG: read xml for rule '%s'.", __local_name, rulepath);
118 /* Apply any variables found */
119 if (OS_ApplyVariables(&xml) != 0) {
120 merror(XML_ERROR_VAR, __local_name, rulepath, xml.err);
126 debug1("%s: DEBUG: XML Variables applied.", __local_name);
128 /* Get the root elements */
129 node = OS_GetElementsbyNode(&xml, NULL);
131 merror(CONFIG_ERROR, __local_name, rulepath);
139 /* Zero the rule memory -- not used anymore */
142 /* Check if there is any invalid global option */
145 if (node[i]->element) {
147 if (strcasecmp(node[i]->element, xml_group) != 0) {
148 merror(RL_INV_ROOT, __local_name, node[i]->element);
152 /* Check group attribute -- only name is allowed */
153 if ((!node[i]->attributes) || (!node[i]->values) ||
154 (!node[i]->values[0]) || (!node[i]->attributes[0]) ||
155 (strcasecmp(node[i]->attributes[0], "name") != 0) ||
156 (node[i]->attributes[1])) {
157 merror(RL_INV_ROOT, __local_name, node[i]->element);
162 merror(XML_READ_ERROR, __local_name);
173 XML_NODE rule = NULL;
175 /* Get all rules for a global group */
176 rule = OS_GetElementsbyNode(&xml, node[i]);
182 /* Loop over the rules node */
186 char *regex = NULL, *match = NULL, *url = NULL,
187 *if_matched_regex = NULL, *if_matched_group = NULL,
188 *user = NULL, *id = NULL, *srcport = NULL,
189 *dstport = NULL, *status = NULL, *hostname = NULL,
190 *extra_data = NULL, *program_name = NULL;
192 RuleInfo *config_ruleinfo = NULL;
193 XML_NODE rule_opt = NULL;
195 /* Check if the rule element is correct */
196 if ((!rule[j]->element) ||
197 (strcasecmp(rule[j]->element, xml_rule) != 0)) {
198 merror(RL_INV_RULE, __local_name, node[i]->element);
203 /* Check for the attributes of the rule */
204 if ((!rule[j]->attributes) || (!rule[j]->values)) {
205 merror(RL_INV_RULE, __local_name, rulefile);
210 /* Attribute block */
211 config_ruleinfo = _OS_AllocateRule();
213 if (_OS_GetRulesAttributes(rule[j]->attributes, rule[j]->values,
214 config_ruleinfo) < 0) {
215 merror(RL_INV_ATTR, __local_name, rulefile);
220 /* We must have an id or level */
221 if ((config_ruleinfo->sigid == -1) || (config_ruleinfo->level == -1)) {
222 merror(RL_INV_ATTR, __local_name, rulefile);
227 /* Assign the group name to the rule. The level is correct so
228 * the rule is probably going to be fine.
230 os_strdup(node[i]->values[0], config_ruleinfo->group);
232 /* Get rules options */
233 rule_opt = OS_GetElementsbyNode(&xml, rule[j]);
234 if (rule_opt == NULL) {
235 merror(RL_NO_OPT, __local_name, config_ruleinfo->sigid);
240 /* Read the whole rule block */
241 while (rule_opt[k]) {
242 if ((!rule_opt[k]->element) || (!rule_opt[k]->content)) {
244 } else if (strcasecmp(rule_opt[k]->element, xml_regex) == 0) {
247 rule_opt[k]->content);
248 } else if (strcasecmp(rule_opt[k]->element, xml_match) == 0) {
251 rule_opt[k]->content);
252 } else if (strcasecmp(rule_opt[k]->element, xml_decoded) == 0) {
253 } else if (strcasecmp(rule_opt[k]->element, xml_info) == 0) {
254 config_ruleinfo->info =
255 os_LoadString(config_ruleinfo->info,
256 rule_opt[k]->content);
257 } else if (strcasecmp(rule_opt[k]->element, xml_day_time) == 0) {
258 config_ruleinfo->day_time =
259 OS_IsValidTime(rule_opt[k]->content);
260 if (!config_ruleinfo->day_time) {
261 merror(INVALID_CONFIG, __local_name,
262 rule_opt[k]->element,
263 rule_opt[k]->content);
267 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
268 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
270 } else if (strcasecmp(rule_opt[k]->element, xml_week_day) == 0) {
271 config_ruleinfo->week_day =
272 OS_IsValidDay(rule_opt[k]->content);
274 if (!config_ruleinfo->week_day) {
275 merror(INVALID_CONFIG, __local_name,
276 rule_opt[k]->element,
277 rule_opt[k]->content);
280 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
281 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
283 } else if (strcasecmp(rule_opt[k]->element, xml_group) == 0) {
284 config_ruleinfo->group =
285 os_LoadString(config_ruleinfo->group,
286 rule_opt[k]->content);
287 } else if (strcasecmp(rule_opt[k]->element, xml_cve) == 0) {
288 config_ruleinfo->cve =
289 os_LoadString(config_ruleinfo->cve,
290 rule_opt[k]->content);
291 } else if (strcasecmp(rule_opt[k]->element, xml_comment) == 0) {
294 newline = strchr(rule_opt[k]->content, '\n');
298 config_ruleinfo->comment =
299 os_LoadString(config_ruleinfo->comment,
300 rule_opt[k]->content);
301 } else if (strcasecmp(rule_opt[k]->element, xml_srcip) == 0) {
304 /* Get size of source IP list */
305 while (config_ruleinfo->srcip &&
306 config_ruleinfo->srcip[ip_s]) {
310 config_ruleinfo->srcip = (os_ip **)
311 realloc(config_ruleinfo->srcip,
312 (ip_s + 2) * sizeof(os_ip *));
314 /* Allocate memory for the individual entries */
315 os_calloc(1, sizeof(os_ip),
316 config_ruleinfo->srcip[ip_s]);
317 config_ruleinfo->srcip[ip_s + 1] = NULL;
319 /* Check if the IP is valid */
320 if (!OS_IsValidIP(rule_opt[k]->content,
321 config_ruleinfo->srcip[ip_s])) {
322 merror(INVALID_IP, __local_name, rule_opt[k]->content);
326 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
327 config_ruleinfo->alert_opts |= DO_PACKETINFO;
329 } else if (strcasecmp(rule_opt[k]->element, xml_dstip) == 0) {
332 /* Get size of destination IP list */
333 while (config_ruleinfo->dstip &&
334 config_ruleinfo->dstip[ip_s]) {
338 config_ruleinfo->dstip = (os_ip **)
339 realloc(config_ruleinfo->dstip,
340 (ip_s + 2) * sizeof(os_ip *));
342 /* Allocate memory for the individual entries */
343 os_calloc(1, sizeof(os_ip),
344 config_ruleinfo->dstip[ip_s]);
345 config_ruleinfo->dstip[ip_s + 1] = NULL;
347 /* Checking if the IP is valid */
348 if (!OS_IsValidIP(rule_opt[k]->content,
349 config_ruleinfo->dstip[ip_s])) {
350 merror(INVALID_IP, __local_name, rule_opt[k]->content);
354 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
355 config_ruleinfo->alert_opts |= DO_PACKETINFO;
357 } else if (strcasecmp(rule_opt[k]->element, xml_user) == 0) {
358 user = os_LoadString(user, rule_opt[k]->content);
360 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
361 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
363 } else if (strcasecmp(rule_opt[k]->element, xml_id) == 0) {
364 id = os_LoadString(id, rule_opt[k]->content);
365 } else if (strcasecmp(rule_opt[k]->element, xml_srcport) == 0) {
366 srcport = os_LoadString(srcport, rule_opt[k]->content);
368 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
369 config_ruleinfo->alert_opts |= DO_PACKETINFO;
371 } else if (strcasecmp(rule_opt[k]->element, xml_dstport) == 0) {
372 dstport = os_LoadString(dstport, rule_opt[k]->content);
374 if (!(config_ruleinfo->alert_opts & DO_PACKETINFO)) {
375 config_ruleinfo->alert_opts |= DO_PACKETINFO;
377 } else if (strcasecmp(rule_opt[k]->element, xml_status) == 0) {
378 status = os_LoadString(status, rule_opt[k]->content);
380 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
381 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
383 } else if (strcasecmp(rule_opt[k]->element, xml_hostname) == 0) {
384 hostname = os_LoadString(hostname, rule_opt[k]->content);
386 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
387 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
389 } else if (strcasecmp(rule_opt[k]->element, xml_data) == 0) {
390 extra_data = os_LoadString(extra_data, rule_opt[k]->content);
392 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
393 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
395 } else if (strcasecmp(rule_opt[k]->element,
396 xml_program_name) == 0) {
397 program_name = os_LoadString(program_name,
398 rule_opt[k]->content);
399 } else if (strcasecmp(rule_opt[k]->element, xml_action) == 0) {
400 config_ruleinfo->action =
401 os_LoadString(config_ruleinfo->action,
402 rule_opt[k]->content);
403 } else if (strcasecmp(rule_opt[k]->element, xml_url) == 0) {
404 url = os_LoadString(url, rule_opt[k]->content);
407 else if (strcasecmp(rule_opt[k]->element, xml_compiled) == 0) {
408 /* Not using this in here */
411 /* We allow these categories so far */
412 else if (strcasecmp(rule_opt[k]->element, xml_category) == 0) {
413 if (strcmp(rule_opt[k]->content, "firewall") == 0) {
414 config_ruleinfo->category = FIREWALL;
415 } else if (strcmp(rule_opt[k]->content, "ids") == 0) {
416 config_ruleinfo->category = IDS;
417 } else if (strcmp(rule_opt[k]->content, "syslog") == 0) {
418 config_ruleinfo->category = SYSLOG;
419 } else if (strcmp(rule_opt[k]->content, "web-log") == 0) {
420 config_ruleinfo->category = WEBLOG;
421 } else if (strcmp(rule_opt[k]->content, "squid") == 0) {
422 config_ruleinfo->category = SQUID;
423 } else if (strcmp(rule_opt[k]->content, "windows") == 0) {
424 config_ruleinfo->category = DECODER_WINDOWS;
425 } else if (strcmp(rule_opt[k]->content, "ossec") == 0) {
426 config_ruleinfo->category = OSSEC_RL;
428 merror(INVALID_CAT, __local_name, rule_opt[k]->content);
431 } else if (strcasecmp(rule_opt[k]->element, xml_if_sid) == 0) {
432 config_ruleinfo->if_sid =
433 os_LoadString(config_ruleinfo->if_sid,
434 rule_opt[k]->content);
435 } else if (strcasecmp(rule_opt[k]->element, xml_if_level) == 0) {
436 if (!OS_StrIsNum(rule_opt[k]->content)) {
437 merror(INVALID_CONFIG, __local_name,
439 rule_opt[k]->content);
443 config_ruleinfo->if_level =
444 os_LoadString(config_ruleinfo->if_level,
445 rule_opt[k]->content);
446 } else if (strcasecmp(rule_opt[k]->element, xml_if_group) == 0) {
447 config_ruleinfo->if_group =
448 os_LoadString(config_ruleinfo->if_group,
449 rule_opt[k]->content);
450 } else if (strcasecmp(rule_opt[k]->element,
451 xml_if_matched_regex) == 0) {
452 config_ruleinfo->context = 1;
454 os_LoadString(if_matched_regex,
455 rule_opt[k]->content);
456 } else if (strcasecmp(rule_opt[k]->element,
457 xml_if_matched_group) == 0) {
458 config_ruleinfo->context = 1;
460 os_LoadString(if_matched_group,
461 rule_opt[k]->content);
462 } else if (strcasecmp(rule_opt[k]->element,
463 xml_if_matched_sid) == 0) {
464 config_ruleinfo->context = 1;
465 if (!OS_StrIsNum(rule_opt[k]->content)) {
466 merror(INVALID_CONFIG, __local_name,
467 rule_opt[k]->element,
468 rule_opt[k]->content);
471 config_ruleinfo->if_matched_sid =
472 atoi(rule_opt[k]->content);
474 } else if (strcasecmp(rule_opt[k]->element,
475 xml_same_source_ip) == 0) {
476 config_ruleinfo->context_opts |= SAME_SRCIP;
477 } else if (strcasecmp(rule_opt[k]->element,
478 xml_same_src_port) == 0) {
479 config_ruleinfo->context_opts |= SAME_SRCPORT;
481 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
482 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
484 } else if (strcasecmp(rule_opt[k]->element,
486 config_ruleinfo->context++;
487 config_ruleinfo->context_opts |= SAME_DODIFF;
488 if (!(config_ruleinfo->alert_opts & DO_EXTRAINFO)) {
489 config_ruleinfo->alert_opts |= DO_EXTRAINFO;
491 } else if (strcasecmp(rule_opt[k]->element,
492 xml_same_dst_port) == 0) {
493 config_ruleinfo->context_opts |= SAME_DSTPORT;
495 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
496 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
498 } else if (strcasecmp(rule_opt[k]->element,
499 xml_notsame_source_ip) == 0) {
500 config_ruleinfo->context_opts &= NOT_SAME_SRCIP;
501 } else if (strcmp(rule_opt[k]->element, xml_same_id) == 0) {
502 config_ruleinfo->context_opts |= SAME_ID;
503 } else if (strcmp(rule_opt[k]->element,
504 xml_different_url) == 0) {
505 config_ruleinfo->context_opts |= DIFFERENT_URL;
507 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
508 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
510 } else if (strcmp(rule_opt[k]->element, xml_notsame_id) == 0) {
511 config_ruleinfo->context_opts &= NOT_SAME_ID;
512 } else if (strcasecmp(rule_opt[k]->element,
514 config_ruleinfo->alert_opts |= DO_FTS;
515 } else if (strcasecmp(rule_opt[k]->element,
516 xml_same_user) == 0) {
517 config_ruleinfo->context_opts |= SAME_USER;
519 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
520 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
522 } else if (strcasecmp(rule_opt[k]->element,
523 xml_notsame_user) == 0) {
524 config_ruleinfo->context_opts &= NOT_SAME_USER;
525 } else if (strcasecmp(rule_opt[k]->element,
526 xml_same_location) == 0) {
527 config_ruleinfo->context_opts |= SAME_LOCATION;
528 if (!(config_ruleinfo->alert_opts & SAME_EXTRAINFO)) {
529 config_ruleinfo->alert_opts |= SAME_EXTRAINFO;
531 } else if (strcasecmp(rule_opt[k]->element,
532 xml_notsame_agent) == 0) {
533 config_ruleinfo->context_opts &= NOT_SAME_AGENT;
534 } else if (strcasecmp(rule_opt[k]->element,
536 if (strcmp("alert_by_email",
537 rule_opt[k]->content) == 0) {
538 if (!(config_ruleinfo->alert_opts & DO_MAILALERT)) {
539 config_ruleinfo->alert_opts |= DO_MAILALERT;
541 } else if (strcmp("no_email_alert",
542 rule_opt[k]->content) == 0) {
543 if (config_ruleinfo->alert_opts & DO_MAILALERT) {
544 config_ruleinfo->alert_opts &= 0xfff - DO_MAILALERT;
546 } else if (strcmp("log_alert",
547 rule_opt[k]->content) == 0) {
548 if (!(config_ruleinfo->alert_opts & DO_LOGALERT)) {
549 config_ruleinfo->alert_opts |= DO_LOGALERT;
551 } else if (strcmp("no_log", rule_opt[k]->content) == 0) {
552 if (config_ruleinfo->alert_opts & DO_LOGALERT) {
553 config_ruleinfo->alert_opts &= 0xfff - DO_LOGALERT;
555 } else if (strcmp("no_ar", rule_opt[k]->content) == 0) {
556 if (!(config_ruleinfo->alert_opts & NO_AR)) {
557 config_ruleinfo->alert_opts |= NO_AR;
560 merror(XML_VALUEERR, __local_name, xml_options,
561 rule_opt[k]->content);
563 merror(INVALID_ELEMENT, __local_name,
564 rule_opt[k]->element,
565 rule_opt[k]->content);
569 } else if (strcasecmp(rule_opt[k]->element,
571 if (strstr(rule_opt[k]->content, "user") != NULL) {
572 config_ruleinfo->ignore |= FTS_USER;
574 if (strstr(rule_opt[k]->content, "srcip") != NULL) {
575 config_ruleinfo->ignore |= FTS_SRCIP;
577 if (strstr(rule_opt[k]->content, "dstip") != NULL) {
578 config_ruleinfo->ignore |= FTS_DSTIP;
580 if (strstr(rule_opt[k]->content, "id") != NULL) {
581 config_ruleinfo->ignore |= FTS_ID;
583 if (strstr(rule_opt[k]->content, "location") != NULL) {
584 config_ruleinfo->ignore |= FTS_LOCATION;
586 if (strstr(rule_opt[k]->content, "data") != NULL) {
587 config_ruleinfo->ignore |= FTS_DATA;
589 if (strstr(rule_opt[k]->content, "name") != NULL) {
590 config_ruleinfo->ignore |= FTS_NAME;
593 if (!config_ruleinfo->ignore) {
594 merror(INVALID_ELEMENT, __local_name,
595 rule_opt[k]->element,
596 rule_opt[k]->content);
600 } else if (strcasecmp(rule_opt[k]->element,
601 xml_check_if_ignored) == 0) {
602 if (strstr(rule_opt[k]->content, "user") != NULL) {
603 config_ruleinfo->ckignore |= FTS_USER;
605 if (strstr(rule_opt[k]->content, "srcip") != NULL) {
606 config_ruleinfo->ckignore |= FTS_SRCIP;
608 if (strstr(rule_opt[k]->content, "dstip") != NULL) {
609 config_ruleinfo->ckignore |= FTS_DSTIP;
611 if (strstr(rule_opt[k]->content, "id") != NULL) {
612 config_ruleinfo->ckignore |= FTS_ID;
614 if (strstr(rule_opt[k]->content, "location") != NULL) {
615 config_ruleinfo->ckignore |= FTS_LOCATION;
617 if (strstr(rule_opt[k]->content, "data") != NULL) {
618 config_ruleinfo->ckignore |= FTS_DATA;
620 if (strstr(rule_opt[k]->content, "name") != NULL) {
621 config_ruleinfo->ckignore |= FTS_NAME;
624 if (!config_ruleinfo->ckignore) {
625 merror(INVALID_ELEMENT, __local_name,
626 rule_opt[k]->element,
627 rule_opt[k]->content);
632 /* XXX As new features are added into ../analysisd/rules.c
633 * This code needs to be updated to match, but is out of date
634 * it's become a nightmare to correct with out just make the
635 * problem for someone later.
637 * This hack will allow any crap xml to pass without an
638 * error. The correct fix is to refactor the code so that
639 * ../analysisd/rules* and this code are not duplicates
643 merror(XML_INVELEM, __local_name, rule_opt[k]->element);
652 /* Check for a valid use of frequency */
653 if ((config_ruleinfo->context_opts ||
654 config_ruleinfo->frequency) &&
655 !config_ruleinfo->context) {
656 merror("%s: Invalid use of frequency/context options. "
657 "Missing if_matched on rule '%d'.",
658 __local_name, config_ruleinfo->sigid);
663 /* If if_matched_group we must have a if_sid or if_group */
664 if (if_matched_group) {
665 if (!config_ruleinfo->if_sid && !config_ruleinfo->if_group) {
666 os_strdup(if_matched_group, config_ruleinfo->if_group);
670 /* If_matched_sid, we need to get the if_sid */
671 if (config_ruleinfo->if_matched_sid &&
672 !config_ruleinfo->if_sid &&
673 !config_ruleinfo->if_group) {
674 os_calloc(16, sizeof(char), config_ruleinfo->if_sid);
675 snprintf(config_ruleinfo->if_sid, 15, "%d",
676 config_ruleinfo->if_matched_sid);
679 /* Check the regexes */
681 os_calloc(1, sizeof(OSRegex), config_ruleinfo->regex);
682 if (!OSRegex_Compile(regex, config_ruleinfo->regex, 0)) {
683 merror(REGEX_COMPILE, __local_name, regex,
684 config_ruleinfo->regex->error);
696 os_calloc(1, sizeof(OSMatch), config_ruleinfo->match);
697 if (!OSMatch_Compile(match, config_ruleinfo->match, 0)) {
698 merror(REGEX_COMPILE, __local_name, match,
699 config_ruleinfo->match->error);
711 os_calloc(1, sizeof(OSMatch), config_ruleinfo->id);
712 if (!OSMatch_Compile(id, config_ruleinfo->id, 0)) {
713 merror(REGEX_COMPILE, __local_name, id,
714 config_ruleinfo->id->error);
726 os_calloc(1, sizeof(OSMatch), config_ruleinfo->srcport);
727 if (!OSMatch_Compile(srcport, config_ruleinfo->srcport, 0)) {
728 merror(REGEX_COMPILE, __local_name, srcport,
729 config_ruleinfo->id->error);
741 os_calloc(1, sizeof(OSMatch), config_ruleinfo->dstport);
742 if (!OSMatch_Compile(dstport, config_ruleinfo->dstport, 0)) {
743 merror(REGEX_COMPILE, __local_name, dstport,
744 config_ruleinfo->id->error);
756 os_calloc(1, sizeof(OSMatch), config_ruleinfo->status);
757 if (!OSMatch_Compile(status, config_ruleinfo->status, 0)) {
758 merror(REGEX_COMPILE, __local_name, status,
759 config_ruleinfo->status->error);
771 os_calloc(1, sizeof(OSMatch), config_ruleinfo->hostname);
772 if (!OSMatch_Compile(hostname, config_ruleinfo->hostname, 0)) {
773 merror(REGEX_COMPILE, __local_name, hostname,
774 config_ruleinfo->hostname->error);
786 os_calloc(1, sizeof(OSMatch), config_ruleinfo->extra_data);
787 if (!OSMatch_Compile(extra_data,
788 config_ruleinfo->extra_data, 0)) {
789 merror(REGEX_COMPILE, __local_name, extra_data,
790 config_ruleinfo->extra_data->error);
800 /* Add in program name */
802 os_calloc(1, sizeof(OSMatch), config_ruleinfo->program_name);
803 if (!OSMatch_Compile(program_name,
804 config_ruleinfo->program_name, 0)) {
805 merror(REGEX_COMPILE, __local_name, program_name,
806 config_ruleinfo->program_name->error);
818 os_calloc(1, sizeof(OSMatch), config_ruleinfo->user);
819 if (!OSMatch_Compile(user, config_ruleinfo->user, 0)) {
820 merror(REGEX_COMPILE, __local_name, user,
821 config_ruleinfo->user->error);
833 os_calloc(1, sizeof(OSMatch), config_ruleinfo->url);
834 if (!OSMatch_Compile(url, config_ruleinfo->url, 0)) {
835 merror(REGEX_COMPILE, __local_name, url,
836 config_ruleinfo->url->error);
846 /* Add matched_group */
847 if (if_matched_group) {
848 os_calloc(1, sizeof(OSMatch), config_ruleinfo->if_matched_group);
850 if (!OSMatch_Compile(if_matched_group,
851 config_ruleinfo->if_matched_group, 0)) {
852 merror(REGEX_COMPILE, __local_name, if_matched_group,
853 config_ruleinfo->if_matched_group->error);
856 free(if_matched_group);
857 if_matched_group = NULL;
860 /* Add matched_regex */
861 if (if_matched_regex) {
862 os_calloc(1, sizeof(OSRegex),
863 config_ruleinfo->if_matched_regex);
864 if (!OSRegex_Compile(if_matched_regex,
865 config_ruleinfo->if_matched_regex, 0)) {
866 merror(REGEX_COMPILE, __local_name, if_matched_regex,
867 config_ruleinfo->if_matched_regex->error);
868 if (if_matched_regex) {
869 free(if_matched_regex);
873 free(if_matched_regex);
874 if_matched_regex = NULL;
877 /* Call the function provided */
878 ruleact_function(config_ruleinfo, data);
882 } /* while(rule[j]) */
886 } /* while (node[i]) */
888 /* Clean global node */
895 /* Allocate memory for a rule */
896 static RuleInfo *_OS_AllocateRule()
898 RuleInfo *ruleinfo_pt = NULL;
900 /* Allocate memory for structure */
901 ruleinfo_pt = (RuleInfo *)calloc(1, sizeof(RuleInfo));
902 if (ruleinfo_pt == NULL) {
903 ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
907 ruleinfo_pt->level = -1;
909 /* Default category is syslog */
910 ruleinfo_pt->category = SYSLOG;
912 ruleinfo_pt->ar = NULL;
914 ruleinfo_pt->context = 0;
916 /* Default sigid of -1 */
917 ruleinfo_pt->sigid = -1;
918 ruleinfo_pt->firedtimes = 0;
919 ruleinfo_pt->maxsize = 0;
920 ruleinfo_pt->frequency = 0;
921 ruleinfo_pt->ignore_time = 0;
922 ruleinfo_pt->timeframe = 0;
923 ruleinfo_pt->time_ignored = 0;
925 ruleinfo_pt->context_opts = 0;
926 ruleinfo_pt->alert_opts = 0;
927 ruleinfo_pt->ignore = 0;
928 ruleinfo_pt->ckignore = 0;
930 ruleinfo_pt->day_time = NULL;
931 ruleinfo_pt->week_day = NULL;
933 ruleinfo_pt->group = NULL;
934 ruleinfo_pt->regex = NULL;
935 ruleinfo_pt->match = NULL;
936 ruleinfo_pt->decoded_as = 0;
938 ruleinfo_pt->comment = NULL;
939 ruleinfo_pt->info = NULL;
940 ruleinfo_pt->cve = NULL;
942 ruleinfo_pt->if_sid = NULL;
943 ruleinfo_pt->if_group = NULL;
944 ruleinfo_pt->if_level = NULL;
946 ruleinfo_pt->if_matched_regex = NULL;
947 ruleinfo_pt->if_matched_group = NULL;
948 ruleinfo_pt->if_matched_sid = 0;
950 ruleinfo_pt->user = NULL;
951 ruleinfo_pt->srcip = NULL;
952 ruleinfo_pt->srcport = NULL;
953 ruleinfo_pt->dstip = NULL;
954 ruleinfo_pt->dstport = NULL;
955 ruleinfo_pt->url = NULL;
956 ruleinfo_pt->id = NULL;
957 ruleinfo_pt->status = NULL;
958 ruleinfo_pt->hostname = NULL;
959 ruleinfo_pt->program_name = NULL;
960 ruleinfo_pt->action = NULL;
962 /* Zero last matched events */
963 ruleinfo_pt->__frequency = 0;
964 ruleinfo_pt->last_events = NULL;
966 /* Zero the list of previous matches */
967 ruleinfo_pt->sid_prev_matched = NULL;
968 ruleinfo_pt->group_prev_matched = NULL;
970 ruleinfo_pt->sid_search = NULL;
971 ruleinfo_pt->group_search = NULL;
973 ruleinfo_pt->event_search = NULL;
975 return (ruleinfo_pt);
978 /* Reads the rules attributes and assign them */
979 static int _OS_GetRulesAttributes(char **attributes, char **values,
980 RuleInfo *ruleinfo_pt)
984 const char *xml_id = "id";
985 const char *xml_level = "level";
986 const char *xml_maxsize = "maxsize";
987 const char *xml_timeframe = "timeframe";
988 const char *xml_frequency = "frequency";
989 const char *xml_accuracy = "accuracy";
990 const char *xml_noalert = "noalert";
991 const char *xml_ignore_time = "ignore";
992 const char *xml_overwrite = "overwrite";
995 while (attributes[k]) {
997 merror(RL_EMPTY_ATTR, __local_name, attributes[k]);
1001 else if (strcasecmp(attributes[k], xml_id) == 0) {
1002 if (OS_StrIsNum(values[k]) && (strlen(values[k]) <= 6 )) {
1003 ruleinfo_pt->sigid = atoi(values[k]);
1005 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1010 else if (strcasecmp(attributes[k], xml_level) == 0) {
1011 if (OS_StrIsNum(values[k]) && (strlen(values[k]) <= 3)) {
1012 ruleinfo_pt->level = atoi(values[k]);
1014 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1019 else if (strcasecmp(attributes[k], xml_maxsize) == 0) {
1020 if (OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4)) {
1021 ruleinfo_pt->maxsize = atoi(values[k]);
1023 /* Add EXTRAINFO options */
1024 if (ruleinfo_pt->maxsize > 0 &&
1025 !(ruleinfo_pt->alert_opts & DO_EXTRAINFO)) {
1026 ruleinfo_pt->alert_opts |= DO_EXTRAINFO;
1029 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1034 else if (strcasecmp(attributes[k], xml_timeframe) == 0) {
1035 if (OS_StrIsNum(values[k]) && (strlen(values[k]) <= 5)) {
1036 ruleinfo_pt->timeframe = atoi(values[k]);
1038 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1043 else if (strcasecmp(attributes[k], xml_frequency) == 0) {
1044 if (OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4)) {
1045 ruleinfo_pt->frequency = atoi(values[k]);
1047 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1052 else if (strcasecmp(attributes[k], xml_accuracy) == 0) {
1053 merror("%s: XXX: Use of 'accuracy' isn't supported. Ignoring.",
1056 /* Rule ignore_time */
1057 else if (strcasecmp(attributes[k], xml_ignore_time) == 0) {
1058 if (OS_StrIsNum(values[k]) && (strlen(values[k]) <= 4)) {
1059 ruleinfo_pt->ignore_time = atoi(values[k]);
1061 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1066 else if (strcasecmp(attributes[k], xml_noalert) == 0) {
1067 ruleinfo_pt->alert_opts |= NO_ALERT;
1068 } else if (strcasecmp(attributes[k], xml_overwrite) == 0) {
1069 if (strcmp(values[k], "yes") == 0) {
1070 ruleinfo_pt->alert_opts |= DO_OVERWRITE;
1071 } else if (strcmp(values[k], "no") == 0) {
1073 merror(XML_VALUEERR, __local_name, attributes[k], values[k]);
1077 merror(XML_INVELEM, __local_name, attributes[k]);