Imported Upstream version 2.7
[ossec-hids.git] / src / rootcheck / common.c
index 67ae180..eec625a 100755 (executable)
@@ -1,21 +1,22 @@
-/* @(#) $Id: common.c,v 1.25 2009/06/24 18:53:07 dcid Exp $ */
+/* @(#) $Id: ./src/rootcheck/common.c, 2011/09/08 dcid Exp $
+ */
 
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
  *
  * This program is a free software; you can redistribute it
  * and/or modify it under the terms of the GNU General Public
- * License (version 3) as published by the FSF - Free Software
+ * License (version 2) as published by the FSF - Free Software
  * Foundation
  *
- * License details at the LICENSE file included with OSSEC or 
+ * License details at the LICENSE file included with OSSEC or
  * online at: http://www.ossec.net/main/license/ .
  */
 
+
 #include "shared.h"
 #include "rootcheck.h"
-#include "os_regex/os_regex.h" 
+#include "os_regex/os_regex.h"
 
 
 
@@ -59,7 +60,7 @@ int rk_check_dir(char *dir, char *file, char *pattern)
     {
         /* Just ignore . and ..  */
         if((strcmp(entry->d_name,".") == 0) ||
-           (strcmp(entry->d_name,"..") == 0)) 
+           (strcmp(entry->d_name,"..") == 0))
         {
             continue;
         }
@@ -68,7 +69,7 @@ int rk_check_dir(char *dir, char *file, char *pattern)
         /* Creating new file + path string */
         snprintf(f_name, PATH_MAX +1, "%s/%s",dir, entry->d_name);
 
-        
+
         /* Checking if the read entry, matches the provided file name. */
         if(strncasecmp(file, "r:", 2) == 0)
         {
@@ -80,7 +81,7 @@ int rk_check_dir(char *dir, char *file, char *pattern)
                 }
             }
         }
-        
+
         /* Trying without regex. */
         else
         {
@@ -93,7 +94,7 @@ int rk_check_dir(char *dir, char *file, char *pattern)
             }
         }
 
