X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?a=blobdiff_plain;f=src%2Fconfig%2Frules-config.c;h=ca05420e79ca465419061d911774b885f474a029;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hp=f9da8f36911f5f692a74ca7999139d7c89824f87;hpb=914feba5d54f979cd5d7e69c349c3d01f630042a;p=ossec-hids.git diff --git a/src/config/rules-config.c b/src/config/rules-config.c old mode 100755 new mode 100644 index f9da8f3..ca05420 --- a/src/config/rules-config.c +++ b/src/config/rules-config.c @@ -1,73 +1,260 @@ -/* @(#) $Id: rules-config.c,v 1.5 2009/06/24 17:06:25 dcid Exp $ */ - /* Copyright (C) 2009 Trend Micro Inc. * All right reserved. * * This program is a free software; you can redistribute it * and/or modify it under the terms of the GNU General Public - * License (version 3) as published by the FSF - Free Software + * License (version 2) as published by the FSF - Free Software * Foundation */ -/* Functions to handle the configuration files - */ - +#include +#include "config.h" #include "shared.h" #include "global-config.h" +#include "config.h" + +/* Prototypes */ +static int cmpr(const void *a, const void *b) __attribute__((nonnull)); +static int file_in_list(unsigned int list_size, char *f_name, char *d_name, char **alist) __attribute__((nonnull)); + + +static int cmpr(const void *a, const void *b) +{ + return strcmp(*(const char *const *)a, *(const char *const *)b); +} +static int file_in_list(unsigned int list_size, char *f_name, char *d_name, char **alist) +{ + unsigned int i = 0; + for (i = 0; (i + 1) < list_size; i++) { + if ((strcmp(alist[i], f_name) == 0 || strcmp(alist[i], d_name) == 0)) { + return (1); + } + } + return (0); +} -int Read_Rules(XML_NODE node, void *configp, void *mailp) +int Read_Rules(XML_NODE node, void *configp, __attribute__((unused)) void *mailp) { int i = 0; + unsigned int ii = 0; - /* White list size */ - int rules_size = 1; + unsigned int rules_size = 1; + unsigned int lists_size = 1; + unsigned int decoders_size = 1; + char path[PATH_MAX + 2]; + char f_name[PATH_MAX + 2]; + unsigned int start_point = 0; + int att_count = 0; + struct dirent *entry; + DIR *dfd; + OSRegex regex; /* XML definitions */ - char *xml_rules_include = "include"; + const char *xml_rules_include = "include"; + const char *xml_rules_rule = "rule"; + const char *xml_rules_rules_dir = "rule_dir"; + const char *xml_rules_lists = "list"; + const char *xml_rules_decoders = "decoder"; + const char *xml_rules_decoders_dir = "decoder_dir"; _Config *Config; - + Config = (_Config *)configp; - - while(node[i]) - { - if(!node[i]->element) - { - merror(XML_ELEMNULL, ARGV0); - return(OS_INVALID); - } - else if(!node[i]->content) - { - merror(XML_VALUENULL, ARGV0, node[i]->element); - return(OS_INVALID); + + /* Initialize OSRegex */ + memset(®ex, 0, sizeof(regex)); + + while (node[i]) { + if (!node[i]->element) { + merror(XML_ELEMNULL, __local_name); + return (OS_INVALID); + } else if (!node[i]->content) { + merror(XML_VALUENULL, __local_name, node[i]->element); + return (OS_INVALID); } /* Mail notification */ - else if(strcmp(node[i]->element, xml_rules_include) == 0) - { + else if ((strcmp(node[i]->element, xml_rules_include) == 0) || + (strcmp(node[i]->element, xml_rules_rule) == 0)) { rules_size++; - Config->includes = realloc(Config->includes, - sizeof(char *)*rules_size); - if(!Config->includes) - { - merror(MEM_ERROR, ARGV0); - return(OS_INVALID); + Config->includes = (char **) realloc(Config->includes, + sizeof(char *)*rules_size); + if (!Config->includes) { + merror(MEM_ERROR, __local_name, errno, strerror(errno)); + return (OS_INVALID); } - os_strdup(node[i]->content,Config->includes[rules_size -2]); - Config->includes[rules_size -1] = NULL; - } - else - { - merror(XML_INVELEM, ARGV0, node[i]->element); - return(OS_INVALID); + os_strdup(node[i]->content, Config->includes[rules_size - 2]); + Config->includes[rules_size - 1] = NULL; + debug1("adding rule: %s", node[i]->content); + } else if (strcmp(node[i]->element, xml_rules_decoders) == 0) { + decoders_size++; + Config->decoders = (char **) realloc(Config->decoders, + sizeof(char *)*decoders_size); + if (!Config->decoders) { + merror(MEM_ERROR, __local_name, errno, strerror(errno)); + return (OS_INVALID); + } + + os_strdup(node[i]->content, Config->decoders[decoders_size - 2]); + Config->decoders[decoders_size - 1] = NULL; + debug1("adding decoder: %s", node[i]->content); + } else if (strcmp(node[i]->element, xml_rules_lists) == 0) { + lists_size++; + Config->lists = (char **) realloc(Config->lists, + sizeof(char *)*lists_size); + if (!Config->lists) { + merror(MEM_ERROR, __local_name, errno, strerror(errno)); + return (OS_INVALID); + } + os_strdup(node[i]->content, Config->lists[lists_size - 2]); + Config->lists[lists_size - 1] = NULL; + + } else if (strcmp(node[i]->element, xml_rules_decoders_dir) == 0) { + + if (node[i]->attributes && node[i]->values) { + while (node[i]->attributes[att_count]) { + if ((strcasecmp(node[i]->attributes[att_count], "pattern") == 0)) { + if (node[i]->values[att_count]) { + if (!OSRegex_Compile(node[i]->values[att_count], ®ex, 0)) { + merror(CONFIG_ERROR, __local_name, "pattern in decoders_dir does not compile"); + merror("%s: ERROR: Regex would not compile", __local_name); + return (-1); + } + } + } + att_count++; + } + } else { + OSRegex_Compile(".xml$", ®ex, 0); + } + +#ifdef TESTRULE + snprintf(path, PATH_MAX + 1, "%s", node[i]->content); +#else + snprintf(path, PATH_MAX + 1, "%s/%s", DEFAULTDIR, node[i]->content); +#endif + + f_name[PATH_MAX + 1] = '\0'; + dfd = opendir(path); + + att_count = 0; // Reset this variable after it was used in decoder + + if (dfd != NULL) { + start_point = decoders_size - 1; + while ((entry = readdir(dfd)) != NULL) { + snprintf(f_name, PATH_MAX + 1, "%s/%s", node[i]->content, entry->d_name); + + /* Ignore . and .. */ + if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { + continue; + } + + /* No duplicates allowed */ + if (file_in_list(decoders_size, f_name, entry->d_name, Config->decoders)) { + continue; + } + + if (OSRegex_Execute(f_name, ®ex)) { + decoders_size++; + Config->decoders = (char **) realloc(Config->decoders, sizeof(char *)*decoders_size); + if (!Config->decoders) { + merror(MEM_ERROR, __local_name, errno, strerror(errno)); + OSRegex_FreePattern(®ex); + closedir(dfd); + return (-1); + } + + os_strdup(f_name, Config->decoders[decoders_size - 2]); + Config->decoders[decoders_size - 1] = NULL; + debug1("adding decoder: %s", f_name); + } else { + debug1("Regex does not match \"%s\"", f_name); + } + } + + OSRegex_FreePattern(®ex); + closedir(dfd); + /* Sort just then newly added items */ + qsort(Config->decoders + start_point , decoders_size - start_point - 1, sizeof(char *), cmpr); + } + debug1("decoders_size %d", decoders_size); + for (ii = 0; ii < decoders_size - 1; ii++) { + debug1("- %s", Config->decoders[ii]); + } + } else if (strcmp(node[i]->element, xml_rules_rules_dir) == 0) { + if (node[i]->attributes && node[i]->values) { + while (node[i]->attributes[att_count]) { + if ((strcasecmp(node[i]->attributes[att_count], "pattern") == 0)) { + if (node[i]->values[att_count]) { + if (!OSRegex_Compile(node[i]->values[att_count], ®ex, 0)) { + merror(CONFIG_ERROR, __local_name, "pattern in rules_dir does not compile"); + merror("%s: ERROR: Regex would not compile", __local_name); + return (-1); + } + } + } + att_count++; + } + } else { + OSRegex_Compile(".xml$", ®ex, 0); + } + +#ifdef TESTRULE + snprintf(path, PATH_MAX + 1, "%s", node[i]->content); +#else + snprintf(path, PATH_MAX + 1, "%s/%s", DEFAULTDIR, node[i]->content); +#endif + + f_name[PATH_MAX + 1] = '\0'; + dfd = opendir(path); + + if (dfd != NULL) { + start_point = rules_size - 1; + while ((entry = readdir(dfd)) != NULL) { + snprintf(f_name, PATH_MAX + 1, "%s/%s", node[i]->content, entry->d_name); + + /* Ignore . and .. */ + if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { + continue; + } + + /* No duplicates allowed */ + if (file_in_list(rules_size, f_name, entry->d_name, Config->includes)) { + continue; + } + + if (OSRegex_Execute(f_name, ®ex)) { + rules_size++; + Config->includes = (char **) realloc(Config->includes, sizeof(char *)*rules_size); + if (!Config->includes) { + merror(MEM_ERROR, __local_name, errno, strerror(errno)); + OSRegex_FreePattern(®ex); + closedir(dfd); + return (-1); + } + + os_strdup(f_name, Config->includes[rules_size - 2]); + Config->includes[rules_size - 1] = NULL; + debug1("adding rule: %s", f_name); + } else { + debug1("Regex does not match \"%s\"", f_name); + } + } + + OSRegex_FreePattern(®ex); + closedir(dfd); + /* Sort just then newly added items */ + qsort(Config->includes + start_point , rules_size - start_point - 1, sizeof(char *), cmpr); + } + } else { + merror(XML_INVELEM, __local_name, node[i]->element); + OSRegex_FreePattern(®ex); + return (OS_INVALID); } i++; } - return(0); + return (0); } - - -/* EOF */