Imported Upstream version 2.7
[ossec-hids.git] / src / os_execd / execd.c
index d1b637c..09b5107 100755 (executable)
@@ -1,4 +1,5 @@
-/* @(#) $Id$ */
+/* @(#) $Id: ./src/os_execd/execd.c, 2011/09/08 dcid Exp $
+ */
 
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
@@ -32,17 +33,19 @@ typedef struct _timeout_data
 /* Timeout list */
 OSList *timeout_list;
 OSListNode *timeout_node;
-            
+OSHash *repeated_hash;
+int repeated_offenders_timeout[] = {0,0,0,0,0,0,0};
+
 
 
-/** 
+/**
  * Shudowns execd properly.
  */
 void execd_shutdown()
 {
     /* Removing pending active responses. */
     merror(EXEC_SHUTDOWN, ARGV0);
-    
+
     timeout_node = OSList_GetFirstNode(timeout_list);
     while(timeout_node)
     {
@@ -82,7 +85,7 @@ int main(int argc, char **argv)
 
     /* Setting the name */
     OS_SetName(ARGV0);
-        
+
 
     while((c = getopt(argc, argv, "Vtdhfu:g:D:c:")) != -1){
         switch(c){
@@ -107,6 +110,7 @@ int main(int argc, char **argv)
                 if(!optarg)
                     ErrorExit("%s: -D needs an argument.",ARGV0);
                 dir = optarg;
+                break;
             case 'c':
                 if(!optarg)
                     ErrorExit("%s: -c needs an argument.",ARGV0);
@@ -114,7 +118,7 @@ int main(int argc, char **argv)
                 break;
             case 't':
                 test_config = 1;
-                break;    
+                break;
             default:
                 help(ARGV0);
                 break;
@@ -130,7 +134,7 @@ int main(int argc, char **argv)
         ErrorExit(USER_ERROR,ARGV0,"",group);
 
 
-    /* Privilege separation */  
+    /* Privilege separation */
     if(Privsep_SetGroup(gid) < 0)
         ErrorExit(SETGID_ERROR,ARGV0,group);
 
@@ -145,18 +149,18 @@ int main(int argc, char **argv)
     /* Exit if test_config */
     if(test_config)
         exit(0);
-        
-        
+
+
     /* Signal manipulation */
     StartSIG2(ARGV0, execd_shutdown);
 
-    
-    if (!run_foreground) 
+
+    if (!run_foreground)
     {
         /* Going daemon */
         nowDaemon();
         goDaemon();
-    } 
+    }
 
 
     /* Active response disabled */
@@ -165,12 +169,12 @@ int main(int argc, char **argv)
         verbose(EXEC_DISABLED, ARGV0);
         exit(0);
     }
-    
+
     /* Creating the PID file */
     if(CreatePID(ARGV0, getpid()) < 0)
         merror(PID_ERROR, ARGV0);
 
-    
+
     /* Starting queue (exec queue) */
     if((m_queue = StartMQ(EXECQUEUEPATH,READ)) < 0)
         ErrorExit(QUEUE_ERROR, ARGV0, EXECQUEUEPATH, strerror(errno));
@@ -178,11 +182,11 @@ int main(int argc, char **argv)
 
     /* Start up message */
     verbose(STARTUP_MSG, ARGV0, (int)getpid());
-        
 
-    /* The real daemon Now */  
+
+    /* The real daemon Now */
     ExecdStart(m_queue);
-    
+
     exit(0);
 }
 
@@ -206,7 +210,7 @@ void FreeTimeoutEntry(void *timeout_entry_pt)
     {
         return;
     }
-    
+
     tmp_str = timeout_entry->command;
 
     /* Clearing the command arguments */
@@ -239,7 +243,7 @@ void ExecdStart(int q)
 {
     int i, childcount = 0;
     time_t curr_time;
-    
+
     char buffer[OS_MAXSTR + 1];
     char *tmp_msg = NULL;
     char *name;
@@ -251,32 +255,43 @@ void ExecdStart(int q)
     fd_set fdset;
     struct timeval socket_timeout;
 
-    
+
     /* Clearing the buffer */
     memset(buffer, '\0', OS_MAXSTR +1);
-    
-    
+
+
     /* Initializing the cmd arguments */
     for(i = 0; i<= MAX_ARGS +1; i++)
     {
         cmd_args[i] = NULL;
     }
-   
-    
+
+
     /* Creating list for timeout */
-    timeout_list = OSList_Create(); 
+    timeout_list = OSList_Create();
     if(!timeout_list)
     {
         ErrorExit(LIST_ERROR, ARGV0);
     }
-    
-   
+
+
+    if(repeated_offenders_timeout[0] != 0)
+    {
+        repeated_hash = OSHash_Create();
+    }
+    else
+    {
+        repeated_hash = NULL;
+    }
+
+
+
     /* Main loop. */
     while(1)
     {
         int timeout_value;
         int added_before = 0;
-    
+
         char **timeout_args;
         timeout_data *timeout_entry;
 
@@ -289,6 +304,7 @@ void ExecdStart(int q)
             if (wp < 0)
             {
                 merror(WAITPID_ERROR, ARGV0);
+                break;
             }
 
             /* if = 0, we still need to wait for the child process */
@@ -315,13 +331,13 @@ void ExecdStart(int q)
             timeout_data *list_entry;
 
             list_entry = (timeout_data *)timeout_node->data;
-            
+
             /* Timeouted */
-            if((curr_time - list_entry->time_of_addition) > 
+            if((curr_time - list_entry->time_of_addition) >
                     list_entry->time_to_block)
             {
                 ExecCmd(list_entry->command);
-                
+
                 /* Deletecurrently node already sets the pointer to next */
                 OSList_DeleteCurrentlyNode(timeout_list);
                 timeout_node = OSList_GetCurrentlyNode(timeout_list);
@@ -338,7 +354,7 @@ void ExecdStart(int q)
             }
         }
 
-        
+
         /* Setting timeout to EXECD_TIMEOUT */
         socket_timeout.tv_sec = EXECD_TIMEOUT;
         socket_timeout.tv_usec= 0;
@@ -379,8 +395,8 @@ void ExecdStart(int q)
 
         /* Getting application name */
         name = buffer;
-        
-        
+
+
         /* Zeroing the name */
         tmp_msg = strchr(buffer, ' ');
         if(!tmp_msg)
@@ -413,10 +429,10 @@ void ExecdStart(int q)
 
         /* Allocating memory for the timeout argument */
         os_calloc(MAX_ARGS+2, sizeof(char *), timeout_args);
-        
+
 
         /* Adding initial variables to the cmd_arg and to the timeout cmd */
-        cmd_args[0] = command; 
+        cmd_args[0] = command;
         cmd_args[1] = ADD_ENTRY;
         os_strdup(command, timeout_args[0]);
         os_strdup(DELETE_ENTRY, timeout_args[1]);
@@ -447,7 +463,7 @@ void ExecdStart(int q)
 
             i++;
         }
-        
+
 
         /* Check this command was already executed. */
         timeout_node = OSList_GetFirstNode(timeout_list);
@@ -460,14 +476,16 @@ void ExecdStart(int q)
             added_before = 1;
             merror("%s: Invalid number of arguments.", ARGV0);
         }
-        
+
+
+
         while(timeout_node)
         {
             timeout_data *list_entry;
 
             list_entry = (timeout_data *)timeout_node->data;
             if((strcmp(list_entry->command[3], timeout_args[3]) == 0) &&
-               (strcmp(list_entry->command[0], timeout_args[0]) == 0)) 
+               (strcmp(list_entry->command[0], timeout_args[0]) == 0))
             {
                 /* Means we executed this command before
                  * and we don't need to add it again.
@@ -477,6 +495,42 @@ void ExecdStart(int q)
 
                 /* updating the timeout */
                 list_entry->time_of_addition = curr_time;
+
+                if(repeated_offenders_timeout[0] != 0 &&
+                   repeated_hash != NULL &&
+                   strncmp(timeout_args[3],"-", 1) != 0)
+                {
+                    char *ntimes = NULL;
+                    char rkey[256];
+                    rkey[255] = '\0';
+                    snprintf(rkey, 255, "%s%s", list_entry->command[0],
+                                                timeout_args[3]);
+
+                    if((ntimes = OSHash_Get(repeated_hash, rkey)))
+                    {
+                        int ntimes_int = 0;
+                        int i2 = 0;
+                        int new_timeout = 0;
+                        ntimes_int = atoi(ntimes);
+                        while(repeated_offenders_timeout[i2] != 0)
+                        {
+                            i2++;
+                        }
+                        if(ntimes_int >= i2)
+                        {
+                            new_timeout = repeated_offenders_timeout[i2 - 1]*60;
+                        }
+                        else
+                        {
+                            os_calloc(10, sizeof(char), ntimes);
+                            new_timeout = repeated_offenders_timeout[ntimes_int]*60;
+                            ntimes_int++;
+                            snprintf(ntimes, 9, "%d", ntimes_int);
+                            OSHash_Update(repeated_hash,rkey,ntimes);
+                        }
+                        list_entry->time_to_block = new_timeout;
+                    }
+                }
                 break;
             }
 
@@ -494,6 +548,48 @@ void ExecdStart(int q)
             /* We don't need to add to the list if the timeout_value == 0 */
             if(timeout_value)
             {
+                char *ntimes;
+                char rkey[256];
+                rkey[255] = '\0';
+                snprintf(rkey, 255, "%s%s", timeout_args[0],
+                                            timeout_args[3]);
+
+                if(repeated_hash != NULL)
+                {
+                  if((ntimes = OSHash_Get(repeated_hash, rkey)))
+                  {
+                    int ntimes_int = 0;
+                    int i2 = 0;
+                    int new_timeout = 0;
+
+                    ntimes_int = atoi(ntimes);
+                    while(repeated_offenders_timeout[i2] != 0)
+                    {
+                        i2++;
+                    }
+                    if(ntimes_int >= i2)
+                    {
+                        new_timeout = repeated_offenders_timeout[i2 - 1]*60;
+                    }
+                    else
+                    {
+                        os_calloc(10, sizeof(char), ntimes);
+                        new_timeout = repeated_offenders_timeout[ntimes_int]*60;
+                        ntimes_int++;
+                        snprintf(ntimes, 9, "%d", ntimes_int);
+                        OSHash_Update(repeated_hash, rkey, ntimes);
+                    }
+                    timeout_value = new_timeout;
+                  }
+                  else
+                  {
+                      /* Adding to the repeated offenders list. */
+                      OSHash_Add(repeated_hash,
+                           strdup(rkey),strdup("0"));
+                  }
+                }
+
+
                 /* Creating the timeout entry */
                 os_calloc(1, sizeof(timeout_data), timeout_entry);
                 timeout_entry->command = timeout_args;
@@ -506,9 +602,9 @@ void ExecdStart(int q)
                 {
                     merror(LIST_ADD_ERROR, ARGV0);
                     FreeTimeoutEntry(timeout_entry);
-                } 
+                }
             }
-            
+
             /* If no timeout, we still need to free it in here */
             else
             {
@@ -524,7 +620,7 @@ void ExecdStart(int q)
 
             childcount++;
         }
-        
+
         /* We didn't add it to the timeout list */
         else
         {