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 * Shudowns 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 char *dir = DEFAULTDIR;
81 char *group = GROUPGLOBAL;
82 char *cfg = DEFAULTARPATH;
83 char *xmlcfg = DEFAULTCPATH;
86 /* Setting the name */
90 while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
106 ErrorExit("%s: -g needs an argument.",ARGV0);
111 ErrorExit("%s: -D needs an argument.",ARGV0);
116 ErrorExit("%s: -c needs an argument.",ARGV0);
131 /* Check if the group given are valid */
132 gid = Privsep_GetGroup(group);
134 ErrorExit(USER_ERROR,ARGV0,"",group);
137 /* Privilege separation */
138 if(Privsep_SetGroup(gid) < 0)
139 ErrorExit(SETGID_ERROR,ARGV0,group);
143 if((c = ExecdConfig(xmlcfg)) < 0)
145 ErrorExit(CONFIG_ERROR, ARGV0, xmlcfg);
149 /* Exit if test_config */
154 /* Signal manipulation */
155 StartSIG2(ARGV0, execd_shutdown);
166 /* Active response disabled */
169 verbose(EXEC_DISABLED, ARGV0);
173 /* Creating the PID file */
174 if(CreatePID(ARGV0, getpid()) < 0)
175 merror(PID_ERROR, ARGV0);
178 /* Starting queue (exec queue) */
179 if((m_queue = StartMQ(EXECQUEUEPATH,READ)) < 0)
180 ErrorExit(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
183 /* Start up message */
184 verbose(STARTUP_MSG, ARGV0, (int)getpid());
187 /* The real daemon Now */
198 /** void FreeTimeoutEntry(timeout_data *timeout_entry) v0.1
199 * Free the timeout entry. Must be called after popping it
200 * from the timeout list
202 void FreeTimeoutEntry(void *timeout_entry_pt)
204 timeout_data *timeout_entry;
207 timeout_entry = (timeout_data *)timeout_entry_pt;
214 tmp_str = timeout_entry->command;
216 /* Clearing the command arguments */
225 os_free(timeout_entry->command);
226 timeout_entry->command = NULL;
229 os_free(timeout_entry);
230 timeout_entry = NULL;
239 /** void ExecdStart(int q) v0.2
240 * Main function on the execd. Does all the data receiving ,etc.
242 void ExecdStart(int q)
244 int i, childcount = 0;
247 char buffer[OS_MAXSTR + 1];
248 char *tmp_msg = NULL;
251 char *cmd_args[MAX_ARGS +2];
256 struct timeval socket_timeout;
259 /* Clearing the buffer */
260 memset(buffer, '\0', OS_MAXSTR +1);
263 /* Initializing the cmd arguments */
264 for(i = 0; i<= MAX_ARGS +1; i++)
270 /* Creating list for timeout */
271 timeout_list = OSList_Create();
274 ErrorExit(LIST_ERROR, ARGV0);
278 if(repeated_offenders_timeout[0] != 0)
280 repeated_hash = OSHash_Create();
284 repeated_hash = NULL;
293 int added_before = 0;
296 timeout_data *timeout_entry;
299 /* Cleaning up any child. */
303 wp = waitpid((pid_t) -1, NULL, WNOHANG);
306 merror(WAITPID_ERROR, ARGV0);
310 /* if = 0, we still need to wait for the child process */
315 /* Child completed if wp > 0 */
323 /* Getting currently time */
327 /* Checking if there is any timeouted command to execute. */
328 timeout_node = OSList_GetFirstNode(timeout_list);
331 timeout_data *list_entry;
333 list_entry = (timeout_data *)timeout_node->data;
336 if((curr_time - list_entry->time_of_addition) >
337 list_entry->time_to_block)
339 ExecCmd(list_entry->command);
341 /* Deletecurrently node already sets the pointer to next */
342 OSList_DeleteCurrentlyNode(timeout_list);
343 timeout_node = OSList_GetCurrentlyNode(timeout_list);
345 /* Clearing the memory */
346 FreeTimeoutEntry(list_entry);
353 timeout_node = OSList_GetNextNode(timeout_list);
358 /* Setting timeout to EXECD_TIMEOUT */
359 socket_timeout.tv_sec = EXECD_TIMEOUT;
360 socket_timeout.tv_usec= 0;
364 /* Setting FD values */
369 if(select(q+1, &fdset, NULL, NULL, &socket_timeout) == 0)
376 /* Checking for error */
377 if(!FD_ISSET(q, &fdset))
379 merror(SELECT_ERROR, ARGV0);
384 /* Receiving the message */
385 if(recv(q, buffer, OS_MAXSTR, 0) == -1)
387 merror(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
396 /* Getting application name */
400 /* Zeroing the name */
401 tmp_msg = strchr(buffer, ' ');
404 merror(EXECD_INV_MSG, ARGV0, buffer);
411 /* Getting the command to execute (valid name) */
412 command = GetCommandbyName(name, &timeout_value);
416 command = GetCommandbyName(name, &timeout_value);
419 merror(EXEC_INV_NAME, ARGV0, name);
425 /* Command not present. */
426 if(command[0] == '\0')
430 /* Allocating memory for the timeout argument */
431 os_calloc(MAX_ARGS+2, sizeof(char *), timeout_args);
434 /* Adding initial variables to the cmd_arg and to the timeout cmd */
435 cmd_args[0] = command;
436 cmd_args[1] = ADD_ENTRY;
437 os_strdup(command, timeout_args[0]);
438 os_strdup(DELETE_ENTRY, timeout_args[1]);
441 timeout_args[2] = NULL;
444 /* Getting the arguments. */
446 while(i < (MAX_ARGS -1))
448 cmd_args[i] = tmp_msg;
449 cmd_args[i+1] = NULL;
451 tmp_msg = strchr(tmp_msg, ' ');
454 timeout_args[i] = strdup(cmd_args[i]);
455 timeout_args[i+1] = NULL;
461 timeout_args[i] = strdup(cmd_args[i]);
462 timeout_args[i+1] = NULL;
468 /* Check this command was already executed. */
469 timeout_node = OSList_GetFirstNode(timeout_list);
473 /* Checking for the username and ip argument */
474 if(!timeout_args[2] || !timeout_args[3])
477 merror("%s: Invalid number of arguments.", ARGV0);
484 timeout_data *list_entry;
486 list_entry = (timeout_data *)timeout_node->data;
487 if((strcmp(list_entry->command[3], timeout_args[3]) == 0) &&
488 (strcmp(list_entry->command[0], timeout_args[0]) == 0))
490 /* Means we executed this command before
491 * and we don't need to add it again.
496 /* updating the timeout */
497 list_entry->time_of_addition = curr_time;
499 if(repeated_offenders_timeout[0] != 0 &&
500 repeated_hash != NULL &&
501 strncmp(timeout_args[3],"-", 1) != 0)
506 snprintf(rkey, 255, "%s%s", list_entry->command[0],
509 if((ntimes = OSHash_Get(repeated_hash, rkey)))
514 ntimes_int = atoi(ntimes);
515 while(repeated_offenders_timeout[i2] != 0)
521 new_timeout = repeated_offenders_timeout[i2 - 1]*60;
525 os_calloc(10, sizeof(char), ntimes);
526 new_timeout = repeated_offenders_timeout[ntimes_int]*60;
528 snprintf(ntimes, 9, "%d", ntimes_int);
529 OSHash_Update(repeated_hash,rkey,ntimes);
531 list_entry->time_to_block = new_timeout;
537 /* Continue with the next entry in timeout list*/
538 timeout_node = OSList_GetNextNode(timeout_list);
542 /* If it wasn't added before, do it now */
545 /* executing command */
548 /* We don't need to add to the list if the timeout_value == 0 */
554 snprintf(rkey, 255, "%s%s", timeout_args[0],
557 if(repeated_hash != NULL)
559 if((ntimes = OSHash_Get(repeated_hash, rkey)))
565 ntimes_int = atoi(ntimes);
566 while(repeated_offenders_timeout[i2] != 0)
572 new_timeout = repeated_offenders_timeout[i2 - 1]*60;
576 os_calloc(10, sizeof(char), ntimes);
577 new_timeout = repeated_offenders_timeout[ntimes_int]*60;
579 snprintf(ntimes, 9, "%d", ntimes_int);
580 OSHash_Update(repeated_hash, rkey, ntimes);
582 timeout_value = new_timeout;
586 /* Adding to the repeated offenders list. */
587 OSHash_Add(repeated_hash,
588 strdup(rkey),strdup("0"));
593 /* Creating the timeout entry */
594 os_calloc(1, sizeof(timeout_data), timeout_entry);
595 timeout_entry->command = timeout_args;
596 timeout_entry->time_of_addition = curr_time;
597 timeout_entry->time_to_block = timeout_value;
600 /* Adding command to the timeout list */
601 if(!OSList_AddData(timeout_list, timeout_entry))
603 merror(LIST_ADD_ERROR, ARGV0);
604 FreeTimeoutEntry(timeout_entry);
608 /* If no timeout, we still need to free it in here */
611 char **ss_ta = timeout_args;
614 os_free(*timeout_args);
615 *timeout_args = NULL;
624 /* We didn't add it to the timeout list */
627 char **ss_ta = timeout_args;
629 /* Clear the timeout arguments */
632 os_free(*timeout_args);
633 *timeout_args = NULL;