3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
16 #include <sys/types.h>
27 #define sleep(x) Sleep(x * 1000)
28 #define os_calloc(x,y,z) (z = calloc(x,y))?(void)1:ErrorExit(MEM_ERROR, ARGV0)
29 #define os_strdup(x,y) (y = strdup(x))?(void)1:ErrorExit(MEM_ERROR, ARGV0)
36 #include "error_messages/error_messages.h"
40 #include <sys/inotify.h>
41 #define OS_SIZE_6144 6144
42 #define OS_MAXSTR OS_SIZE_6144 /* Size for logs, sockets, etc */
49 /** Global functions for all realtime options. **/
50 int c_read_file(char *file_name, char *oldsum, char *newsum);
53 /* Checking sum of the realtime file being monitored. */
54 int realtime_checksumfile(char *file_name)
58 buf = OSHash_Get(syscheck.fp, file_name);
67 /* If it returns < 0, we will already have alerted. */
68 if(c_read_file(file_name, buf, c_sum) < 0)
74 if(strcmp(c_sum, buf+6) != 0)
76 char *fullalert = NULL;
77 char alert_msg[OS_MAXSTR +1];
78 alert_msg[OS_MAXSTR] = '\0';
79 if(buf[5] == 's' || buf[5] == 'n')
81 fullalert = seechanges_addfile(file_name);
84 snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
90 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
95 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
97 send_syscheck_msg(alert_msg);
113 #include <sys/inotify.h>
116 #define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_TO|IN_DELETE|IN_MOVED_FROM
117 #define REALTIME_EVENT_SIZE (sizeof (struct inotify_event))
118 #define REALTIME_EVENT_BUFFER (2048 * (REALTIME_EVENT_SIZE + 16))
122 /* Starts real time monitoring using inotify. */
125 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
127 syscheck.realtime = calloc(1, sizeof(rtfim));
128 if(syscheck.realtime == NULL)
130 ErrorExit(MEM_ERROR, ARGV0);
132 syscheck.realtime->dirtb = (void *)OSHash_Create();
133 syscheck.realtime->fd = -1;
136 syscheck.realtime->fd = inotify_init();
137 if(syscheck.realtime->fd < 0)
139 merror("%s: ERROR: Unable to initialize inotify.", ARGV0);
149 /* Adds a directory to real time checking. */
150 int realtime_adddir(char *dir)
152 if(!syscheck.realtime)
158 /* Checking if it is ready to use. */
159 if(syscheck.realtime->fd < 0)
167 wd = inotify_add_watch(syscheck.realtime->fd,
169 REALTIME_MONITOR_FLAGS);
172 merror("%s: ERROR: Unable to add directory to real time "
173 "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno);
179 snprintf(wdchar, 32, "%d", wd);
181 /* Entry not present. */
182 if(!OSHash_Get(syscheck.realtime->dirtb, wdchar))
189 ErrorExit("%s: ERROR: Out of memory. Exiting.", ARGV0);
192 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), ndir);
193 debug1("%s: DEBUG: Directory added for real time monitoring: "
194 "'%s'.", ARGV0, ndir);
203 /* Process events in the real time queue. */
204 int realtime_process()
207 char buf[REALTIME_EVENT_BUFFER +1];
208 struct inotify_event *event;
210 buf[REALTIME_EVENT_BUFFER] = '\0';
213 len = read(syscheck.realtime->fd, buf, REALTIME_EVENT_BUFFER);
216 merror("%s: ERROR: Unable to read from real time buffer.", ARGV0);
222 event = (struct inotify_event *) &buf[i];
227 char final_name[MAX_LINE +1];
230 final_name[MAX_LINE] = '\0';
232 snprintf(wdchar, 32, "%d", event->wd);
234 snprintf(final_name, MAX_LINE, "%s/%s",
235 (char *)OSHash_Get(syscheck.realtime->dirtb, wdchar),
237 realtime_checksumfile(final_name);
240 i += REALTIME_EVENT_SIZE + event->len;
250 typedef struct _win32rtfim
259 int realtime_win32read(win32rtfim *rtlocald);
261 void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap)
268 char final_path[MAX_LINE +1];
270 win32rtfim *rtlocald;
272 PFILE_NOTIFY_INFORMATION pinfo;
273 TCHAR finalfile[MAX_PATH];
277 merror("%s: ERROR: real time call back called, but 0 bytes.", ARGV0);
281 if(dwerror != ERROR_SUCCESS)
283 merror("%s: ERROR: real time call back called, but error is set.",
289 /* Getting hash to parse the data. */
291 snprintf(wdchar, 32, "%d", (int)overlap->Offset);
292 rtlocald = OSHash_Get(syscheck.realtime->dirtb, wdchar);
295 merror("%s: ERROR: real time call back called, but hash is empty.",
304 pinfo = (PFILE_NOTIFY_INFORMATION) &rtlocald->buffer[offset];
305 offset += pinfo->NextEntryOffset;
307 lcount = WideCharToMultiByte(CP_ACP, 0, pinfo->FileName,
308 pinfo->FileNameLength / sizeof(WCHAR),
309 finalfile, MAX_PATH - 1, NULL, NULL);
310 finalfile[lcount] = TEXT('\0');
313 /* Change forward slashes to backslashes on finalfile. */
314 ptfile = strchr(finalfile, '\\');
320 ptfile = strchr(ptfile, '\\');
323 final_path[MAX_LINE] = '\0';
324 snprintf(final_path, MAX_LINE, "%s/%s", rtlocald->dir, finalfile);
327 /* Checking the change. */
328 realtime_checksumfile(final_path);
332 if(pinfo->Action == FILE_ACTION_ADDED)
333 else if(pinfo->Action == FILE_ACTION_REMOVED)
334 else if(pinfo->Action == FILE_ACTION_MODIFIED)
335 else if(pinfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
336 else if(pinfo->Action == FILE_ACTION_RENAMED_NEW_NAME)
340 }while(pinfo->NextEntryOffset != 0);
343 realtime_win32read(rtlocald);
353 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
355 os_calloc(1, sizeof(rtfim), syscheck.realtime);
356 syscheck.realtime->dirtb = (void *)OSHash_Create();
357 syscheck.realtime->fd = -1;
358 syscheck.realtime->evt = CreateEvent(NULL, TRUE, FALSE, NULL);
362 int realtime_win32read(win32rtfim *rtlocald)
366 rc = ReadDirectoryChangesW(rtlocald->h,
368 sizeof(rtlocald->buffer) / sizeof(TCHAR),
370 FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE,
376 merror("%s: ERROR: Unable to set directory for monitoring: %s",
377 ARGV0, rtlocald->dir);
384 int realtime_adddir(char *dir)
387 win32rtfim *rtlocald;
390 if(!syscheck.realtime)
396 /* Maximum limit for realtime on Windows. */
397 if(syscheck.realtime->fd > 256)
399 merror("%s: ERROR: Unable to add directory to real time "
400 "monitoring: '%s' - Maximum size permitted.", ARGV0, dir);
405 os_calloc(1, sizeof(win32rtfim), rtlocald);
408 rtlocald->h = CreateFile(dir,
410 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
413 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
417 if(rtlocald->h == INVALID_HANDLE_VALUE ||
422 merror("%s: ERROR: Unable to add directory to real time "
423 "monitoring: '%s'.", ARGV0, dir);
427 rtlocald->overlap.Offset = ++syscheck.realtime->fd;
431 /* Setting key for hash. */
433 snprintf(wdchar, 32, "%d", (int)rtlocald->overlap.Offset);
436 if(OSHash_Get(syscheck.realtime->dirtb, wdchar))
438 merror("%s: ERROR: Entry already in the real time hash: %s",
440 CloseHandle(rtlocald->overlap.hEvent);
447 /* Adding final elements to the hash. */
448 os_strdup(dir, rtlocald->dir);
450 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), rtlocald);
453 /* Adding directory to be monitored. */
454 realtime_win32read(rtlocald);
467 verbose("%s: ERROR: Unable to initalize real time file monitoring.", ARGV0);
471 int realtime_adddir(char *dir)
476 int realtime_process()