-/* @(#) $Id: ./src/syscheckd/seechanges.c, 2011/09/08 dcid Exp $
- */
-
/* Copyright (C) 2009 Trend Micro Inc.
* All rights reserved.
*
* Foundation
*/
-
-
#include "shared.h"
#include "os_crypto/md5/md5_op.h"
+#include "syscheck.h"
+
+/* Prototypes */
+static char *gen_diff_alert(const char *filename, time_t alert_diff_time) __attribute__((nonnull));
+static int seechanges_dupfile(const char *old, const char *current) __attribute__((nonnull));
+static int seechanges_createpath(const char *filename) __attribute__((nonnull));
#ifdef USE_MAGIC
#include <magic.h>
+
+/* Global variables */
extern magic_t magic_cookie;
-int is_text(magic_t cookie, const void* buf, size_t len)
+
+int is_text(magic_t cookie, const void *buf, size_t len)
{
- const char* magic = magic_buffer(cookie, buf, len);
+ const char *magic = magic_buffer(cookie, buf, len);
- if(!magic)
- {
- const char* err = magic_error(cookie);
+ 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 (1); // TODO default to true?
+ } else {
+ if (strncmp(magic, "text/", 5) == 0) {
+ return (1);
+ }
}
- return(0);
+ return (0);
}
#endif
-/* Generate diffs alerts. */
-char *gen_diff_alert(char *filename, int alert_diff_time)
+/* Return TRUE if the file name match one of the ``nodiff`` entries.
+ Return FALSE otherwise */
+int is_nodiff(const char *filename){
+ if (syscheck.nodiff){
+ int i;
+ for (i = 0; syscheck.nodiff[i] != NULL; i++){
+ if (strncasecmp(syscheck.nodiff[i], filename,
+ strlen(syscheck.nodiff[i])) == 0) {
+ return (TRUE);
+ }
+ }
+ }
+ if (syscheck.nodiff_regex) {
+ int i;
+ for (i = 0; syscheck.nodiff_regex[i] != NULL; i++) {
+ if (OSMatch_Execute(filename, strlen(filename),
+ syscheck.nodiff_regex[i])) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+}
+
+/* Generate diffs alerts */
+static char *gen_diff_alert(const char *filename, time_t alert_diff_time)
{
- int n = 0;
+ size_t n = 0;
FILE *fp;
char *tmp_str;
- char buf[OS_MAXSTR +1];
- char diff_alert[OS_MAXSTR +1];
+ char buf[OS_MAXSTR + 1];
+ char diff_alert[OS_MAXSTR + 1];
buf[OS_MAXSTR] = '\0';
diff_alert[OS_MAXSTR] = '\0';
snprintf(buf, OS_MAXSTR, "%s/local/%s/diff.%d",
- DIFF_DIR_PATH, filename, alert_diff_time);
+ DIFF_DIR_PATH, filename, (int)alert_diff_time);
fp = fopen(buf, "r");
- if(!fp)
- {
+ if (!fp) {
merror("%s: ERROR: Unable to generate diff alert.", ARGV0);
- return(NULL);
+ return (NULL);
}
- n = fread(buf, 1, 4096 -1, fp);
- if(n <= 0)
- {
+ n = fread(buf, 1, 4096 - 1, fp);
+ if (n <= 0) {
merror("%s: ERROR: Unable to generate diff alert (fread).", ARGV0);
fclose(fp);
- return(NULL);
- }
- else if(n >= 4000)
- {
- /* We need to clear the last new line. */
+ return (NULL);
+ } else if (n >= 4000) {
+ /* Clear the last newline */
buf[n] = '\0';
tmp_str = strrchr(buf, '\n');
- if(tmp_str)
+ if (tmp_str) {
*tmp_str = '\0';
- else
- {
- /* Weird diff with only one large line. */
+ } else {
+ /* Weird diff with only one large line */
buf[256] = '\0';
}
- }
- else
- {
+ } else {
buf[n] = '\0';
}
n = 0;
-
- /* Getting up to 20 line changes. */
+ /* Get up to 20 line changes */
tmp_str = buf;
-
- while(tmp_str && (*tmp_str != '\0'))
- {
+ while (tmp_str && (*tmp_str != '\0')) {
tmp_str = strchr(tmp_str, '\n');
- if(!tmp_str)
+ if (!tmp_str) {
break;
- else if(n >= 19)
- {
+ } else if (n >= 19) {
*tmp_str = '\0';
break;
}
tmp_str++;
}
-
- /* Creating alert. */
- snprintf(diff_alert, 4096 -1, "%s%s",
- buf, n>=19?
- "\nMore changes..":
+ /* Create alert */
+ snprintf(diff_alert, 4096 - 1, "%s%s",
+ buf, n >= 19 ?
+ "\nMore changes.." :
"");
-
fclose(fp);
- return(strdup(diff_alert));
+ return (strdup(diff_alert));
}
-
-int seechanges_dupfile(char *old, char *new)
+static int seechanges_dupfile(const char *old, const char *current)
{
- int n;
+ size_t n;
FILE *fpr;
FILE *fpw;
- unsigned char buf[2048 +1];
+ unsigned char buf[2048 + 1];
buf[2048] = '\0';
- fpr = fopen(old,"r");
- fpw = fopen(new,"w");
+ fpr = fopen(old, "r");
+ if (!fpr) {
+ return (0);
+ }
- if(!fpr || !fpw)
- {
- return(0);
+ fpw = fopen(current, "w");
+ if (!fpw) {
+ fclose(fpr);
+ return (0);
}
n = fread(buf, 1, 2048, fpr);
- #ifdef USE_MAGIC
- if(is_text(magic_cookie, buf, n) == 0)
- {
+#ifdef USE_MAGIC
+ if (is_text(magic_cookie, buf, n) == 0) {
goto cleanup;
}
- #endif
+#endif
- do
- {
+ do {
buf[n] = '\0';
fwrite(buf, n, 1, fpw);
- }
- while((n = fread(buf, 1, 2048, fpr)) > 0);
+ } while ((n = fread(buf, 1, 2048, fpr)) > 0);
#ifdef USE_MAGIC
cleanup:
#endif
fclose(fpr);
fclose(fpw);
- return(1);
+ return (1);
}
-
-int seechanges_createpath(char *filename)
+static int seechanges_createpath(const char *filename)
{
char *buffer = NULL;
char *tmpstr = NULL;
char *newdir = NULL;
-
os_strdup(filename, buffer);
newdir = buffer;
- tmpstr = strchr(buffer +1, '/');
- if(!tmpstr)
- {
+ tmpstr = strchr(buffer + 1, '/');
+ if (!tmpstr) {
merror("%s: ERROR: Invalid path name: '%s'", ARGV0, filename);
free(buffer);
- return(0);
+ return (0);
}
*tmpstr = '\0';
tmpstr++;
-
- while(1)
- {
- if(IsDir(newdir) != 0)
- {
- #ifndef WIN32
- if(mkdir(newdir, 0770) == -1)
- #else
- if(mkdir(newdir) == -1)
- #endif
+ while (1) {
+ if (IsDir(newdir) != 0) {
+#ifndef WIN32
+ if (mkdir(newdir, 0770) == -1)
+#else
+ if (mkdir(newdir) == -1)
+#endif
{
- merror(MKDIR_ERROR, ARGV0, newdir);
+ merror(MKDIR_ERROR, ARGV0, newdir, errno, strerror(errno));
free(buffer);
- return(0);
+ return (0);
}
}
- if(*tmpstr == '\0')
- {
+ if (*tmpstr == '\0') {
break;
}
tmpstr[-1] = '/';
tmpstr = strchr(tmpstr, '/');
- if(!tmpstr)
- {
+ if (!tmpstr) {
break;
}
*tmpstr = '\0';
}
free(buffer);
- return(1);
+ return (1);
}
-
-/* Checks if the file has changed */
-char *seechanges_addfile(char *filename)
+/* Check if the file has changed */
+char *seechanges_addfile(const char *filename)
{
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 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];
-
+ 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';
md5sum_new[0] = '\0';
md5sum_old[0] = '\0';
-
snprintf(
old_location,
OS_MAXSTR,
DIFF_LAST_FILE
);
-
- /* If the file is not there, rename new location to last location. */
- if(OS_MD5_File(old_location, md5sum_old) != 0)
- {
+ /* If the file is not there, rename new location to last location */
+ if (OS_MD5_File(old_location, md5sum_old, OS_BINARY) != 0) {
seechanges_createpath(old_location);
- if(seechanges_dupfile(filename, old_location) != 1)
- {
- merror(RENAME_ERROR, ARGV0, filename);
+ if (seechanges_dupfile(filename, old_location) != 1) {
+ merror(RENAME_ERROR, ARGV0, filename, old_location, errno, strerror(errno));
}
- return(NULL);
+ return (NULL);
}
-
- /* Get md5sum of the new file. */
- if(OS_MD5_File(filename, md5sum_new) != 0)
- {
- //merror("%s: ERROR: Invalid internal state (missing '%s').",
- // ARGV0, filename);
- return(NULL);
+ /* Get md5sum of the new file */
+ if (OS_MD5_File(filename, md5sum_new, OS_BINARY) != 0) {
+ return (NULL);
}
-
- /* If they match, keep the old file and remove the new. */
- if(strcmp(md5sum_new, md5sum_old) == 0)
- {
- return(NULL);
+ /* If they match, keep the old file and remove the new */
+ if (strcmp(md5sum_new, md5sum_old) == 0) {
+ return (NULL);
}
+ /* Save the old file at timestamp and rename new to last */
+ 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
+ );
/* Saving the old file at timestamp and renaming new to last. */
old_date_of_change = File_DateofChange(old_location);
snprintf(
tmp_location,
- OS_MAXSTR,
+ sizeof(tmp_location),
"%s/local/%s/state.%d",
DIFF_DIR_PATH,
filename + 1,
);
- rename(old_location, tmp_location);
+ if((rename(old_location, tmp_location)) < 0) {
+ merror("%s: ERROR rename of %s failed: %s", ARGV0, old_location, strerror(errno));
+ }
if(seechanges_dupfile(filename, old_location) != 1)
{
merror("%s: ERROR: Unable to create snapshot for %s",ARGV0, filename);
return(NULL);
}
+ if (seechanges_dupfile(filename, old_location) != 1) {
+ merror("%s: ERROR: Unable to create snapshot for %s", ARGV0, filename);
+ return (NULL);
+ }
new_date_of_change = File_DateofChange(old_location);
md5sum_new,
(int)new_date_of_change
);
-
/* Create diff location */
snprintf(
diff_location,
goto cleanup;
}
+ if (is_nodiff((filename))) {
+ /* Dont leak sensible data with a diff hanging around */
+ FILE *fdiff;
+ char* nodiff_message = "<Diff truncated because nodiff option>";
+ fdiff = fopen(diff_location, "w");
+ if (!fdiff){
+ merror("%s: ERROR: Unable to open file for writing `%s`", ARGV0, diff_location);
+ goto cleanup;
+ }
+ fwrite(nodiff_message, strlen(nodiff_message) + 1, 1, fdiff);
+ fclose(fdiff);
+ /* Success */
+ status = 0;
+ } else {
+ /* OK, run diff */
+ 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 `%s`", ARGV0, diff_cmd);
+ goto cleanup;
+ }
-
- /* Run diff. */
- 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;
+ /* Success */
+ status = 0;
+ };
cleanup:
unlink(old_tmp);
if (status == -1)
return (NULL);
- /* Generate alert. */
+ /* Generate alert */
return (gen_diff_alert(filename, new_date_of_change));
}
-
-
-
-/* EOF */