Imported Upstream version 2.7
[ossec-hids.git] / src / config / active-response.c
1 /* @(#) $Id: ./src/config/active-response.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
14 #include "shared.h"
15 #include "os_xml/os_xml.h"
16 #include "os_regex/os_regex.h"
17
18 #include "active-response.h"
19
20
21 /** int ReadActiveResponses(XML_NODE node, void *d1, void *d2)
22  * Generates a list with all active responses.
23  */
24 int ReadActiveResponses(XML_NODE node, void *d1, void *d2)
25 {
26     FILE *fp;
27     int i = 0;
28     int r_ar = 0;
29     int l_ar = 0;
30     int rpt = 0;
31
32
33     /* Xml options */
34     char *xml_ar_command = "command";
35     char *xml_ar_location = "location";
36     char *xml_ar_agent_id = "agent_id";
37     char *xml_ar_rules_id = "rules_id";
38     char *xml_ar_rules_group = "rules_group";
39     char *xml_ar_level = "level";
40     char *xml_ar_timeout = "timeout";
41     char *xml_ar_disabled = "disabled";
42     char *xml_ar_repeated = "repeated_offenders";
43
44     char *tmp_location;
45
46
47     /* Currently active response */
48     active_response *tmp_ar;
49
50
51     /* Opening shared ar file */
52     fp = fopen(DEFAULTARPATH, "a");
53     if(!fp)
54     {
55         merror(FOPEN_ERROR, ARGV0, DEFAULTARPATH);
56         return(-1);
57     }
58     chmod(DEFAULTARPATH, 0440);
59
60
61     /* Allocating for the active-response */
62     tmp_ar = calloc(1, sizeof(active_response));
63     if(!tmp_ar)
64     {
65         merror(MEM_ERROR, ARGV0);
66         return(-1);
67     }
68
69     /* Initializing variables */
70     tmp_ar->name = NULL;
71     tmp_ar->command = NULL;
72     tmp_ar->location = 0;
73     tmp_ar->timeout = 0;
74     tmp_ar->level = 0;
75     tmp_ar->agent_id = NULL;
76     tmp_ar->rules_id = NULL;
77     tmp_ar->rules_group = NULL;
78     tmp_ar->ar_cmd = NULL;
79     tmp_location = NULL;
80
81
82
83     /* Searching for the commands */
84     while(node[i])
85     {
86         if(!node[i]->element)
87         {
88             merror(XML_ELEMNULL, ARGV0);
89             return(OS_INVALID);
90         }
91         else if(!node[i]->content)
92         {
93             merror(XML_VALUENULL, ARGV0, node[i]->element);
94             return(OS_INVALID);
95         }
96
97         /* Command */
98         if(strcmp(node[i]->element, xml_ar_command) == 0)
99         {
100             tmp_ar->command = strdup(node[i]->content);
101         }
102         /* Target */
103         else if(strcmp(node[i]->element, xml_ar_location) == 0)
104         {
105             tmp_location = strdup(node[i]->content);
106         }
107         else if(strcmp(node[i]->element, xml_ar_agent_id) == 0)
108         {
109             tmp_ar->agent_id = strdup(node[i]->content);
110         }
111         else if(strcmp(node[i]->element, xml_ar_rules_id) == 0)
112         {
113             tmp_ar->rules_id = strdup(node[i]->content);
114         }
115         else if(strcmp(node[i]->element, xml_ar_rules_group) == 0)
116         {
117             tmp_ar->rules_group = strdup(node[i]->content);
118         }
119         else if(strcmp(node[i]->element, xml_ar_level) == 0)
120         {
121             /* Level must be numeric */
122             if(!OS_StrIsNum(node[i]->content))
123             {
124                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
125                 return(OS_INVALID);
126             }
127
128             tmp_ar->level = atoi(node[i]->content);
129
130             /* Making sure the level is valid */
131             if((tmp_ar->level < 0) || (tmp_ar->level > 20))
132             {
133                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
134                 return(OS_INVALID);
135             }
136         }
137         else if(strcmp(node[i]->element, xml_ar_timeout) == 0)
138         {
139             tmp_ar->timeout = atoi(node[i]->content);
140         }
141         else if(strcmp(node[i]->element, xml_ar_disabled) == 0)
142         {
143             if(strcmp(node[i]->content, "yes") == 0)
144             {
145                 ar_flag = -1;
146             }
147             else if(strcmp(node[i]->content, "no") == 0)
148             {
149                 /* Don't do anything if disabled is set to "no" */
150             }
151             else
152             {
153                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
154                 return(OS_INVALID);
155             }
156         }
157         else if(strcmp(node[i]->element, xml_ar_repeated) == 0)
158         {
159             /* Nothing - we deal with it on execd. */
160             rpt = 1;
161         }
162         else
163         {
164             merror(XML_INVELEM, ARGV0, node[i]->element);
165             return(OS_INVALID);
166         }
167         i++;
168     }
169
170     /* Checking if ar is disabled */
171     if(ar_flag == -1)
172     {
173         fclose(fp);
174         return(0);
175     }
176
177     /* Command and location must be there */
178     if(!tmp_ar->command || !tmp_location)
179     {
180         if(rpt == 1)
181         {
182             fclose(fp);
183             return(0);
184         }
185         merror(AR_MISS, ARGV0);
186         return(-1);
187     }
188
189     /* analysisd */
190     if(OS_Regex("AS|analysisd|analysis-server|server", tmp_location))
191     {
192         tmp_ar->location|= AS_ONLY;
193     }
194
195     if(OS_Regex("local", tmp_location))
196     {
197         tmp_ar->location|= REMOTE_AGENT;
198     }
199
200     if(OS_Regex("defined-agent", tmp_location))
201     {
202         if(!tmp_ar->agent_id)
203         {
204             merror(AR_DEF_AGENT, ARGV0);
205             return(-1);
206         }
207
208         tmp_ar->location|= SPECIFIC_AGENT;
209
210     }
211     if(OS_Regex("all|any", tmp_location))
212     {
213         tmp_ar->location|=ALL_AGENTS;
214     }
215
216     /* If we didn't set any value for the location */
217     if(tmp_ar->location == 0)
218     {
219         merror(AR_INV_LOC, ARGV0, tmp_location);
220         return(-1);
221     }
222
223
224     /* cleaning tmp_location */
225     free(tmp_location);
226     tmp_location = NULL;
227
228
229     /* Checking if command name is valid */
230     {
231         OSListNode *my_commands_node;
232
233         my_commands_node = OSList_GetFirstNode(d1);
234         while(my_commands_node)
235         {
236             ar_command *my_command;
237             my_command = (ar_command *)my_commands_node->data;
238
239             if(strcmp(my_command->name, tmp_ar->command) == 0)
240             {
241                 tmp_ar->ar_cmd = my_command;
242                 break;
243             }
244
245             my_commands_node = OSList_GetNextNode(d1);
246         }
247
248         /* Didn't find a valid command */
249         if(tmp_ar->ar_cmd == NULL)
250         {
251             merror(AR_INV_CMD, ARGV0, tmp_ar->command);
252             return(-1);
253         }
254     }
255
256     /* Checking if timeout is allowed */
257     if(tmp_ar->timeout && !tmp_ar->ar_cmd->timeout_allowed)
258     {
259         merror(AR_NO_TIMEOUT, ARGV0, tmp_ar->ar_cmd->name);
260         return(-1);
261     }
262
263     /* d1 is the active response list */
264     if(!OSList_AddData(d2, (void *)tmp_ar))
265     {
266         merror(LIST_ADD_ERROR, ARGV0);
267         return(-1);
268     }
269
270
271     /* Setting a unique active response name */
272     tmp_ar->name = calloc(OS_FLSIZE +1, sizeof(char));
273     if(!tmp_ar->name)
274     {
275         ErrorExit(MEM_ERROR, ARGV0);
276     }
277     snprintf(tmp_ar->name, OS_FLSIZE, "%s%d",
278             tmp_ar->ar_cmd->name,
279             tmp_ar->timeout);
280
281
282     /* Adding to shared file */
283     fprintf(fp, "%s - %s - %d\n",
284             tmp_ar->name,
285             tmp_ar->ar_cmd->executable,
286             tmp_ar->timeout);
287
288
289     /* Setting the configs to start the right queues */
290     if(tmp_ar->location & AS_ONLY)
291     {
292         l_ar = 1;
293     }
294     if(tmp_ar->location & ALL_AGENTS)
295     {
296         r_ar = 1;
297     }
298     if(tmp_ar->location & REMOTE_AGENT)
299     {
300         r_ar = 1;
301         l_ar = 1;
302     }
303     if(tmp_ar->location & SPECIFIC_AGENT)
304     {
305         r_ar = 1;
306     }
307
308     /* Setting the configuration for the active response */
309     if(r_ar && (!(ar_flag & REMOTE_AR)))
310     {
311         ar_flag|= REMOTE_AR;
312     }
313     if(l_ar && (!(ar_flag & LOCAL_AR)))
314     {
315         ar_flag|= LOCAL_AR;
316     }
317
318     /* Closing shared file for active response */
319     fclose(fp);
320
321     /* Done over here */
322     return(0);
323 }
324
325
326
327 /** int ReadActiveCommands(XML_NODE node, void *d1, void *d2)
328  */
329 int ReadActiveCommands(XML_NODE node, void *d1, void *d2)
330 {
331     int i = 0;
332
333     char *tmp_str = NULL;
334
335     /* Xml values */
336     char *command_name = "name";
337     char *command_expect = "expect";
338     char *command_executable = "executable";
339     char *timeout_allowed = "timeout_allowed";
340
341     ar_command *tmp_command;
342
343
344     /* Allocating the active-response command */
345     tmp_command = calloc(1, sizeof(ar_command));
346     if(!tmp_command)
347     {
348         merror(MEM_ERROR, ARGV0);
349         return(-1);
350     }
351
352     tmp_command->name = NULL;
353     tmp_command->expect= 0;
354     tmp_command->executable = NULL;
355     tmp_command->timeout_allowed = 0;
356
357
358     /* Searching for the commands */
359     while(node[i])
360     {
361         if(!node[i]->element)
362         {
363             merror(XML_ELEMNULL, ARGV0);
364             return(OS_INVALID);
365         }
366         else if(!node[i]->content)
367         {
368             merror(XML_VALUENULL, ARGV0, node[i]->element);
369             return(OS_INVALID);
370         }
371         if(strcmp(node[i]->element, command_name) == 0)
372         {
373             tmp_command->name = strdup(node[i]->content);
374         }
375         else if(strcmp(node[i]->element, command_expect) == 0)
376         {
377             tmp_str = strdup(node[i]->content);
378         }
379         else if(strcmp(node[i]->element, command_executable) == 0)
380         {
381             tmp_command->executable = strdup(node[i]->content);
382         }
383         else if(strcmp(node[i]->element, timeout_allowed) == 0)
384         {
385             if(strcmp(node[i]->content, "yes") == 0)
386                 tmp_command->timeout_allowed = 1;
387             else if(strcmp(node[i]->content, "no") == 0)
388                 tmp_command->timeout_allowed = 0;
389             else
390             {
391                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
392                 return(OS_INVALID);
393             }
394         }
395         else
396         {
397             merror(XML_INVELEM, ARGV0, node[i]->element);
398             return(OS_INVALID);
399         }
400         i++;
401     }
402
403     if(!tmp_command->name || !tmp_str || !tmp_command->executable)
404     {
405         merror(AR_CMD_MISS, ARGV0);
406         return(-1);
407     }
408
409
410     /* Getting the expect */
411     if(strlen(tmp_str) >= 4)
412     {
413         if(OS_Regex("user", tmp_str))
414             tmp_command->expect |= USERNAME;
415         if(OS_Regex("srcip", tmp_str))
416             tmp_command->expect |= SRCIP;
417     }
418
419     free(tmp_str);
420     tmp_str = NULL;
421
422
423     /* Adding command to the list */
424     if(!OSList_AddData(d1, (void *)tmp_command))
425     {
426         merror(LIST_ADD_ERROR, ARGV0);
427         return(-1);
428     }
429
430
431     /* Done over here */
432     return(0);
433 }
434
435
436 /* EOF */