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