1 /* @(#) $Id: ./src/os_execd/execd.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
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
17 #include "os_regex/os_regex.h"
18 #include "os_net/os_net.h"
24 /* Timeout data structure */
25 typedef struct _timeout_data
27 time_t time_of_addition;
35 OSListNode *timeout_node;
36 OSHash *repeated_hash;
37 int repeated_offenders_timeout[] = {0,0,0,0,0,0,0};
42 * Shutdowns execd properly.
46 /* Removing pending active responses. */
47 merror(EXEC_SHUTDOWN, ARGV0);
49 timeout_node = OSList_GetFirstNode(timeout_list);
52 timeout_data *list_entry;
54 list_entry = (timeout_data *)timeout_node->data;
56 ExecCmd(list_entry->command);
58 /* Delete currently node - already sets the pointer to next */
59 OSList_DeleteCurrentlyNode(timeout_list);
60 timeout_node = OSList_GetCurrentlyNode(timeout_list);
72 /** int main(int argc, char **argv) v0.1
74 int main(int argc, char **argv)
77 int test_config = 0,run_foreground = 0;
78 int gid = 0,m_queue = 0;
80 // TODO: delete or implement
81 char *dir __attribute__((unused)) = DEFAULTDIR;
82 char *group = GROUPGLOBAL;
83 // TODO: delete or implement
84 char *cfg __attribute__((unused)) = DEFAULTARPATH;
85 char *xmlcfg = DEFAULTCPATH;
88 /* Setting the name */
92 while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
108 ErrorExit("%s: -g needs an argument.",ARGV0);
113 ErrorExit("%s: -D needs an argument.",ARGV0);
118 ErrorExit("%s: -c needs an argument.",ARGV0);
133 /* Check if the group given are valid */
134 gid = Privsep_GetGroup(group);
136 ErrorExit(USER_ERROR,ARGV0,"",group);
139 /* Privilege separation */
140 if(Privsep_SetGroup(gid) < 0)
141 ErrorExit(SETGID_ERROR,ARGV0,group);
145 if((c = ExecdConfig(xmlcfg)) < 0)
147 ErrorExit(CONFIG_ERROR, ARGV0, xmlcfg);
151 /* Exit if test_config */
156 /* Signal manipulation */
157 StartSIG2(ARGV0, execd_shutdown);
168 /* Active response disabled */
171 verbose(EXEC_DISABLED, ARGV0);
175 /* Creating the PID file */
176 if(CreatePID(ARGV0, getpid()) < 0)
177 merror(PID_ERROR, ARGV0);
180 /* Starting queue (exec queue) */
181 if((m_queue = StartMQ(EXECQUEUEPATH,READ)) < 0)
182 ErrorExit(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
185 /* Start up message */
186 verbose(STARTUP_MSG, ARGV0, (int)getpid());
189 /* The real daemon Now */
200 /** void FreeTimeoutEntry(timeout_data *timeout_entry) v0.1
201 * Free the timeout entry. Must be called after popping it
202 * from the timeout list
204 void FreeTimeoutEntry(void *timeout_entry_pt)
206 timeout_data *timeout_entry;
209 timeout_entry = (timeout_data *)timeout_entry_pt;
216 tmp_str = timeout_entry->command;
218 /* Clearing the command arguments */
227 os_free(timeout_entry->command);
228 timeout_entry->command = NULL;
231 os_free(timeout_entry);
232 timeout_entry = NULL;
241 /** void ExecdStart(int q) v0.2
242 * Main function on the execd. Does all the data receiving ,etc.
244 void ExecdStart(int q)
246 int i, childcount = 0;
249 char buffer[OS_MAXSTR + 1];
250 char *tmp_msg = NULL;
253 char *cmd_args[MAX_ARGS +2];
258 struct timeval socket_timeout;
261 /* Clearing the buffer */
262 memset(buffer, '\0', OS_MAXSTR +1);
265 /* Initializing the cmd arguments */
266 for(i = 0; i<= MAX_ARGS +1; i++)
272 /* Creating list for timeout */
273 timeout_list = OSList_Create();
276 ErrorExit(LIST_ERROR, ARGV0);
280 if(repeated_offenders_timeout[0] != 0)
282 repeated_hash = OSHash_Create();
286 repeated_hash = NULL;
295 int added_before = 0;
298 timeout_data *timeout_entry;
301 /* Cleaning up any child. */
305 wp = waitpid((pid_t) -1, NULL, WNOHANG);
308 merror(WAITPID_ERROR, ARGV0);
312 /* if = 0, we still need to wait for the child process */
317 /* Child completed if wp > 0 */
325 /* Getting currently time */
329 /* Checking if there is any timeouted command to execute. */
330 timeout_node = OSList_GetFirstNode(timeout_list);
333 timeout_data *list_entry;
335 list_entry = (timeout_data *)timeout_node->data;
338 if((curr_time - list_entry->time_of_addition) >
339 list_entry->time_to_block)
341 ExecCmd(list_entry->command);
343 /* Deletecurrently node already sets the pointer to next */
344 OSList_DeleteCurrentlyNode(timeout_list);
345 timeout_node = OSList_GetCurrentlyNode(timeout_list);
347 /* Clearing the memory */
348 FreeTimeoutEntry(list_entry);
355 timeout_node = OSList_GetNextNode(timeout_list);
360 /* Setting timeout to EXECD_TIMEOUT */
361 socket_timeout.tv_sec = EXECD_TIMEOUT;
362 socket_timeout.tv_usec= 0;
366 /* Setting FD values */
371 if(select(q+1, &fdset, NULL, NULL, &socket_timeout) == 0)
378 /* Checking for error */
379 if(!FD_ISSET(q, &fdset))
381 merror(SELECT_ERROR, ARGV0);
386 /* Receiving the message */
387 if(recv(q, buffer, OS_MAXSTR, 0) == -1)
389 merror(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
398 /* Getting application name */
402 /* Zeroing the name */
403 tmp_msg = strchr(buffer, ' ');
406 merror(EXECD_INV_MSG, ARGV0, buffer);
413 /* Getting the command to execute (valid name) */
414 command = GetCommandbyName(name, &timeout_value);
418 command = GetCommandbyName(name, &timeout_value);
421 merror(EXEC_INV_NAME, ARGV0, name);
427 /* Command not present. */
428 if(command[0] == '\0')
432 /* Allocating memory for the timeout argument */
433 os_calloc(MAX_ARGS+2, sizeof(char *), timeout_args);
436 /* Adding initial variables to the cmd_arg and to the timeout cmd */
437 cmd_args[0] = command;
438 cmd_args[1] = ADD_ENTRY;
439 os_strdup(command, timeout_args[0]);
440 os_strdup(DELETE_ENTRY, timeout_args[1]);
443 timeout_args[2] = NULL;
446 /* Getting the arguments. */
448 while(i < (MAX_ARGS -1))
450 cmd_args[i] = tmp_msg;
451 cmd_args[i+1] = NULL;
453 tmp_msg = strchr(tmp_msg, ' ');
456 timeout_args[i] = strdup(cmd_args[i]);
457 timeout_args[i+1] = NULL;
463 timeout_args[i] = strdup(cmd_args[i]);
464 timeout_args[i+1] = NULL;
470 /* Check this command was already executed. */
471 timeout_node = OSList_GetFirstNode(timeout_list);
475 /* Checking for the username and ip argument */
476 if(!timeout_args[2] || !timeout_args[3])
479 merror("%s: Invalid number of arguments.", ARGV0);
486 timeout_data *list_entry;
488 list_entry = (timeout_data *)timeout_node->data;
489 if((strcmp(list_entry->command[3], timeout_args[3]) == 0) &&
490 (strcmp(list_entry->command[0], timeout_args[0]) == 0))
492 /* Means we executed this command before
493 * and we don't need to add it again.
498 /* updating the timeout */
499 list_entry->time_of_addition = curr_time;
501 if(repeated_offenders_timeout[0] != 0 &&
502 repeated_hash != NULL &&
503 strncmp(timeout_args[3],"-", 1) != 0)
508 snprintf(rkey, 255, "%s%s", list_entry->command[0],
511 if((ntimes = OSHash_Get(repeated_hash, rkey)))
516 ntimes_int = atoi(ntimes);
517 while(repeated_offenders_timeout[i2] != 0)
523 new_timeout = repeated_offenders_timeout[i2 - 1]*60;
527 os_calloc(10, sizeof(char), ntimes);
528 new_timeout = repeated_offenders_timeout[ntimes_int]*60;
530 snprintf(ntimes, 9, "%d", ntimes_int);
531 OSHash_Update(repeated_hash,rkey,ntimes);
533 list_entry->time_to_block = new_timeout;
539 /* Continue with the next entry in timeout list*/
540 timeout_node = OSList_GetNextNode(timeout_list);
544 /* If it wasn't added before, do it now */
547 /* executing command */
550 /* We don't need to add to the list if the timeout_value == 0 */
556 snprintf(rkey, 255, "%s%s", timeout_args[0],
559 if(repeated_hash != NULL)
561 if((ntimes = OSHash_Get(repeated_hash, rkey)))
567 ntimes_int = atoi(ntimes);
568 while(repeated_offenders_timeout[i2] != 0)
574 new_timeout = repeated_offenders_timeout[i2 - 1]*60;
578 os_calloc(10, sizeof(char), ntimes);
579 new_timeout = repeated_offenders_timeout[ntimes_int]*60;
581 snprintf(ntimes, 9, "%d", ntimes_int);
582 OSHash_Update(repeated_hash, rkey, ntimes);
584 timeout_value = new_timeout;
588 /* Adding to the repeated offenders list. */
589 OSHash_Add(repeated_hash,
590 strdup(rkey),strdup("0"));
595 /* Creating the timeout entry */
596 os_calloc(1, sizeof(timeout_data), timeout_entry);
597 timeout_entry->command = timeout_args;
598 timeout_entry->time_of_addition = curr_time;
599 timeout_entry->time_to_block = timeout_value;
602 /* Adding command to the timeout list */
603 if(!OSList_AddData(timeout_list, timeout_entry))
605 merror(LIST_ADD_ERROR, ARGV0);
606 FreeTimeoutEntry(timeout_entry);
610 /* If no timeout, we still need to free it in here */
613 char **ss_ta = timeout_args;
616 os_free(*timeout_args);
617 *timeout_args = NULL;
626 /* We didn't add it to the timeout list */
629 char **ss_ta = timeout_args;
631 /* Clear the timeout arguments */
634 os_free(*timeout_args);
635 *timeout_args = NULL;