-        
+
         /* Checking if file is a directory */
         if(lstat(f_name, &statbuf_local) == 0)
         {
@@ -119,11 +120,13 @@ int rk_check_dir(char *dir, char *file, char *pattern)
 int rk_check_file(char *file, char *pattern)
 {
     char *split_file;
-    
+    int full_negate = 0;
+    int pt_result = 0;
+
     FILE *fp;
     char buf[OS_SIZE_2048 +1];
-    
-    
+
+
     /* If string is null, we don't match */
     if(file == NULL)
     {
@@ -143,7 +146,7 @@ int rk_check_file(char *file, char *pattern)
     /* Getting each file */
     do
     {
-        
+
 
         /* If we don't have a pattern, just check if the file/dir is there */
         if(pattern == NULL)
@@ -165,7 +168,7 @@ int rk_check_file(char *file, char *pattern)
 
                 while(rootcheck.alert_msg[i] && (i < 255))
                     i++;
-                
+
                 if(!rootcheck.alert_msg[i])
                     os_strdup(_b_msg, rootcheck.alert_msg[i]);
 
@@ -175,11 +178,14 @@ int rk_check_file(char *file, char *pattern)
 
         else
         {
+            full_negate = pt_check_negate(pattern);
             /* Checking for a content in the file */
+            debug1("checking file: %s", file);
             fp = fopen(file, "r");
             if(fp)
             {
 
+                debug1(" starting new file: %s", file);
                 buf[OS_SIZE_2048] = '\0';
                 while(fgets(buf, OS_SIZE_2048, fp) != NULL)
                 {
@@ -204,8 +210,13 @@ int rk_check_file(char *file, char *pattern)
 
 
                     /* Matched */
-                    if(pt_matches(buf, pattern))
+                    pt_result = pt_matches(buf, pattern);
+                    debug1("Buf == \"%s\"", buf);
+                    debug1("Pattern == \"%s\"", pattern);
+                    debug1("pt_result == %d and full_negate == %d", pt_result, full_negate);
+                    if((pt_result == 1 && full_negate == 0) )
                     {
+                        debug1("alerting file %s on line %s", file, buf);
                         int i = 0;
                         char _b_msg[OS_SIZE_1024 +1];
 
@@ -217,7 +228,7 @@ int rk_check_file(char *file, char *pattern)
                         _b_msg[OS_SIZE_1024] = '\0';
                         snprintf(_b_msg, OS_SIZE_1024, " File: %s.",
                                  file);
-                        
+
                         /* Already present. */
                         if(_is_str_in_array(rootcheck.alert_msg, _b_msg))
                         {
@@ -232,9 +243,45 @@ int rk_check_file(char *file, char *pattern)
 
                         return(1);
                     }
+                    else if((pt_result == 0 && full_negate == 1) )
+                    {
+                        /* found a full+negate match so no longer need to search
+                         * break out of loop and amke sure the full negate does
+                         * not alertin
+                         */
+                        debug1("found a complete match for full_negate");
+                        full_negate = 0;
+                        break;
+                    }
                 }
 
                 fclose(fp);
+
+                if(full_negate == 1)
+                {
+                    debug1("full_negate alerting - file %s",file);
+                    int i = 0;
+                    char _b_msg[OS_SIZE_1024 +1];
+
+                    /* Generating the alert itself. */
+                    _b_msg[OS_SIZE_1024] = '\0';
+                    snprintf(_b_msg, OS_SIZE_1024, " File: %s.",
+                             file);
+
+                    /* Already present. */
+                    if(_is_str_in_array(rootcheck.alert_msg, _b_msg))
+                    {
+                        return(1);
+                    }
+
+                    while(rootcheck.alert_msg[i] && (i < 255))
+                        i++;
+
+                    if(!rootcheck.alert_msg[i])
+                    os_strdup(_b_msg, rootcheck.alert_msg[i]);
+
+                    return(1);
+                }
             }
         }
 
@@ -247,8 +294,8 @@ int rk_check_file(char *file, char *pattern)
                 split_file++;
             }
         }
-        
-        
+
+
     }while(split_file);
 
 
@@ -256,6 +303,49 @@ int rk_check_file(char *file, char *pattern)
 }
 
 
+/** int pt_check_negate(char *pattern)
+ * Checks if the patterns is all negate values and if so returns 1
+ * else return 0
+ */
+int pt_check_negate(char *pattern)
+{
+    char *mypattern = NULL;
+    os_strdup(pattern, mypattern);
+    char *tmp_pt = mypattern;
+    char *tmp_pattern = mypattern;
+    char *tmp_ret = NULL;
+
+
+    while(tmp_pt != NULL)
+    {
+        /* We first look for " && " */
+        tmp_pt = strchr(tmp_pattern, ' ');
+        if(tmp_pt && tmp_pt[1] == '&' && tmp_pt[2] == '&' && tmp_pt[3] == ' ')
+        {
+            /* Marking pointer to clean it up */
+            tmp_ret = tmp_pt;
+
+            *tmp_pt = '\0';
+            tmp_pt += 4;
+        }
+        else
+        {
+            tmp_pt = NULL;
+        }
+
+        if(*tmp_pattern != '!')
+        {
+            free(mypattern);
+            return 0;
+        }
+
+        tmp_pattern = tmp_pt;
+    }
+
+    debug1("pattern: %s is fill_negate",pattern);
+    free(mypattern);
+    return(1);
+}
 
 /** int pt_matches(char *str, char *pattern)
  * Checks if the specific pattern is present on str.
@@ -263,7 +353,7 @@ int rk_check_file(char *file, char *pattern)
  *                                =: (for equal) - default - strcasecmp
  *                                r: (for ossec regexes)
  *                                >: (for strcmp greater)
- *                                <: (for strcmp  lower)    
+ *                                <: (for strcmp  lower)
  *
  * Multiple patterns can be specified by using " && " between them.
  * All of them must match for it to return true.
@@ -281,16 +371,16 @@ int pt_matches(char *str, char *pattern)
     {
         return(0);
     }
-    
+
     while(tmp_pt != NULL)
     {
         /* We first look for " && " */
         tmp_pt = strchr(pattern, ' ');
         if(tmp_pt && tmp_pt[1] == '&' && tmp_pt[2] == '&' && tmp_pt[3] == ' ')
         {
-            /* Marking pointer to clean it up */        
+            /* Marking pointer to clean it up */
             tmp_ret = tmp_pt;
-                    
+
             *tmp_pt = '\0';
             tmp_pt += 4;
         }
@@ -308,7 +398,7 @@ int pt_matches(char *str, char *pattern)
             pattern++;
             neg = 1;
         }
-        
+
 
         /* Doing strcasecmp */
         if(strncasecmp(pattern, "=:", 2) == 0)
@@ -324,6 +414,7 @@ int pt_matches(char *str, char *pattern)
             pattern += 2;
             if(OS_Regex(pattern, str))
             {
+                debug1("pattern: %s matches %s.",pattern, str);
                 ret_code = 1;
             }
         }
