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