Imported Upstream version 2.7
[ossec-hids.git] / src / config / rules-config.c
1 /* @(#) $Id: ./src/config/rules-config.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All right reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation
11  */
12
13 /* Functions to handle the configuration files
14  */
15
16 #include "config.h"
17 #include "shared.h"
18 #include "global-config.h"
19
20
21
22 static int cmpr(const void *a, const void *b) {
23     /*printf("%s - %s\n", *(char **)a, *(char **)b);*/
24     return strcmp(*(char **)a, *(char **)b);
25 }
26
27 static int file_in_list(int list_size, char *f_name, char *d_name, char **alist)
28 {
29     int i = 0;
30     for(i=0; i<(list_size-1); i++)
31     {
32         if((strcmp(alist[i], f_name) == 0 || strcmp(alist[i], d_name) == 0))
33         {
34             return(1);
35         }
36     }
37     return(0);
38 }
39
40 int Read_Rules(XML_NODE node, void *configp, void *mailp)
41 {
42     int i = 0;
43     int ii = 0;
44
45     int rules_size = 1;
46     int lists_size = 1;
47     int decoders_size = 1;
48
49
50     char path[PATH_MAX +2];
51     char f_name[PATH_MAX +2];
52     int start_point = 0;
53     int att_count = 0;
54     struct dirent *entry;
55     DIR *dfd;
56     OSRegex regex;
57
58
59     /* XML definitions */
60     char *xml_rules_include = "include";
61     char *xml_rules_rule = "rule";
62     char *xml_rules_rules_dir = "rule_dir";
63     char *xml_rules_lists = "list";
64     char *xml_rules_decoders = "decoder";
65     char *xml_rules_decoders_dir = "decoder_dir";
66
67     _Config *Config;
68
69     Config = (_Config *)configp;
70
71     /* initialise OSRegex */
72     regex.patterns = NULL;
73     regex.prts_closure = NULL;
74     regex.prts_str = NULL;
75     regex.sub_strings = NULL;
76
77     while(node[i])
78     {
79         if(!node[i]->element)
80         {
81             merror(XML_ELEMNULL, ARGV0);
82             return(OS_INVALID);
83         }
84         else if(!node[i]->content)
85         {
86             merror(XML_VALUENULL, ARGV0, node[i]->element);
87             return(OS_INVALID);
88         }
89         /* Mail notification */
90         else if((strcmp(node[i]->element, xml_rules_include) == 0) ||
91                 (strcmp(node[i]->element, xml_rules_rule) == 0))
92         {
93             rules_size++;
94             Config->includes = realloc(Config->includes,
95                                        sizeof(char *)*rules_size);
96             if(!Config->includes)
97             {
98                 merror(MEM_ERROR, ARGV0);
99                 return(OS_INVALID);
100             }
101
102             os_strdup(node[i]->content,Config->includes[rules_size -2]);
103             Config->includes[rules_size -1] = NULL;
104             debug1("adding rule: %s", node[i]->content);
105         }
106         else if(strcmp(node[i]->element, xml_rules_decoders) == 0)
107         {
108             decoders_size++;
109             Config->decoders = realloc(Config->decoders,
110                                        sizeof(char *)*decoders_size);
111             if(!Config->decoders)
112             {
113                 merror(MEM_ERROR, ARGV0);
114                 return(OS_INVALID);
115             }
116
117             os_strdup(node[i]->content,Config->decoders[decoders_size -2]);
118             Config->decoders[decoders_size -1] = NULL;
119             debug1("adding decoder: %s", node[i]->content);
120         }
121         else if(strcmp(node[i]->element, xml_rules_lists) == 0)
122         {
123             lists_size++;
124             Config->lists = realloc(Config->lists,
125                                     sizeof(char *)*lists_size);
126             if(!Config->lists)
127             {
128                 merror(MEM_ERROR, ARGV0);
129                 return(OS_INVALID);
130             }
131             os_strdup(node[i]->content,Config->lists[lists_size -2]);
132             Config->lists[lists_size -1] = NULL;
133
134         }
135         else if(strcmp(node[i]->element, xml_rules_lists) == 0)
136         {
137             lists_size++;
138             Config->lists = realloc(Config->lists,
139                                     sizeof(char *)*lists_size);
140             if(!Config->lists)
141             {
142                 merror(MEM_ERROR, ARGV0);
143                 return(OS_INVALID);
144             }
145             os_strdup(node[i]->content,Config->lists[lists_size -2]);
146             Config->lists[lists_size -1] = NULL;
147
148         }
149         else if(strcmp(node[i]->element, xml_rules_decoders_dir) == 0)
150         {
151
152             if(node[i]->attributes && node[i]->values)
153             {
154                 while(node[i]->attributes[att_count])
155                 {
156                     if((strcasecmp(node[i]->attributes[att_count], "pattern") == 0))
157                     {
158                         if(node[i]->values[att_count])
159                         {
160                             if(!OSRegex_Compile(node[i]->values[att_count], &regex, 0))
161                             {
162                                 merror(CONFIG_ERROR, ARGV0, "pattern in decoders_dir does not compile");
163                                 merror("%s: ERROR: Regex would not compile", ARGV0);
164                                 return(-1);
165                             }
166                         }
167                     }
168                     att_count++;
169                 }
170             }
171             else
172             {
173                 OSRegex_Compile(".xml$", &regex, 0);
174             }
175
176             #ifdef TESTRULE
177             snprintf(path,PATH_MAX +1,"%s", node[i]->content);
178             #else
179             snprintf(path,PATH_MAX +1,"%s/%s", DEFAULTDIR, node[i]->content);
180             #endif
181
182             f_name[PATH_MAX +1] = '\0';
183             dfd = opendir(path);
184
185             if(dfd != NULL) {
186                 start_point = decoders_size- 1;
187                 while((entry = readdir(dfd)) != NULL)
188                 {
189                     snprintf(f_name, PATH_MAX +1, "%s/%s", node[i]->content, entry->d_name);
190
191                     /* Just ignore . and ..  */
192                     if((strcmp(entry->d_name,".") == 0) || (strcmp(entry->d_name,"..") == 0))
193                         continue;
194
195                     /* no dups allowed */
196                     if(file_in_list(decoders_size, f_name, entry->d_name, Config->decoders))
197                         continue;
198
199                     if(OSRegex_Execute(f_name, &regex))
200                     {
201                         decoders_size++;
202                         Config->decoders= realloc(Config->decoders, sizeof(char *)*decoders_size);
203                         if(!Config->decoders)
204                         {
205                             merror(MEM_ERROR, ARGV0);
206                             OSRegex_FreePattern(&regex);
207                             return(-1);
208                         }
209
210                         os_strdup(f_name, Config->decoders[decoders_size -2]);
211                         Config->decoders[decoders_size -1] = NULL;
212                         debug1("adding decoder: %s", f_name);
213                     }
214                     else
215                     {
216                         debug1("Regex does not match \"%s\"",  f_name);
217                     }
218                 }
219
220                 closedir(dfd);
221                 /* Sort just then newly added items */
222                 qsort(Config->decoders + start_point , decoders_size- start_point -1, sizeof(char *), cmpr);
223             }
224             debug1("decoders_size %d", decoders_size);
225             for(ii=0;ii<decoders_size-1;ii++)
226                 debug1("- %s", Config->decoders[ii]);
227         }
228         else if(strcmp(node[i]->element, xml_rules_rules_dir) == 0)
229         {
230             if(node[i]->attributes && node[i]->values)
231             {
232                 while(node[i]->attributes[att_count])
233                 {
234                     if((strcasecmp(node[i]->attributes[att_count], "pattern") == 0))
235                     {
236                         if(node[i]->values[att_count])
237                         {
238                             if(!OSRegex_Compile(node[i]->values[att_count], &regex, 0))
239                             {
240                                 merror(CONFIG_ERROR, ARGV0, "pattern in rules_dir does not compile");
241                                 merror("%s: ERROR: Regex would not compile", ARGV0);
242                                 return(-1);
243                             }
244                         }
245                     }
246                     att_count++;
247                 }
248             }
249             else
250             {
251                 OSRegex_Compile(".xml$", &regex, 0);
252             }
253
254             #ifdef TESTRULE
255             snprintf(path,PATH_MAX +1,"%s", node[i]->content);
256             #else
257             snprintf(path,PATH_MAX +1,"%s/%s", DEFAULTDIR, node[i]->content);
258             #endif
259
260             f_name[PATH_MAX +1] = '\0';
261             dfd = opendir(path);
262
263             if(dfd != NULL) {
264                 start_point = rules_size - 1;
265                 while((entry = readdir(dfd)) != NULL)
266                 {
267                     snprintf(f_name, PATH_MAX +1, "%s/%s", node[i]->content, entry->d_name);
268
269                     /* Just ignore . and ..  */
270                     if((strcmp(entry->d_name,".") == 0) || (strcmp(entry->d_name,"..") == 0))
271                         continue;
272
273                     /* no dups allowed */
274                     if(file_in_list(rules_size, f_name, entry->d_name, Config->includes))
275                         continue;
276
277                     if(OSRegex_Execute(f_name, &regex))
278                     {
279                         rules_size++;
280                         Config->includes = realloc(Config->includes, sizeof(char *)*rules_size);
281                         if(!Config->includes)
282                         {
283                             merror(MEM_ERROR, ARGV0);
284                             OSRegex_FreePattern(&regex);
285                             return(-1);
286                         }
287
288                         os_strdup(f_name, Config->includes[rules_size -2]);
289                         Config->includes[rules_size -1] = NULL;
290                         debug1("adding rule: %s", f_name);
291                     }
292                     else
293                     {
294                         debug1("Regex does not match \"%s\"",  f_name);
295                     }
296                 }
297
298                 closedir(dfd);
299                 /* Sort just then newly added items */
300                 qsort(Config->includes + start_point , rules_size - start_point -1, sizeof(char *), cmpr);
301             }
302         }
303         else
304         {
305             merror(XML_INVELEM, ARGV0, node[i]->element);
306             OSRegex_FreePattern(&regex);
307             return(OS_INVALID);
308         }
309         i++;
310     }
311     return(0);
312 }
313
314
315 /* EOF */