@@ -347,7 +438,7 @@ int pt_matches(char *str, char *pattern)
         {
             #ifdef WIN32
             char final_file[2048 +1];
-            
+
             /* Try to get Windows variable */
             if(*pattern == '%')
             {
@@ -366,7 +457,7 @@ int pt_matches(char *str, char *pattern)
             {
                 ret_code = 1;
             }
-            
+
             #else
             if(strcasecmp(pattern, str) == 0)
             {
@@ -383,7 +474,7 @@ int pt_matches(char *str, char *pattern)
             tmp_ret = NULL;
         }
 
-        
+
         /* If we have "!", return true if we don't match */
         if(neg == 1)
         {
@@ -401,7 +492,7 @@ int pt_matches(char *str, char *pattern)
                 break;
             }
         }
-        
+
         ret_code = 1;
         pattern = tmp_pt;
     }
@@ -417,8 +508,22 @@ int pt_matches(char *str, char *pattern)
  */
 char *normalize_string(char *str)
 {
-    int str_sz = strlen(str) -1;
-    
+    unsigned int str_sz = strlen(str);
+    // return zero-length str as is
+    if (str_sz == 0) {
+       return str;
+    } else {
+        str_sz--;
+    }
+    // remove trailing spaces
+    while(str[str_sz] == ' ' || str[str_sz] == '\t')
+    {
+        if(str_sz == 0)
+            break;
+
+        str[str_sz--] = '\0';
+    }
+    // ignore leading spaces
     while(*str != '\0')
     {
         if(*str == ' ' || *str == '\t')
@@ -431,17 +536,13 @@ char *normalize_string(char *str)
         }
     }
 
-    while(str[str_sz] == ' ' || str[str_sz] == '\t')
-    {
-        str[str_sz] = '\0';
-        str_sz--;
-    }
-
     return(str);
 }
 
 
 
+
+
 /** int isfile_ondir(char *file, char *dir)
  * Checks is 'file' is present on 'dir' using readdir
  */
@@ -450,7 +551,7 @@ int isfile_ondir(char *file, char *dir)
     DIR *dp = NULL;
     struct dirent *entry;
     dp = opendir(dir);
-    
+
     if(!dp)
         return(0);
 
@@ -462,7 +563,7 @@ int isfile_ondir(char *file, char *dir)
             return(1);
         }
     }
-    
+
     closedir(dp);
     return(0);
 }
@@ -475,19 +576,19 @@ int isfile_ondir(char *file, char *dir)
 int is_file(char *file_name)
 {
     int ret = 0;
-    
+
     struct stat statbuf;
     FILE *fp = NULL;
     DIR *dp = NULL;
 
 
     #ifndef WIN32
-    
+
     char curr_dir[1024];
-    
+
     char *file_dirname;
     char *file_basename;
-    
+
 
     curr_dir[1023] = '\0';
 
@@ -504,7 +605,7 @@ int is_file(char *file_name)
         return(0);
     }
 
-    
+
     /* If file_basename == file_name, then the file
      * only has one slash at the beginning.
      */
@@ -565,7 +666,7 @@ int is_file(char *file_name)
             ret = 1;
         }
     }
-    
+
     #else
     dp = opendir(file_name);
     if(dp)
@@ -573,10 +674,10 @@ int is_file(char *file_name)
         closedir(dp);
         ret = 1;
     }
-                                                                                
+
     #endif /* WIN32 */
 
-    
+
     /* Trying other calls */
     if( (stat(file_name, &statbuf) < 0) &&
         #ifndef WIN32
@@ -590,7 +691,7 @@ int is_file(char *file_name)
     /* must close it over here */
     if(fp)
         fclose(fp);
-    
+
     return(1);
 }
 
@@ -625,7 +726,7 @@ int del_plist(void *p_list_p)
         {
             free(pinfo->p_path);
         }
-        
+
         free(l_node->data);
 
         if(p_node)
@@ -681,7 +782,7 @@ int is_process(char *value, void *p_list_p)
             char _b_msg[OS_SIZE_1024 +1];
 
             _b_msg[OS_SIZE_1024] = '\0';
-            
+
             snprintf(_b_msg, OS_SIZE_1024, " Process: %s.",
                      pinfo->p_path);
 
@@ -690,7 +791,7 @@ int is_process(char *value, void *p_list_p)
             {
                 return(1);
             }
-            
+
             while(rootcheck.alert_msg[i] && (i< 255))
                 i++;
 
@@ -706,7 +807,7 @@ int is_process(char *value, void *p_list_p)
     return(0);
 
 }
+
+
 
 /* EOF */