1 /* @(#) $Id: run_realtime.c,v 1.12 2009/12/01 15:40:08 dcid Exp $ */
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 3) 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>
45 /** Global functions for all realtime options. **/
46 int c_read_file(char *file_name, char *oldsum, char *newsum);
49 /* Checking sum of the realtime file being monitored. */
50 int realtime_checksumfile(char *file_name)
52 char buf[MAX_LINE +2];
53 buf[MAX_LINE +1] = '\0';
56 fseek(syscheck.fp, 0, SEEK_SET);
57 while(fgets(buf, MAX_LINE, syscheck.fp) != NULL)
59 if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n'))
63 /* Removing the new line */
64 n_buf = strchr(buf,'\n');
71 /* First 6 characters are for internal use */
75 n_buf = strchr(n_buf, ' ');
80 /* Checking if name matches */
81 if(strcmp(n_buf, file_name) == 0)
88 /* If it returns < 0, we will already have alerted. */
89 if(c_read_file(file_name, buf, c_sum) < 0)
93 if(strcmp(c_sum, buf+6) != 0)
95 char alert_msg[912 +2];
97 /* Sending the new checksum to the analysis server */
98 alert_msg[912 +1] = '\0';
99 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
100 send_syscheck_msg(alert_msg);
113 /* Adding entry if not in there. */
114 fseek(syscheck.fp, 0, SEEK_END);
122 #include <sys/inotify.h>
125 #define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_TO|IN_DELETE|IN_MOVED_FROM
126 #define REALTIME_EVENT_SIZE (sizeof (struct inotify_event))
127 #define REALTIME_EVENT_BUFFER (2048 * (REALTIME_EVENT_SIZE + 16))
131 /* Starts real time monitoring using inotify. */
134 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
136 syscheck.realtime = calloc(1, sizeof(rtfim));
137 if(syscheck.realtime == NULL)
139 ErrorExit(MEM_ERROR, ARGV0);
141 syscheck.realtime->dirtb = (void *)OSHash_Create();
142 syscheck.realtime->fd = -1;
145 syscheck.realtime->fd = inotify_init();
146 if(syscheck.realtime->fd < 0)
148 merror("%s: ERROR: Unable to initialize inotify.", ARGV0);
158 /* Adds a directory to real time checking. */
159 int realtime_adddir(char *dir)
161 if(!syscheck.realtime)
167 /* Checking if it is ready to use. */
168 if(syscheck.realtime->fd < 0)
176 wd = inotify_add_watch(syscheck.realtime->fd,
178 REALTIME_MONITOR_FLAGS);
181 merror("%s: ERROR: Unable to add directory to real time "
182 "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno);
188 snprintf(wdchar, 32, "%d", wd);
190 /* Entry not present. */
191 if(!OSHash_Get(syscheck.realtime->dirtb, wdchar))
198 ErrorExit("%s: ERROR: Out of memory. Exiting.", ARGV0);
201 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), ndir);
202 debug1("%s: DEBUG: Directory added for real time monitoring: "
203 "'%s'.", ARGV0, ndir);
212 /* Process events in the real time queue. */
213 int realtime_process()
216 char buf[REALTIME_EVENT_BUFFER +1];
217 struct inotify_event *event;
219 buf[REALTIME_EVENT_BUFFER] = '\0';
222 len = read(syscheck.realtime->fd, buf, REALTIME_EVENT_BUFFER);
225 merror("%s: ERROR: Unable to read from real time buffer.", ARGV0);
231 event = (struct inotify_event *) &buf[i];
236 char final_name[MAX_LINE +1];
239 final_name[MAX_LINE] = '\0';
241 snprintf(wdchar, 32, "%d", event->wd);
243 snprintf(final_name, MAX_LINE, "%s/%s",
244 (char *)OSHash_Get(syscheck.realtime->dirtb, wdchar),
246 realtime_checksumfile(final_name);
249 i += REALTIME_EVENT_SIZE + event->len;
259 typedef struct _win32rtfim
268 int realtime_win32read(win32rtfim *rtlocald);
270 void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap)
277 char final_path[MAX_LINE +1];
279 win32rtfim *rtlocald;
281 PFILE_NOTIFY_INFORMATION pinfo;
282 TCHAR finalfile[MAX_PATH];
286 merror("%s: ERROR: real time call back called, but 0 bytes.", ARGV0);
290 if(dwerror != ERROR_SUCCESS)
292 merror("%s: ERROR: real time call back called, but error is set.",
298 /* Getting hash to parse the data. */
300 snprintf(wdchar, 32, "%d", (int)overlap->Offset);
301 rtlocald = OSHash_Get(syscheck.realtime->dirtb, wdchar);
304 merror("%s: ERROR: real time call back called, but hash is empty.",
313 pinfo = (PFILE_NOTIFY_INFORMATION) &rtlocald->buffer[offset];
314 offset += pinfo->NextEntryOffset;
316 lcount = WideCharToMultiByte(CP_ACP, 0, pinfo->FileName,
317 pinfo->FileNameLength / sizeof(WCHAR),
318 finalfile, MAX_PATH - 1, NULL, NULL);
319 finalfile[lcount] = TEXT('\0');
322 /* Change forward slashes to backslashes on finalfile. */
323 ptfile = strchr(finalfile, '\\');
329 ptfile = strchr(ptfile, '\\');
332 final_path[MAX_LINE] = '\0';
333 snprintf(final_path, MAX_LINE, "%s/%s", rtlocald->dir, finalfile);
336 /* Checking the change. */
337 realtime_checksumfile(final_path);
341 if(pinfo->Action == FILE_ACTION_ADDED)
342 else if(pinfo->Action == FILE_ACTION_REMOVED)
343 else if(pinfo->Action == FILE_ACTION_MODIFIED)
344 else if(pinfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
345 else if(pinfo->Action == FILE_ACTION_RENAMED_NEW_NAME)
349 }while(pinfo->NextEntryOffset != 0);
352 realtime_win32read(rtlocald);
362 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
364 os_calloc(1, sizeof(rtfim), syscheck.realtime);
365 syscheck.realtime->dirtb = (void *)OSHash_Create();
366 syscheck.realtime->fd = -1;
367 syscheck.realtime->evt = CreateEvent(NULL, TRUE, FALSE, NULL);
371 int realtime_win32read(win32rtfim *rtlocald)
375 rc = ReadDirectoryChangesW(rtlocald->h,
377 sizeof(rtlocald->buffer) / sizeof(TCHAR),
379 FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE,
385 merror("%s: ERROR: Unable to set directory for monitoring: %s",
386 ARGV0, rtlocald->dir);
393 int realtime_adddir(char *dir)
396 win32rtfim *rtlocald;
399 if(!syscheck.realtime)
405 /* Maximum limit for realtime on Windows. */
406 if(syscheck.realtime->fd > 256)
408 merror("%s: ERROR: Unable to add directory to real time "
409 "monitoring: '%s' - Maximum size permitted.", ARGV0, dir);
414 os_calloc(1, sizeof(win32rtfim), rtlocald);
417 rtlocald->h = CreateFile(dir,
419 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
422 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
426 if(rtlocald->h == INVALID_HANDLE_VALUE ||
431 merror("%s: ERROR: Unable to add directory to real time "
432 "monitoring: '%s'.", ARGV0, dir);
436 rtlocald->overlap.Offset = ++syscheck.realtime->fd;
440 /* Setting key for hash. */
442 snprintf(wdchar, 32, "%d", (int)rtlocald->overlap.Offset);
445 if(OSHash_Get(syscheck.realtime->dirtb, wdchar))
447 merror("%s: ERROR: Entry already in the real time hash: %s",
449 CloseHandle(rtlocald->overlap.hEvent);
456 /* Adding final elements to the hash. */
457 os_strdup(dir, rtlocald->dir);
459 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), rtlocald);
462 /* Adding directory to be monitored. */
463 realtime_win32read(rtlocald);
476 verbose("%s: ERROR: Unable to initalize real time file monitoring.", ARGV0);
480 int realtime_adddir(char *dir)
485 int realtime_process()