1 /* Copyright (C) 2009 Trend Micro Inc.
2 * All right reserved.
3 *
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
7 * Foundation
8 */
9
10 #include <string.h>
11
12 #include "config.h"
13 #include "shared.h"
14 #include "global-config.h"
15 #include "config.h"
16
17 /* Prototypes */
18 static int cmpr(const void *a, const void *b) __attribute__((nonnull));
19 static int file_in_list(unsigned int list_size, char *f_name, char *d_name, char **alist) __attribute__((nonnull));
20
21
cmpr(const void * a,const void * b)22 static int cmpr(const void *a, const void *b)
23 {
24 return strcmp(*(const char *const *)a, *(const char *const *)b);
25 }
26
file_in_list(unsigned int list_size,char * f_name,char * d_name,char ** alist)27 static int file_in_list(unsigned int list_size, char *f_name, char *d_name, char **alist)
28 {
29 unsigned int i = 0;
30 for (i = 0; (i + 1) < list_size; i++) {
31 if ((strcmp(alist[i], f_name) == 0 || strcmp(alist[i], d_name) == 0)) {
32 return (1);
33 }
34 }
35 return (0);
36 }
37
Read_Rules(XML_NODE node,void * configp,void * mailp)38 int Read_Rules(XML_NODE node, void *configp, __attribute__((unused)) void *mailp)
39 {
40 int i = 0;
41 unsigned int ii = 0;
42
43 unsigned int rules_size = 1;
44 unsigned int lists_size = 1;
45 unsigned int decoders_size = 1;
46
47 char path[PATH_MAX + 2];
48 char f_name[PATH_MAX + 2];
49 unsigned int start_point = 0;
50 int att_count = 0;
51 struct dirent *entry;
52 DIR *dfd;
53 OSRegex regex;
54
55 /* XML definitions */
56 const char *xml_rules_include = "include";
57 const char *xml_rules_rule = "rule";
58 const char *xml_rules_rules_dir = "rule_dir";
59 const char *xml_rules_lists = "list";
60 const char *xml_rules_decoders = "decoder";
61 const char *xml_rules_decoders_dir = "decoder_dir";
62
63 _Config *Config;
64
65 Config = (_Config *)configp;
66
67 /* Initialize OSRegex */
68 memset(®ex, 0, sizeof(regex));
69
70 while (node[i]) {
71 if (!node[i]->element) {
72 merror(XML_ELEMNULL, __local_name);
73 return (OS_INVALID);
74 } else if (!node[i]->content) {
75 merror(XML_VALUENULL, __local_name, node[i]->element);
76 return (OS_INVALID);
77 }
78 /* Mail notification */
79 else if ((strcmp(node[i]->element, xml_rules_include) == 0) ||
80 (strcmp(node[i]->element, xml_rules_rule) == 0)) {
81 rules_size++;
82 Config->includes = (char **) realloc(Config->includes,
83 sizeof(char *)*rules_size);
84 if (!Config->includes) {
85 merror(MEM_ERROR, __local_name, errno, strerror(errno));
86 return (OS_INVALID);
87 }
88
89 os_strdup(node[i]->content, Config->includes[rules_size - 2]);
90 Config->includes[rules_size - 1] = NULL;
91 debug1("adding rule: %s", node[i]->content);
92 } else if (strcmp(node[i]->element, xml_rules_decoders) == 0) {
93 decoders_size++;
94 Config->decoders = (char **) realloc(Config->decoders,
95 sizeof(char *)*decoders_size);
96 if (!Config->decoders) {
97 merror(MEM_ERROR, __local_name, errno, strerror(errno));
98 return (OS_INVALID);
99 }
100
101 os_strdup(node[i]->content, Config->decoders[decoders_size - 2]);
102 Config->decoders[decoders_size - 1] = NULL;
103 debug1("adding decoder: %s", node[i]->content);
104 } else if (strcmp(node[i]->element, xml_rules_lists) == 0) {
105 lists_size++;
106 Config->lists = (char **) realloc(Config->lists,
107 sizeof(char *)*lists_size);
108 if (!Config->lists) {
109 merror(MEM_ERROR, __local_name, errno, strerror(errno));
110 return (OS_INVALID);
111 }
112 os_strdup(node[i]->content, Config->lists[lists_size - 2]);
113 Config->lists[lists_size - 1] = NULL;
114
115 } else if (strcmp(node[i]->element, xml_rules_decoders_dir) == 0) {
116
117 if (node[i]->attributes && node[i]->values) {
118 while (node[i]->attributes[att_count]) {
119 if ((strcasecmp(node[i]->attributes[att_count], "pattern") == 0)) {
120 if (node[i]->values[att_count]) {
121 if (!OSRegex_Compile(node[i]->values[att_count], ®ex, 0)) {
122 merror(CONFIG_ERROR, __local_name, "pattern in decoders_dir does not compile");
123 merror("%s: ERROR: Regex would not compile", __local_name);
124 return (-1);
125 }
126 }
127 }
128 att_count++;
129 }
130 } else {
131 OSRegex_Compile(".xml$", ®ex, 0);
132 }
133
134 #ifdef TESTRULE
135 snprintf(path, PATH_MAX + 1, "%s", node[i]->content);
136 #else
137 snprintf(path, PATH_MAX + 1, "%s/%s", DEFAULTDIR, node[i]->content);
138 #endif
139
140 f_name[PATH_MAX + 1] = '\0';
141 dfd = opendir(path);
142
143 att_count = 0; // Reset this variable after it was used in decoder
144
145 if (dfd != NULL) {
146 start_point = decoders_size - 1;
147 while ((entry = readdir(dfd)) != NULL) {
148 snprintf(f_name, PATH_MAX + 1, "%s/%s", node[i]->content, entry->d_name);
149
150 /* Ignore . and .. */
151 if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
152 continue;
153 }
154
155 /* No duplicates allowed */
156 if (file_in_list(decoders_size, f_name, entry->d_name, Config->decoders)) {
157 continue;
158 }
159
160 if (OSRegex_Execute(f_name, ®ex)) {
161 decoders_size++;
162 Config->decoders = (char **) realloc(Config->decoders, sizeof(char *)*decoders_size);
163 if (!Config->decoders) {
164 merror(MEM_ERROR, __local_name, errno, strerror(errno));
165 OSRegex_FreePattern(®ex);
166 closedir(dfd);
167 return (-1);
168 }
169
170 os_strdup(f_name, Config->decoders[decoders_size - 2]);
171 Config->decoders[decoders_size - 1] = NULL;
172 debug1("adding decoder: %s", f_name);
173 } else {
174 debug1("Regex does not match \"%s\"", f_name);
175 }
176 }
177
178 OSRegex_FreePattern(®ex);
179 closedir(dfd);
180 /* Sort just then newly added items */
181 qsort(Config->decoders + start_point , decoders_size - start_point - 1, sizeof(char *), cmpr);
182 }
183 debug1("decoders_size %d", decoders_size);
184 for (ii = 0; ii < decoders_size - 1; ii++) {
185 debug1("- %s", Config->decoders[ii]);
186 }
187 } else if (strcmp(node[i]->element, xml_rules_rules_dir) == 0) {
188 if (node[i]->attributes && node[i]->values) {
189 while (node[i]->attributes[att_count]) {
190 if ((strcasecmp(node[i]->attributes[att_count], "pattern") == 0)) {
191 if (node[i]->values[att_count]) {
192 if (!OSRegex_Compile(node[i]->values[att_count], ®ex, 0)) {
193 merror(CONFIG_ERROR, __local_name, "pattern in rules_dir does not compile");
194 merror("%s: ERROR: Regex would not compile", __local_name);
195 return (-1);
196 }
197 }
198 }
199 att_count++;
200 }
201 } else {
202 OSRegex_Compile(".xml$", ®ex, 0);
203 }
204
205 #ifdef TESTRULE
206 snprintf(path, PATH_MAX + 1, "%s", node[i]->content);
207 #else
208 snprintf(path, PATH_MAX + 1, "%s/%s", DEFAULTDIR, node[i]->content);
209 #endif
210
211 f_name[PATH_MAX + 1] = '\0';
212 dfd = opendir(path);
213
214 if (dfd != NULL) {
215 start_point = rules_size - 1;
216 while ((entry = readdir(dfd)) != NULL) {
217 snprintf(f_name, PATH_MAX + 1, "%s/%s", node[i]->content, entry->d_name);
218
219 /* Ignore . and .. */
220 if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
221 continue;
222 }
223
224 /* No duplicates allowed */
225 if (file_in_list(rules_size, f_name, entry->d_name, Config->includes)) {
226 continue;
227 }
228
229 if (OSRegex_Execute(f_name, ®ex)) {
230 rules_size++;
231 Config->includes = (char **) realloc(Config->includes, sizeof(char *)*rules_size);
232 if (!Config->includes) {
233 merror(MEM_ERROR, __local_name, errno, strerror(errno));
234 OSRegex_FreePattern(®ex);
235 closedir(dfd);
236 return (-1);
237 }
238
239 os_strdup(f_name, Config->includes[rules_size - 2]);
240 Config->includes[rules_size - 1] = NULL;
241 debug1("adding rule: %s", f_name);
242 } else {
243 debug1("Regex does not match \"%s\"", f_name);
244 }
245 }
246
247 OSRegex_FreePattern(®ex);
248 closedir(dfd);
249 /* Sort just then newly added items */
250 qsort(Config->includes + start_point , rules_size - start_point - 1, sizeof(char *), cmpr);
251 }
252 } else {
253 merror(XML_INVELEM, __local_name, node[i]->element);
254 OSRegex_FreePattern(®ex);
255 return (OS_INVALID);
256 }
257 i++;
258 }
259 return (0);
260 }
261