1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
11 #include <sys/types.h>
16 #include "os_xml/os_xml.h"
17 #include "os_regex/os_regex.h"
18 #include "active-response.h"
21 /* Global variables */
25 /* Generate a list with all active responses */
26 int ReadActiveResponses(XML_NODE node, void *d1, void *d2)
28 OSList *l1 = (OSList *) d1;
29 OSList *l2 = (OSList *) d2;
37 const char *xml_ar_command = "command";
38 const char *xml_ar_location = "location";
39 const char *xml_ar_agent_id = "agent_id";
40 const char *xml_ar_rules_id = "rules_id";
41 const char *xml_ar_rules_group = "rules_group";
42 const char *xml_ar_level = "level";
43 const char *xml_ar_timeout = "timeout";
44 const char *xml_ar_disabled = "disabled";
45 const char *xml_ar_repeated = "repeated_offenders";
49 /* Currently active response */
50 active_response *tmp_ar;
52 /* Open shared ar file */
53 fp = fopen(DEFAULTARPATH, "a");
55 merror(FOPEN_ERROR, __local_name, DEFAULTARPATH, errno, strerror(errno));
60 struct group *os_group;
61 if ((os_group = getgrnam(USER)) == NULL) {
62 merror("Could not get ossec gid.");
67 if ((chown(DEFAULTARPATH, (uid_t) - 1, os_group->gr_gid)) == -1) {
68 merror("Could not change the group to ossec: %d", errno);
74 if ((chmod(DEFAULTARPATH, 0440)) == -1) {
75 merror("Could not chmod to 0440: %d", errno);
80 /* Allocate for the active-response */
81 tmp_ar = (active_response *) calloc(1, sizeof(active_response));
83 merror(MEM_ERROR, __local_name, errno, strerror(errno));
88 /* Initialize variables */
90 tmp_ar->command = NULL;
94 tmp_ar->agent_id = NULL;
95 tmp_ar->rules_id = NULL;
96 tmp_ar->rules_group = NULL;
97 tmp_ar->ar_cmd = NULL;
100 /* Search for the commands */
102 if (!node[i]->element) {
103 merror(XML_ELEMNULL, __local_name);
105 } else if (!node[i]->content) {
106 merror(XML_VALUENULL, __local_name, node[i]->element);
111 if (strcmp(node[i]->element, xml_ar_command) == 0) {
112 tmp_ar->command = strdup(node[i]->content);
115 else if (strcmp(node[i]->element, xml_ar_location) == 0) {
117 tmp_location = strdup(node[i]->content);
118 } else if (strcmp(node[i]->element, xml_ar_agent_id) == 0) {
119 tmp_ar->agent_id = strdup(node[i]->content);
120 } else if (strcmp(node[i]->element, xml_ar_rules_id) == 0) {
121 tmp_ar->rules_id = strdup(node[i]->content);
122 } else if (strcmp(node[i]->element, xml_ar_rules_group) == 0) {
123 tmp_ar->rules_group = strdup(node[i]->content);
124 } else if (strcmp(node[i]->element, xml_ar_level) == 0) {
125 /* Level must be numeric */
126 if (!OS_StrIsNum(node[i]->content)) {
127 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
131 tmp_ar->level = atoi(node[i]->content);
133 /* Make sure the level is valid */
134 if ((tmp_ar->level < 0) || (tmp_ar->level > 20)) {
135 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
138 } else if (strcmp(node[i]->element, xml_ar_timeout) == 0) {
139 tmp_ar->timeout = atoi(node[i]->content);
140 } else if (strcmp(node[i]->element, xml_ar_disabled) == 0) {
141 if (strcmp(node[i]->content, "yes") == 0) {
143 } else if (strcmp(node[i]->content, "no") == 0) {
144 /* Don't do anything if disabled is set to "no" */
146 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
149 } else if (strcmp(node[i]->element, xml_ar_repeated) == 0) {
150 /* Nothing - we deal with it on execd */
153 merror(XML_INVELEM, __local_name, node[i]->element);
159 /* Check if ar is disabled */
161 /* reset ar_flag, the next ar command may not be disabled */
163 debug1("active response command '%s' is disabled", tmp_ar->command);
170 /* Command and location must be there */
171 if (!tmp_ar->command || !tmp_location) {
172 debug1("command or location missing");
180 merror(AR_MISS, __local_name);
185 if (OS_Regex("AS|analysisd|analysis-server|server", tmp_location)) {
186 tmp_ar->location |= AS_ONLY;
189 if (OS_Regex("local", tmp_location)) {
190 tmp_ar->location |= REMOTE_AGENT;
193 if (OS_Regex("defined-agent", tmp_location)) {
194 if (!tmp_ar->agent_id) {
195 debug1("'defined-agent' agent_id not defined");
196 merror(AR_DEF_AGENT, __local_name);
203 tmp_ar->location |= SPECIFIC_AGENT;
206 if (OS_Regex("all|any", tmp_location)) {
207 tmp_ar->location |= ALL_AGENTS;
210 /* If we didn't set any value for the location */
211 if (tmp_ar->location == 0) {
212 debug1("no location defined");
213 merror(AR_INV_LOC, __local_name, tmp_location);
220 /* Clean tmp_location */
224 /* Check if command name is valid */
226 OSListNode *my_commands_node;
228 my_commands_node = OSList_GetFirstNode(l1);
229 while (my_commands_node) {
230 ar_command *my_command;
231 my_command = (ar_command *)my_commands_node->data;
233 if (strcmp(my_command->name, tmp_ar->command) == 0) {
234 tmp_ar->ar_cmd = my_command;
238 my_commands_node = OSList_GetNextNode(l1);
241 /* Didn't find a valid command */
242 if (tmp_ar->ar_cmd == NULL) {
243 debug1("invalid command");
244 merror(AR_INV_CMD, __local_name, tmp_ar->command);
251 /* Check if timeout is allowed */
252 if (tmp_ar->timeout && !tmp_ar->ar_cmd->timeout_allowed) {
253 debug1("timeout is not allowed");
254 merror(AR_NO_TIMEOUT, __local_name, tmp_ar->ar_cmd->name);
260 /* d1 is the active response list */
261 if (!OSList_AddData(l2, (void *)tmp_ar)) {
262 merror(LIST_ADD_ERROR, __local_name);
268 /* Set a unique active response name */
269 tmp_ar->name = (char *) calloc(OS_FLSIZE + 1, sizeof(char));
271 ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
273 snprintf(tmp_ar->name, OS_FLSIZE, "%s%d",
274 tmp_ar->ar_cmd->name,
277 /* Add to shared file */
278 debug1("writing command '%s' to '%s'", tmp_ar->command, DEFAULTARPATH);
279 fprintf(fp, "%s - %s - %d\n",
281 tmp_ar->ar_cmd->executable,
284 /* Set the configs to start the right queues */
285 if (tmp_ar->location & AS_ONLY) {
288 if (tmp_ar->location & ALL_AGENTS) {
291 if (tmp_ar->location & REMOTE_AGENT) {
295 if (tmp_ar->location & SPECIFIC_AGENT) {
299 /* Set the configuration for the active response */
300 if (r_ar && (!(ar_flag & REMOTE_AR))) {
301 ar_flag |= REMOTE_AR;
303 if (l_ar && (!(ar_flag & LOCAL_AR))) {
307 /* Close shared file for active response */
314 /* In case of an error clean up first*/
322 int ReadActiveCommands(XML_NODE node, void *d1, __attribute__((unused)) void *d2)
324 OSList *l1 = (OSList *) d1;
326 char *tmp_str = NULL;
329 const char *command_name = "name";
330 const char *command_expect = "expect";
331 const char *command_executable = "executable";
332 const char *timeout_allowed = "timeout_allowed";
334 ar_command *tmp_command;
336 /* Allocate the active-response command */
337 tmp_command = (ar_command *) calloc(1, sizeof(ar_command));
339 merror(MEM_ERROR, __local_name, errno, strerror(errno));
343 tmp_command->name = NULL;
344 tmp_command->expect = 0;
345 tmp_command->executable = NULL;
346 tmp_command->timeout_allowed = 0;
348 /* Search for the commands */
350 if (!node[i]->element) {
351 merror(XML_ELEMNULL, __local_name);
355 } else if (!node[i]->content) {
356 merror(XML_VALUENULL, __local_name, node[i]->element);
361 if (strcmp(node[i]->element, command_name) == 0) {
362 tmp_command->name = strdup(node[i]->content);
363 } else if (strcmp(node[i]->element, command_expect) == 0) {
365 tmp_str = strdup(node[i]->content);
366 } else if (strcmp(node[i]->element, command_executable) == 0) {
367 tmp_command->executable = strdup(node[i]->content);
368 } else if (strcmp(node[i]->element, timeout_allowed) == 0) {
369 if (strcmp(node[i]->content, "yes") == 0) {
370 tmp_command->timeout_allowed = 1;
371 } else if (strcmp(node[i]->content, "no") == 0) {
372 tmp_command->timeout_allowed = 0;
374 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
380 merror(XML_INVELEM, __local_name, node[i]->element);
388 if (!tmp_command->name || !tmp_str || !tmp_command->executable) {
389 merror(AR_CMD_MISS, __local_name);
396 if (strlen(tmp_str) >= 4) {
397 if (OS_Regex("user", tmp_str)) {
398 tmp_command->expect |= USERNAME;
400 if (OS_Regex("srcip", tmp_str)) {
401 tmp_command->expect |= SRCIP;
403 if (OS_Regex("filename", tmp_str)) {
404 tmp_command->expect |= FILENAME;
411 /* Add command to the list */
412 if (!OSList_AddData(l1, (void *)tmp_command)) {
413 merror(LIST_ADD_ERROR, __local_name);