novi upstream verzije 2.8.3
[ossec-hids.git] / src / syscheckd / seechanges.c
index 15496c8..7bf2ee1 100755 (executable)
 #include "shared.h"
 #include "os_crypto/md5/md5_op.h"
 
+#ifdef USE_MAGIC
+#include <magic.h>
+extern magic_t magic_cookie;
 
+int is_text(magic_t cookie, const void* buf, size_t len)
+{
+    const char* magic = magic_buffer(cookie, buf, len);
+
+    if(!magic)
+    {
+        const char* err = magic_error(cookie);
+        merror("%s: ERROR: magic_buffer: %s", ARGV0, err ? err : "unknown");
+        return(1); // TODO default to true?
+    }
+    else
+    {
+        if(strncmp(magic, "text/", 5) == 0) return(1);
+    }
+
+    return(0);
+}
+#endif
 
 /* Generate diffs alerts. */
 char *gen_diff_alert(char *filename, int alert_diff_time)
@@ -115,13 +136,24 @@ int seechanges_dupfile(char *old, char *new)
         return(0);
     }
 
-    while((n = fread(buf, 1, 2048, fpr)) > 0)
+    n = fread(buf, 1, 2048, fpr);
+    #ifdef USE_MAGIC
+    if(is_text(magic_cookie, buf, n) == 0)
+    {
+        goto cleanup;
+    }
+    #endif
+
+    do
     {
         buf[n] = '\0';
         fwrite(buf, n, 1, fpw);
-
     }
+    while((n = fread(buf, 1, 2048, fpr)) > 0);
 
+#ifdef USE_MAGIC
+cleanup:
+#endif
     fclose(fpr);
     fclose(fpw);
     return(1);
@@ -187,23 +219,42 @@ int seechanges_createpath(char *filename)
 /* Checks if the file has changed */
 char *seechanges_addfile(char *filename)
 {
-    int date_of_change;
+    time_t old_date_of_change;
+    time_t new_date_of_change;
+
     char old_location[OS_MAXSTR +1];
     char tmp_location[OS_MAXSTR +1];
+    char diff_location[OS_MAXSTR + 1];
+    char old_tmp[OS_MAXSTR + 1];
+    char new_tmp[OS_MAXSTR + 1];
+    char diff_tmp[OS_MAXSTR + 1];
+
     char diff_cmd[OS_MAXSTR +1];
 
     os_md5 md5sum_old;
     os_md5 md5sum_new;
+    int status = -1;
+
 
     old_location[OS_MAXSTR] = '\0';
     tmp_location[OS_MAXSTR] = '\0';
+    diff_location[OS_MAXSTR] = '\0';
+    old_tmp[OS_MAXSTR] = '\0';
+    new_tmp[OS_MAXSTR] = '\0';
+    diff_tmp[OS_MAXSTR] = '\0';
     diff_cmd[OS_MAXSTR] = '\0';
     md5sum_new[0] = '\0';
     md5sum_old[0] = '\0';
 
 
-    snprintf(old_location, OS_MAXSTR, "%s/local/%s/%s", DIFF_DIR_PATH, filename +1,
-             DIFF_LAST_FILE);
+    snprintf(
+        old_location,
+        OS_MAXSTR,
+        "%s/local/%s/%s",
+        DIFF_DIR_PATH,
+        filename + 1,
+        DIFF_LAST_FILE
+    );
 
 
     /* If the file is not there, rename new location to last location. */
@@ -235,9 +286,18 @@ char *seechanges_addfile(char *filename)
 
 
     /* Saving the old file at timestamp and renaming new to last. */
-    date_of_change = File_DateofChange(old_location);
-    snprintf(tmp_location, OS_MAXSTR, "%s/local/%s/state.%d", DIFF_DIR_PATH, filename +1,
-             date_of_change);
+    old_date_of_change = File_DateofChange(old_location);
+
+    snprintf(
+        tmp_location,
+        OS_MAXSTR,
+        "%s/local/%s/state.%d",
+        DIFF_DIR_PATH,
+        filename + 1,
+       (int)old_date_of_change
+    );
+
+
     rename(old_location, tmp_location);
     if(seechanges_dupfile(filename, old_location) != 1)
     {
@@ -246,25 +306,100 @@ char *seechanges_addfile(char *filename)
     }
 
 
+    new_date_of_change = File_DateofChange(old_location);
+
+    /* Create file names */
+    snprintf(
+        old_tmp,
+        OS_MAXSTR,
+        "%s/%s/syscheck-changes-%s-%d",
+        DEFAULTDIR,
+        TMP_DIR,
+        md5sum_old,
+        (int)old_date_of_change
+    );
+
+    snprintf(
+        new_tmp,
+        OS_MAXSTR,
+        "%s/%s/syscheck-changes-%s-%d",
+        DEFAULTDIR,
+        TMP_DIR,
+        md5sum_new,
+        (int)new_date_of_change
+    );
+
+    snprintf(
+        diff_tmp,
+        OS_MAXSTR,
+        "%s/%s/syscheck-changes-%s-%d-%s-%d",
+        DEFAULTDIR,
+        TMP_DIR,
+        md5sum_old,
+        (int)old_date_of_change,
+        md5sum_new,
+        (int)new_date_of_change
+    );
+
+    /* Create diff location */
+    snprintf(
+        diff_location,
+        OS_MAXSTR,
+        "%s/local/%s/diff.%d",
+        DIFF_DIR_PATH,
+        filename + 1,
+        (int)new_date_of_change
+    );
+
+    /* Create symlinks */
+    if (symlink(old_location, old_tmp) == -1) {
+        merror(LINK_ERROR, ARGV0, old_location, old_tmp, errno, strerror(errno));
+        goto cleanup;
+    }
+
+    if (symlink(tmp_location, new_tmp) == -1) {
+        merror(LINK_ERROR, ARGV0, tmp_location, new_tmp, errno, strerror(errno));
+        goto cleanup;
+    }
+
+    if (symlink(diff_location, diff_tmp) == -1) {
+        merror(LINK_ERROR, ARGV0, diff_location, diff_tmp, errno, strerror(errno));
+        goto cleanup;
+    }
+
+
+
     /* Run diff. */
-    date_of_change = File_DateofChange(old_location);
-    snprintf(diff_cmd, 2048, "diff \"%s\" \"%s\" > \"%s/local/%s/diff.%d\" "
-             "2>/dev/null",
-             tmp_location, old_location,
-             DIFF_DIR_PATH, filename +1, date_of_change);
-    if(system(diff_cmd) != 256)
-    {
-        merror("%s: ERROR: Unable to run diff for %s",
-               ARGV0,  filename);
-        return(NULL);
+    snprintf(
+        diff_cmd,
+        2048,
+        "diff \"%s\" \"%s\" > \"%s\" 2> /dev/null",
+        new_tmp,
+        old_tmp,
+        diff_tmp
+    );
+
+
+
+    if(system(diff_cmd) != 256) {
+        merror("%s: ERROR: Unable to run diff for %s", ARGV0, filename);
+        goto cleanup;
+
     }
 
+    /* Success */
+    status = 0;
 
-    /* Generate alert. */
-    return(gen_diff_alert(filename, date_of_change));
+cleanup:
+    unlink(old_tmp);
+    unlink(new_tmp);
+    unlink(diff_tmp);
 
+    if (status == -1)
+        return (NULL);
 
-    return(NULL);
+    /* Generate alert. */
+    return (gen_diff_alert(filename, new_date_of_change));
 }