1 /* @(#) $Id: ./src/syscheckd/seechanges.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
16 #include "os_crypto/md5/md5_op.h"
20 extern magic_t magic_cookie;
22 int is_text(magic_t cookie, const void* buf, size_t len)
24 const char* magic = magic_buffer(cookie, buf, len);
28 const char* err = magic_error(cookie);
29 merror("%s: ERROR: magic_buffer: %s", ARGV0, err ? err : "unknown");
30 return(1); // TODO default to true?
34 if(strncmp(magic, "text/", 5) == 0) return(1);
41 /* Generate diffs alerts. */
42 char *gen_diff_alert(char *filename, int alert_diff_time)
47 char buf[OS_MAXSTR +1];
48 char diff_alert[OS_MAXSTR +1];
50 buf[OS_MAXSTR] = '\0';
51 diff_alert[OS_MAXSTR] = '\0';
53 snprintf(buf, OS_MAXSTR, "%s/local/%s/diff.%d",
54 DIFF_DIR_PATH, filename, alert_diff_time);
59 merror("%s: ERROR: Unable to generate diff alert.", ARGV0);
63 n = fread(buf, 1, 4096 -1, fp);
66 merror("%s: ERROR: Unable to generate diff alert (fread).", ARGV0);
72 /* We need to clear the last new line. */
74 tmp_str = strrchr(buf, '\n');
79 /* Weird diff with only one large line. */
91 /* Getting up to 20 line changes. */
95 while(tmp_str && (*tmp_str != '\0'))
97 tmp_str = strchr(tmp_str, '\n');
110 /* Creating alert. */
111 snprintf(diff_alert, 4096 -1, "%s%s",
118 return(strdup(diff_alert));
122 int seechanges_dupfile(char *old, char *new)
127 unsigned char buf[2048 +1];
131 fpr = fopen(old,"r");
132 fpw = fopen(new,"w");
139 n = fread(buf, 1, 2048, fpr);
141 if(is_text(magic_cookie, buf, n) == 0)
150 fwrite(buf, n, 1, fpw);
152 while((n = fread(buf, 1, 2048, fpr)) > 0);
163 int seechanges_createpath(char *filename)
170 os_strdup(filename, buffer);
172 tmpstr = strchr(buffer +1, '/');
175 merror("%s: ERROR: Invalid path name: '%s'", ARGV0, filename);
185 if(IsDir(newdir) != 0)
188 if(mkdir(newdir, 0770) == -1)
190 if(mkdir(newdir) == -1)
193 merror(MKDIR_ERROR, ARGV0, newdir);
205 tmpstr = strchr(tmpstr, '/');
219 /* Checks if the file has changed */
220 char *seechanges_addfile(char *filename)
222 time_t old_date_of_change;
223 time_t new_date_of_change;
225 char old_location[OS_MAXSTR +1];
226 char tmp_location[OS_MAXSTR +1];
227 char diff_location[OS_MAXSTR + 1];
228 char old_tmp[OS_MAXSTR + 1];
229 char new_tmp[OS_MAXSTR + 1];
230 char diff_tmp[OS_MAXSTR + 1];
232 char diff_cmd[OS_MAXSTR +1];
239 old_location[OS_MAXSTR] = '\0';
240 tmp_location[OS_MAXSTR] = '\0';
241 diff_location[OS_MAXSTR] = '\0';
242 old_tmp[OS_MAXSTR] = '\0';
243 new_tmp[OS_MAXSTR] = '\0';
244 diff_tmp[OS_MAXSTR] = '\0';
245 diff_cmd[OS_MAXSTR] = '\0';
246 md5sum_new[0] = '\0';
247 md5sum_old[0] = '\0';
260 /* If the file is not there, rename new location to last location. */
261 if(OS_MD5_File(old_location, md5sum_old) != 0)
263 seechanges_createpath(old_location);
264 if(seechanges_dupfile(filename, old_location) != 1)
266 merror(RENAME_ERROR, ARGV0, filename);
272 /* Get md5sum of the new file. */
273 if(OS_MD5_File(filename, md5sum_new) != 0)
275 //merror("%s: ERROR: Invalid internal state (missing '%s').",
281 /* If they match, keep the old file and remove the new. */
282 if(strcmp(md5sum_new, md5sum_old) == 0)
288 /* Saving the old file at timestamp and renaming new to last. */
289 old_date_of_change = File_DateofChange(old_location);
294 "%s/local/%s/state.%d",
297 (int)old_date_of_change
301 rename(old_location, tmp_location);
302 if(seechanges_dupfile(filename, old_location) != 1)
304 merror("%s: ERROR: Unable to create snapshot for %s",ARGV0, filename);
309 new_date_of_change = File_DateofChange(old_location);
311 /* Create file names */
315 "%s/%s/syscheck-changes-%s-%d",
319 (int)old_date_of_change
325 "%s/%s/syscheck-changes-%s-%d",
329 (int)new_date_of_change
335 "%s/%s/syscheck-changes-%s-%d-%s-%d",
339 (int)old_date_of_change,
341 (int)new_date_of_change
344 /* Create diff location */
348 "%s/local/%s/diff.%d",
351 (int)new_date_of_change
354 /* Create symlinks */
355 if (symlink(old_location, old_tmp) == -1) {
356 merror(LINK_ERROR, ARGV0, old_location, old_tmp, errno, strerror(errno));
360 if (symlink(tmp_location, new_tmp) == -1) {
361 merror(LINK_ERROR, ARGV0, tmp_location, new_tmp, errno, strerror(errno));
365 if (symlink(diff_location, diff_tmp) == -1) {
366 merror(LINK_ERROR, ARGV0, diff_location, diff_tmp, errno, strerror(errno));
376 "diff \"%s\" \"%s\" > \"%s\" 2> /dev/null",
384 if(system(diff_cmd) != 256) {
385 merror("%s: ERROR: Unable to run diff for %s", ARGV0, filename);
401 /* Generate alert. */
402 return (gen_diff_alert(filename, new_date_of_change));