-/* @(#) $Id$ */
+/* @(#) $Id: ./src/syscheckd/seechanges.c, 2011/09/08 dcid Exp $
+ */
/* Copyright (C) 2009 Trend Micro Inc.
* All rights reserved.
#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)
snprintf(buf, OS_MAXSTR, "%s/local/%s/diff.%d",
DIFF_DIR_PATH, filename, alert_diff_time);
-
+
fp = fopen(buf, "r");
if(!fp)
{
else
{
/* Weird diff with only one large line. */
- buf[256] = '\0';
+ buf[256] = '\0';
}
}
else
/* Getting up to 20 line changes. */
tmp_str = buf;
-
+
while(tmp_str && (*tmp_str != '\0'))
{
tmp_str = strchr(tmp_str, '\n');
if(!tmp_str)
- break;
+ break;
else if(n >= 19)
{
- *tmp_str = '\0';
+ *tmp_str = '\0';
break;
}
n++;
- tmp_str++;
+ tmp_str++;
}
buf, n>=19?
"\nMore changes..":
"");
-
-
+
+
fclose(fp);
return(strdup(diff_alert));
}
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);
char *tmpstr = NULL;
char *newdir = NULL;
-
+
os_strdup(filename, buffer);
newdir = buffer;
tmpstr = strchr(buffer +1, '/');
{
#ifndef WIN32
if(mkdir(newdir, 0770) == -1)
- #else
+ #else
if(mkdir(newdir) == -1)
- #endif
+ #endif
{
merror(MKDIR_ERROR, ARGV0, newdir);
free(buffer);
/* 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. */
if(OS_MD5_File(filename, md5sum_new) != 0)
{
//merror("%s: ERROR: Invalid internal state (missing '%s').",
- // ARGV0, filename);
+ // ARGV0, filename);
return(NULL);
}
/* 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)
{
}
+ 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));
}