3 /* Copyright (C) 2009 Trend Micro Inc.
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
16 #include "os_regex/os_regex.h"
17 #include "os_net/os_net.h"
23 /* Timeout data structure */
24 typedef struct _timeout_data
26 time_t time_of_addition;
34 OSListNode *timeout_node;
39 * Shudowns execd properly.
43 /* Removing pending active responses. */
44 merror(EXEC_SHUTDOWN, ARGV0);
46 timeout_node = OSList_GetFirstNode(timeout_list);
49 timeout_data *list_entry;
51 list_entry = (timeout_data *)timeout_node->data;
53 ExecCmd(list_entry->command);
55 /* Delete currently node - already sets the pointer to next */
56 OSList_DeleteCurrentlyNode(timeout_list);
57 timeout_node = OSList_GetCurrentlyNode(timeout_list);
69 /** int main(int argc, char **argv) v0.1
71 int main(int argc, char **argv)
74 int test_config = 0,run_foreground = 0;
75 int gid = 0,m_queue = 0;
77 char *dir = DEFAULTDIR;
78 char *group = GROUPGLOBAL;
79 char *cfg = DEFAULTARPATH;
80 char *xmlcfg = DEFAULTCPATH;
83 /* Setting the name */
87 while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
103 ErrorExit("%s: -g needs an argument.",ARGV0);
108 ErrorExit("%s: -D needs an argument.",ARGV0);
112 ErrorExit("%s: -c needs an argument.",ARGV0);
127 /* Check if the group given are valid */
128 gid = Privsep_GetGroup(group);
130 ErrorExit(USER_ERROR,ARGV0,"",group);
133 /* Privilege separation */
134 if(Privsep_SetGroup(gid) < 0)
135 ErrorExit(SETGID_ERROR,ARGV0,group);
139 if((c = ExecdConfig(xmlcfg)) < 0)
141 ErrorExit(CONFIG_ERROR, ARGV0, xmlcfg);
145 /* Exit if test_config */
150 /* Signal manipulation */
151 StartSIG2(ARGV0, execd_shutdown);
162 /* Active response disabled */
165 verbose(EXEC_DISABLED, ARGV0);
169 /* Creating the PID file */
170 if(CreatePID(ARGV0, getpid()) < 0)
171 merror(PID_ERROR, ARGV0);
174 /* Starting queue (exec queue) */
175 if((m_queue = StartMQ(EXECQUEUEPATH,READ)) < 0)
176 ErrorExit(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
179 /* Start up message */
180 verbose(STARTUP_MSG, ARGV0, (int)getpid());
183 /* The real daemon Now */
194 /** void FreeTimeoutEntry(timeout_data *timeout_entry) v0.1
195 * Free the timeout entry. Must be called after popping it
196 * from the timeout list
198 void FreeTimeoutEntry(void *timeout_entry_pt)
200 timeout_data *timeout_entry;
203 timeout_entry = (timeout_data *)timeout_entry_pt;
210 tmp_str = timeout_entry->command;
212 /* Clearing the command arguments */
221 os_free(timeout_entry->command);
222 timeout_entry->command = NULL;
225 os_free(timeout_entry);
226 timeout_entry = NULL;
235 /** void ExecdStart(int q) v0.2
236 * Main function on the execd. Does all the data receiving ,etc.
238 void ExecdStart(int q)
240 int i, childcount = 0;
243 char buffer[OS_MAXSTR + 1];
244 char *tmp_msg = NULL;
247 char *cmd_args[MAX_ARGS +2];
252 struct timeval socket_timeout;
255 /* Clearing the buffer */
256 memset(buffer, '\0', OS_MAXSTR +1);
259 /* Initializing the cmd arguments */
260 for(i = 0; i<= MAX_ARGS +1; i++)
266 /* Creating list for timeout */
267 timeout_list = OSList_Create();
270 ErrorExit(LIST_ERROR, ARGV0);
278 int added_before = 0;
281 timeout_data *timeout_entry;
284 /* Cleaning up any child. */
288 wp = waitpid((pid_t) -1, NULL, WNOHANG);
291 merror(WAITPID_ERROR, ARGV0);
294 /* if = 0, we still need to wait for the child process */
299 /* Child completed if wp > 0 */
307 /* Getting currently time */
311 /* Checking if there is any timeouted command to execute. */
312 timeout_node = OSList_GetFirstNode(timeout_list);
315 timeout_data *list_entry;
317 list_entry = (timeout_data *)timeout_node->data;
320 if((curr_time - list_entry->time_of_addition) >
321 list_entry->time_to_block)
323 ExecCmd(list_entry->command);
325 /* Deletecurrently node already sets the pointer to next */
326 OSList_DeleteCurrentlyNode(timeout_list);
327 timeout_node = OSList_GetCurrentlyNode(timeout_list);
329 /* Clearing the memory */
330 FreeTimeoutEntry(list_entry);
337 timeout_node = OSList_GetNextNode(timeout_list);
342 /* Setting timeout to EXECD_TIMEOUT */
343 socket_timeout.tv_sec = EXECD_TIMEOUT;
344 socket_timeout.tv_usec= 0;
348 /* Setting FD values */
353 if(select(q+1, &fdset, NULL, NULL, &socket_timeout) == 0)
360 /* Checking for error */
361 if(!FD_ISSET(q, &fdset))
363 merror(SELECT_ERROR, ARGV0);
368 /* Receiving the message */
369 if(recv(q, buffer, OS_MAXSTR, 0) == -1)
371 merror(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
380 /* Getting application name */
384 /* Zeroing the name */
385 tmp_msg = strchr(buffer, ' ');
388 merror(EXECD_INV_MSG, ARGV0, buffer);
395 /* Getting the command to execute (valid name) */
396 command = GetCommandbyName(name, &timeout_value);
400 command = GetCommandbyName(name, &timeout_value);
403 merror(EXEC_INV_NAME, ARGV0, name);
409 /* Command not present. */
410 if(command[0] == '\0')
414 /* Allocating memory for the timeout argument */
415 os_calloc(MAX_ARGS+2, sizeof(char *), timeout_args);
418 /* Adding initial variables to the cmd_arg and to the timeout cmd */
419 cmd_args[0] = command;
420 cmd_args[1] = ADD_ENTRY;
421 os_strdup(command, timeout_args[0]);
422 os_strdup(DELETE_ENTRY, timeout_args[1]);
425 timeout_args[2] = NULL;
428 /* Getting the arguments. */
430 while(i < (MAX_ARGS -1))
432 cmd_args[i] = tmp_msg;
433 cmd_args[i+1] = NULL;
435 tmp_msg = strchr(tmp_msg, ' ');
438 timeout_args[i] = strdup(cmd_args[i]);
439 timeout_args[i+1] = NULL;
445 timeout_args[i] = strdup(cmd_args[i]);
446 timeout_args[i+1] = NULL;
452 /* Check this command was already executed. */
453 timeout_node = OSList_GetFirstNode(timeout_list);
457 /* Checking for the username and ip argument */
458 if(!timeout_args[2] || !timeout_args[3])
461 merror("%s: Invalid number of arguments.", ARGV0);
466 timeout_data *list_entry;
468 list_entry = (timeout_data *)timeout_node->data;
469 if((strcmp(list_entry->command[3], timeout_args[3]) == 0) &&
470 (strcmp(list_entry->command[0], timeout_args[0]) == 0))
472 /* Means we executed this command before
473 * and we don't need to add it again.
478 /* updating the timeout */
479 list_entry->time_of_addition = curr_time;
483 /* Continue with the next entry in timeout list*/
484 timeout_node = OSList_GetNextNode(timeout_list);
488 /* If it wasn't added before, do it now */
491 /* executing command */
494 /* We don't need to add to the list if the timeout_value == 0 */
497 /* Creating the timeout entry */
498 os_calloc(1, sizeof(timeout_data), timeout_entry);
499 timeout_entry->command = timeout_args;
500 timeout_entry->time_of_addition = curr_time;
501 timeout_entry->time_to_block = timeout_value;
504 /* Adding command to the timeout list */
505 if(!OSList_AddData(timeout_list, timeout_entry))
507 merror(LIST_ADD_ERROR, ARGV0);
508 FreeTimeoutEntry(timeout_entry);
512 /* If no timeout, we still need to free it in here */
515 char **ss_ta = timeout_args;
518 os_free(*timeout_args);
519 *timeout_args = NULL;
528 /* We didn't add it to the timeout list */
531 char **ss_ta = timeout_args;
533 /* Clear the timeout arguments */
536 os_free(*timeout_args);
537 *timeout_args = NULL;