-/* @(#) $Id$ */
-
/* Copyright (C) 2009 Trend Micro Inc.
* All right reserved.
*
* Foundation
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
-
#ifdef WIN32
-#include <windows.h>
-#include <winsock.h>
-#include <io.h>
-
#define sleep(x) Sleep(x * 1000)
-#define os_calloc(x,y,z) (z = calloc(x,y))?(void)1:ErrorExit(MEM_ERROR, ARGV0)
-#define os_strdup(x,y) (y = strdup(x))?(void)1:ErrorExit(MEM_ERROR, ARGV0)
#endif
-
-#include "hash_op.h"
-#include "debug_op.h"
-#include "syscheck.h"
-#include "error_messages/error_messages.h"
-
-
-#ifdef USEINOTIFY
+#ifdef INOTIFY_ENABLED
#include <sys/inotify.h>
#define OS_SIZE_6144 6144
#define OS_MAXSTR OS_SIZE_6144 /* Size for logs, sockets, etc */
#include "shared.h"
#endif
+#include "fs_op.h"
+#include "hash_op.h"
+#include "debug_op.h"
+#include "syscheck.h"
+#include "error_messages/error_messages.h"
-
-/** Global functions for all realtime options. **/
-int c_read_file(char *file_name, char *oldsum, char *newsum);
+/* Prototypes */
+int realtime_checksumfile(const char *file_name) __attribute__((nonnull));
-/* Checking sum of the realtime file being monitored. */
-int realtime_checksumfile(char *file_name)
+/* Checksum of the realtime file being monitored */
+int realtime_checksumfile(const char *file_name)
{
char *buf;
- buf = OSHash_Get(syscheck.fp, file_name);
- if(buf != NULL)
- {
- char c_sum[256 +2];
+ buf = (char *) OSHash_Get(syscheck.fp, file_name);
+ if (buf != NULL) {
+ char c_sum[256 + 2];
c_sum[0] = '\0';
c_sum[255] = '\0';
+ /* If it returns < 0, we have already alerted */
+ if (c_read_file(file_name, buf, c_sum) < 0) {
+ return (0);
+ }
+
+ if (strcmp(c_sum, buf + 6) != 0) {
+ char alert_msg[OS_MAXSTR + 1];
- /* If it returns < 0, we will already have alerted. */
- if(c_read_file(file_name, buf, c_sum) < 0)
- {
- return(0);
- }
+ alert_msg[OS_MAXSTR] = '\0';
+ #ifdef WIN32
+ snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
+ #else
+ char *fullalert = NULL;
- if(strcmp(c_sum, buf+6) != 0)
- {
- char *fullalert = NULL;
- char alert_msg[OS_MAXSTR +1];
- alert_msg[OS_MAXSTR] = '\0';
- if(buf[5] == 's' || buf[5] == 'n')
- {
- fullalert = seechanges_addfile(file_name);
- if(fullalert)
- {
+ if (buf[5] == 's' || buf[5] == 'n') {
+ fullalert = seechanges_addfile(file_name);
+ if (fullalert) {
snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
free(fullalert);
fullalert = NULL;
- }
- else
- {
- snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
- }
- }
- else
- {
- snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
- }
- send_syscheck_msg(alert_msg);
-
- return(1);
- }
-
- return(0);
-
- }
+ } else {
+ snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
+ }
+ } else {
+ snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
+ }
+ #endif
+ send_syscheck_msg(alert_msg);
- return(0);
-}
+ return (1);
+ }
+ return (0);
+ } else {
+ /* New file */
+ char *c;
+ int i;
+ buf = strdup(file_name);
+
+ /* Find container directory */
+
+ while (c = strrchr(buf, '/'), c && c != buf) {
+ *c = '\0';
+
+ for (i = 0; syscheck.dir[i]; i++) {
+ if (strcmp(syscheck.dir[i], buf) == 0) {
+ debug1("%s: DEBUG: Scanning new file '%s' with options for directory '%s'.", ARGV0, file_name, buf);
+ read_dir(file_name, syscheck.opts[i], syscheck.filerestrict[i]);
+ break;
+ }
+ }
+ if (syscheck.dir[i]) {
+ break;
+ }
+ }
+ free(buf);
+ }
+ return (0);
+}
-#ifdef USEINOTIFY
+#ifdef INOTIFY_ENABLED
#include <sys/inotify.h>
-
-#define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_TO|IN_DELETE|IN_MOVED_FROM
+#define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_FROM|IN_MOVED_TO|IN_CREATE|IN_DELETE|IN_DELETE_SELF
#define REALTIME_EVENT_SIZE (sizeof (struct inotify_event))
#define REALTIME_EVENT_BUFFER (2048 * (REALTIME_EVENT_SIZE + 16))
-
-
-/* Starts real time monitoring using inotify. */
+/* Start real time monitoring using inotify */
int realtime_start()
{
verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
- syscheck.realtime = calloc(1, sizeof(rtfim));
- if(syscheck.realtime == NULL)
- {
- ErrorExit(MEM_ERROR, ARGV0);
+ syscheck.realtime = (rtfim *) calloc(1, sizeof(rtfim));
+ if (syscheck.realtime == NULL) {
+ ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
}
- syscheck.realtime->dirtb = (void *)OSHash_Create();
+ syscheck.realtime->dirtb = OSHash_Create();
syscheck.realtime->fd = -1;
- #ifdef USEINOTIFY
+#ifdef INOTIFY_ENABLED
syscheck.realtime->fd = inotify_init();
- if(syscheck.realtime->fd < 0)
- {
+ if (syscheck.realtime->fd < 0) {
merror("%s: ERROR: Unable to initialize inotify.", ARGV0);
- return(-1);
+ return (-1);
}
- #endif
+#endif
- return(1);
+ return (1);
}
-
-
-/* Adds a directory to real time checking. */
-int realtime_adddir(char *dir)
+/* Add a directory to real time checking */
+int realtime_adddir(const char *dir)
{
- if(!syscheck.realtime)
- {
+ if (!syscheck.realtime) {
realtime_start();
}
-
- /* Checking if it is ready to use. */
- if(syscheck.realtime->fd < 0)
- {
- return(-1);
- }
- else
- {
+ /* Check if it is ready to use */
+ if (syscheck.realtime->fd < 0) {
+ return (-1);
+ } else {
int wd = 0;
+ if(syscheck.skip_nfs) {
+ short is_nfs = IsNFS(dir);
+ if( is_nfs == 1 ) {
+ merror("%s: ERROR: %s NFS Directories do not support iNotify.", ARGV0, dir);
+ return(-1);
+ }
+ else {
+ debug2("%s: DEBUG: syscheck.skip_nfs=%d, %s::is_nfs=%d", ARGV0, syscheck.skip_nfs, dir, is_nfs);
+ }
+ }
+
wd = inotify_add_watch(syscheck.realtime->fd,
dir,
- REALTIME_MONITOR_FLAGS);
- if(wd < 0)
- {
- merror("%s: ERROR: Unable to add directory to real time "
- "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno);
- }
- else
- {
- char wdchar[32 +1];
+ REALTIME_MONITOR_FLAGS);
+ if (wd < 0) {
+ merror("%s: ERROR: Unable to add directory to real time "
+ "monitoring: '%s'. %d %s", ARGV0, dir, wd, strerror(errno));
+ } else {
+ char wdchar[32 + 1];
wdchar[32] = '\0';
snprintf(wdchar, 32, "%d", wd);
- /* Entry not present. */
- if(!OSHash_Get(syscheck.realtime->dirtb, wdchar))
- {
+ /* Entry not present */
+ if (!OSHash_Get(syscheck.realtime->dirtb, wdchar)) {
char *ndir;
ndir = strdup(dir);
- if(ndir == NULL)
- {
+ if (ndir == NULL) {
ErrorExit("%s: ERROR: Out of memory. Exiting.", ARGV0);
}
- OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), ndir);
+ OSHash_Add(syscheck.realtime->dirtb, wdchar, ndir);
debug1("%s: DEBUG: Directory added for real time monitoring: "
"'%s'.", ARGV0, ndir);
}
}
}
- return(1);
+ return (1);
}
-
-/* Process events in the real time queue. */
+/* Process events in the real time queue */
int realtime_process()
{
- int len, i = 0;
- char buf[REALTIME_EVENT_BUFFER +1];
+ ssize_t len;
+ size_t i = 0;
+ char buf[REALTIME_EVENT_BUFFER + 1];
struct inotify_event *event;
buf[REALTIME_EVENT_BUFFER] = '\0';
-
len = read(syscheck.realtime->fd, buf, REALTIME_EVENT_BUFFER);
- if (len < 0)
- {
+ if (len < 0) {
merror("%s: ERROR: Unable to read from real time buffer.", ARGV0);
- }
- else if (len > 0)
- {
- while (i < len)
- {
- event = (struct inotify_event *) &buf[i];
-
- if(event->len)
- {
- char wdchar[32 +1];
- char final_name[MAX_LINE +1];
+ } else if (len > 0) {
+ buf[len] = '\0';
+ while (i < (size_t) len) {
+ event = (struct inotify_event *) (void *) &buf[i];
+
+ if (event->len) {
+ char wdchar[32 + 1];
+ char final_name[MAX_LINE + 1];
wdchar[32] = '\0';
final_name[MAX_LINE] = '\0';
snprintf(wdchar, 32, "%d", event->wd);
- snprintf(final_name, MAX_LINE, "%s/%s",
+ snprintf(final_name, MAX_LINE, "%s/%s",
(char *)OSHash_Get(syscheck.realtime->dirtb, wdchar),
event->name);
+ /* Need a sleep here to avoid triggering on vim edits
+ * (and finding the file removed)
+ */
+ sleep(1);
+
realtime_checksumfile(final_name);
}
}
}
- return(0);
+ return (0);
}
-
-
-#elif WIN32
-typedef struct _win32rtfim
-{
+#elif defined(WIN32)
+typedef struct _win32rtfim {
HANDLE h;
OVERLAPPED overlap;
char *dir;
- TCHAR buffer[12288];
-}win32rtfim;
+ TCHAR buffer[1228800];
+} win32rtfim;
int realtime_win32read(win32rtfim *rtlocald);
{
int lcount;
size_t offset = 0;
-
char *ptfile;
- char wdchar[32 +1];
- char final_path[MAX_LINE +1];
-
+ char wdchar[32 + 1];
+ char final_path[MAX_LINE + 1];
win32rtfim *rtlocald;
-
PFILE_NOTIFY_INFORMATION pinfo;
TCHAR finalfile[MAX_PATH];
- if(dwBytes == 0)
- {
+ if (dwBytes == 0) {
merror("%s: ERROR: real time call back called, but 0 bytes.", ARGV0);
+ rtlocald = OSHash_Get(syscheck.realtime->dirtb, "0");
+ if(rtlocald)
+ realtime_win32read(rtlocald);
+
return;
}
- if(dwerror != ERROR_SUCCESS)
- {
- merror("%s: ERROR: real time call back called, but error is set.",
+ if (dwerror != ERROR_SUCCESS) {
+ merror("%s: ERROR: real time call back called, but error is set.",
ARGV0);
return;
}
-
- /* Getting hash to parse the data. */
+ /* Get hash to parse the data */
wdchar[32] = '\0';
snprintf(wdchar, 32, "%d", (int)overlap->Offset);
rtlocald = OSHash_Get(syscheck.realtime->dirtb, wdchar);
- if(rtlocald == NULL)
- {
- merror("%s: ERROR: real time call back called, but hash is empty.",
+ if (rtlocald == NULL) {
+ merror("%s: ERROR: real time call back called, but hash is empty.",
ARGV0);
return;
}
-
-
- do
- {
+ do {
pinfo = (PFILE_NOTIFY_INFORMATION) &rtlocald->buffer[offset];
offset += pinfo->NextEntryOffset;
finalfile, MAX_PATH - 1, NULL, NULL);
finalfile[lcount] = TEXT('\0');
-
- /* Change forward slashes to backslashes on finalfile. */
+ /* Change forward slashes to backslashes on finalfile */
ptfile = strchr(finalfile, '\\');
- while(ptfile)
- {
+ while (ptfile) {
*ptfile = '/';
ptfile++;
final_path[MAX_LINE] = '\0';
snprintf(final_path, MAX_LINE, "%s/%s", rtlocald->dir, finalfile);
-
- /* Checking the change. */
+ /* Check the change */
realtime_checksumfile(final_path);
-
-
- /*
- if(pinfo->Action == FILE_ACTION_ADDED)
- else if(pinfo->Action == FILE_ACTION_REMOVED)
- else if(pinfo->Action == FILE_ACTION_MODIFIED)
- else if(pinfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
- else if(pinfo->Action == FILE_ACTION_RENAMED_NEW_NAME)
- else
- */
-
- }while(pinfo->NextEntryOffset != 0);
-
+ } while (pinfo->NextEntryOffset != 0);
realtime_win32read(rtlocald);
-
return;
}
-
-
int realtime_start()
{
verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
syscheck.realtime->dirtb = (void *)OSHash_Create();
syscheck.realtime->fd = -1;
syscheck.realtime->evt = CreateEvent(NULL, TRUE, FALSE, NULL);
- return(0);
+
+ return (0);
}
int realtime_win32read(win32rtfim *rtlocald)
rtlocald->buffer,
sizeof(rtlocald->buffer) / sizeof(TCHAR),
TRUE,
- FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE,
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SECURITY,
0,
- &rtlocald->overlap,
+ &rtlocald->overlap,
RTCallBack);
- if(rc == 0)
- {
- merror("%s: ERROR: Unable to set directory for monitoring: %s",
+ if (rc == 0) {
+ merror("%s: ERROR: Unable to set directory for monitoring: %s",
ARGV0, rtlocald->dir);
sleep(2);
}
- return(0);
+ return (0);
}
-int realtime_adddir(char *dir)
+int realtime_adddir(const char *dir)
{
- char wdchar[32 +1];
+ char wdchar[32 + 1];
win32rtfim *rtlocald;
-
- if(!syscheck.realtime)
- {
+ if (!syscheck.realtime) {
realtime_start();
}
-
- /* Maximum limit for realtime on Windows. */
- if(syscheck.realtime->fd > 256)
- {
+ /* Maximum limit for realtime on Windows */
+ if (syscheck.realtime->fd > 256) {
merror("%s: ERROR: Unable to add directory to real time "
"monitoring: '%s' - Maximum size permitted.", ARGV0, dir);
- return(0);
+ return (0);
}
-
os_calloc(1, sizeof(win32rtfim), rtlocald);
-
rtlocald->h = CreateFile(dir,
FILE_LIST_DIRECTORY,
- FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
- if(rtlocald->h == INVALID_HANDLE_VALUE ||
- rtlocald->h == NULL)
- {
+ if (rtlocald->h == INVALID_HANDLE_VALUE ||
+ rtlocald->h == NULL) {
free(rtlocald);
rtlocald = NULL;
merror("%s: ERROR: Unable to add directory to real time "
"monitoring: '%s'.", ARGV0, dir);
- return(0);
+ return (0);
}
rtlocald->overlap.Offset = ++syscheck.realtime->fd;
-
-
- /* Setting key for hash. */
+ /* Set key for hash */
wdchar[32] = '\0';
snprintf(wdchar, 32, "%d", (int)rtlocald->overlap.Offset);
-
- if(OSHash_Get(syscheck.realtime->dirtb, wdchar))
- {
- merror("%s: ERROR: Entry already in the real time hash: %s",
+ if (OSHash_Get(syscheck.realtime->dirtb, wdchar)) {
+ merror("%s: ERROR: Entry already in the real time hash: %s",
ARGV0, wdchar);
CloseHandle(rtlocald->overlap.hEvent);
free(rtlocald);
rtlocald = NULL;
- return(0);
+ return (0);
}
-
- /* Adding final elements to the hash. */
+ /* Add final elements to the hash */
os_strdup(dir, rtlocald->dir);
-
OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), rtlocald);
-
- /* Adding directory to be monitored. */
+ /* Add directory to be monitored */
realtime_win32read(rtlocald);
-
- return(1);
+ return (1);
}
+#else /* !WIN32 */
-
-
-
-#else
int realtime_start()
{
- verbose("%s: ERROR: Unable to initalize real time file monitoring.", ARGV0);
- return(0);
+ verbose("%s: ERROR: Unable to initialize real time file monitoring.", ARGV0);
+
+ return (0);
}
-int realtime_adddir(char *dir)
+int realtime_adddir(__attribute__((unused)) const char *dir)
{
- return(0);
+ return (0);
}
int realtime_process()
{
- return(0);
+ return (0);
}
-#endif
-/* EOF */
+#endif /* WIN32 */
+