X-Git-Url: http://ftp.carnet.hr/pub/carnet-debian/scm?a=blobdiff_plain;f=src%2Fsyscheckd%2Fseechanges.c;h=7bf2ee1920f78c719a7431c064474b07dacf6fd8;hb=927951d1c1ad45ba9e7325f07d996154a91c911b;hp=39ee33fb21cbf7d845020f6b36d4592d818da02a;hpb=301048b51990573e58a30dc4a5bb4ec285cad554;p=ossec-hids.git diff --git a/src/syscheckd/seechanges.c b/src/syscheckd/seechanges.c index 39ee33f..7bf2ee1 100755 --- a/src/syscheckd/seechanges.c +++ b/src/syscheckd/seechanges.c @@ -1,4 +1,5 @@ -/* @(#) $Id$ */ +/* @(#) $Id: ./src/syscheckd/seechanges.c, 2011/09/08 dcid Exp $ + */ /* Copyright (C) 2009 Trend Micro Inc. * All rights reserved. @@ -14,7 +15,28 @@ #include "shared.h" #include "os_crypto/md5/md5_op.h" +#ifdef USE_MAGIC +#include +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) @@ -30,7 +52,7 @@ 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) { @@ -55,7 +77,7 @@ char *gen_diff_alert(char *filename, int alert_diff_time) else { /* Weird diff with only one large line. */ - buf[256] = '\0'; + buf[256] = '\0'; } } else @@ -69,19 +91,19 @@ char *gen_diff_alert(char *filename, int alert_diff_time) /* 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++; } @@ -90,8 +112,8 @@ char *gen_diff_alert(char *filename, int alert_diff_time) buf, n>=19? "\nMore changes..": ""); - - + + fclose(fp); return(strdup(diff_alert)); } @@ -114,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); @@ -133,7 +166,7 @@ int seechanges_createpath(char *filename) char *tmpstr = NULL; char *newdir = NULL; - + os_strdup(filename, buffer); newdir = buffer; tmpstr = strchr(buffer +1, '/'); @@ -153,9 +186,9 @@ int seechanges_createpath(char *filename) { #ifndef WIN32 if(mkdir(newdir, 0770) == -1) - #else + #else if(mkdir(newdir) == -1) - #endif + #endif { merror(MKDIR_ERROR, ARGV0, newdir); free(buffer); @@ -186,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. */ @@ -221,7 +273,7 @@ char *seechanges_addfile(char *filename) if(OS_MD5_File(filename, md5sum_new) != 0) { //merror("%s: ERROR: Invalid internal state (missing '%s').", - // ARGV0, filename); + // ARGV0, filename); return(NULL); } @@ -234,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) { @@ -245,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)); }