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