1 /* @(#) $Id: ./src/syscheckd/run_realtime.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
17 #include <sys/types.h>
28 #define sleep(x) Sleep(x * 1000)
29 #define os_calloc(x,y,z) (z = calloc(x,y))?(void)1:ErrorExit(MEM_ERROR, ARGV0)
30 #define os_strdup(x,y) (y = strdup(x))?(void)1:ErrorExit(MEM_ERROR, ARGV0)
37 #include "error_messages/error_messages.h"
41 #include <sys/inotify.h>
42 #define OS_SIZE_6144 6144
43 #define OS_MAXSTR OS_SIZE_6144 /* Size for logs, sockets, etc */
50 /** Global functions for all realtime options. **/
51 int c_read_file(char *file_name, char *oldsum, char *newsum);
54 /* Checking sum of the realtime file being monitored. */
55 int realtime_checksumfile(char *file_name)
59 buf = OSHash_Get(syscheck.fp, file_name);
68 /* If it returns < 0, we will already have alerted. */
69 if(c_read_file(file_name, buf, c_sum) < 0)
75 if(strcmp(c_sum, buf+6) != 0)
77 char *fullalert = NULL;
78 char alert_msg[OS_MAXSTR +1];
79 alert_msg[OS_MAXSTR] = '\0';
80 if(buf[5] == 's' || buf[5] == 'n')
82 fullalert = seechanges_addfile(file_name);
85 snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
91 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
96 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
98 send_syscheck_msg(alert_msg);
114 #include <sys/inotify.h>
117 #define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_FROM|IN_MOVED_TO|IN_CREATE|IN_DELETE|IN_DELETE_SELF
118 #define REALTIME_EVENT_SIZE (sizeof (struct inotify_event))
119 #define REALTIME_EVENT_BUFFER (2048 * (REALTIME_EVENT_SIZE + 16))
123 /* Starts real time monitoring using inotify. */
126 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
128 syscheck.realtime = calloc(1, sizeof(rtfim));
129 if(syscheck.realtime == NULL)
131 ErrorExit(MEM_ERROR, ARGV0);
133 syscheck.realtime->dirtb = (void *)OSHash_Create();
134 syscheck.realtime->fd = -1;
137 syscheck.realtime->fd = inotify_init();
138 if(syscheck.realtime->fd < 0)
140 merror("%s: ERROR: Unable to initialize inotify.", ARGV0);
150 /* Adds a directory to real time checking. */
151 int realtime_adddir(char *dir)
153 if(!syscheck.realtime)
159 /* Checking if it is ready to use. */
160 if(syscheck.realtime->fd < 0)
168 wd = inotify_add_watch(syscheck.realtime->fd,
170 REALTIME_MONITOR_FLAGS);
173 merror("%s: ERROR: Unable to add directory to real time "
174 "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno);
180 snprintf(wdchar, 32, "%d", wd);
182 /* Entry not present. */
183 if(!OSHash_Get(syscheck.realtime->dirtb, wdchar))
190 ErrorExit("%s: ERROR: Out of memory. Exiting.", ARGV0);
193 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), ndir);
194 debug1("%s: DEBUG: Directory added for real time monitoring: "
195 "'%s'.", ARGV0, ndir);
204 /* Process events in the real time queue. */
205 int realtime_process()
208 char buf[REALTIME_EVENT_BUFFER +1];
209 struct inotify_event *event;
211 buf[REALTIME_EVENT_BUFFER] = '\0';
214 len = read(syscheck.realtime->fd, buf, REALTIME_EVENT_BUFFER);
217 merror("%s: ERROR: Unable to read from real time buffer.", ARGV0);
223 event = (struct inotify_event *) &buf[i];
228 char final_name[MAX_LINE +1];
231 final_name[MAX_LINE] = '\0';
233 snprintf(wdchar, 32, "%d", event->wd);
235 snprintf(final_name, MAX_LINE, "%s/%s",
236 (char *)OSHash_Get(syscheck.realtime->dirtb, wdchar),
238 realtime_checksumfile(final_name);
241 i += REALTIME_EVENT_SIZE + event->len;
251 typedef struct _win32rtfim
260 int realtime_win32read(win32rtfim *rtlocald);
262 void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap)
269 char final_path[MAX_LINE +1];
271 win32rtfim *rtlocald;
273 PFILE_NOTIFY_INFORMATION pinfo;
274 TCHAR finalfile[MAX_PATH];
278 merror("%s: ERROR: real time call back called, but 0 bytes.", ARGV0);
282 if(dwerror != ERROR_SUCCESS)
284 merror("%s: ERROR: real time call back called, but error is set.",
290 /* Getting hash to parse the data. */
292 snprintf(wdchar, 32, "%d", (int)overlap->Offset);
293 rtlocald = OSHash_Get(syscheck.realtime->dirtb, wdchar);
296 merror("%s: ERROR: real time call back called, but hash is empty.",
305 pinfo = (PFILE_NOTIFY_INFORMATION) &rtlocald->buffer[offset];
306 offset += pinfo->NextEntryOffset;
308 lcount = WideCharToMultiByte(CP_ACP, 0, pinfo->FileName,
309 pinfo->FileNameLength / sizeof(WCHAR),
310 finalfile, MAX_PATH - 1, NULL, NULL);
311 finalfile[lcount] = TEXT('\0');
314 /* Change forward slashes to backslashes on finalfile. */
315 ptfile = strchr(finalfile, '\\');
321 ptfile = strchr(ptfile, '\\');
324 final_path[MAX_LINE] = '\0';
325 snprintf(final_path, MAX_LINE, "%s/%s", rtlocald->dir, finalfile);
328 /* Checking the change. */
329 realtime_checksumfile(final_path);
333 if(pinfo->Action == FILE_ACTION_ADDED)
334 else if(pinfo->Action == FILE_ACTION_REMOVED)
335 else if(pinfo->Action == FILE_ACTION_MODIFIED)
336 else if(pinfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
337 else if(pinfo->Action == FILE_ACTION_RENAMED_NEW_NAME)
341 }while(pinfo->NextEntryOffset != 0);
344 realtime_win32read(rtlocald);
354 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
356 os_calloc(1, sizeof(rtfim), syscheck.realtime);
357 syscheck.realtime->dirtb = (void *)OSHash_Create();
358 syscheck.realtime->fd = -1;
359 syscheck.realtime->evt = CreateEvent(NULL, TRUE, FALSE, NULL);
363 int realtime_win32read(win32rtfim *rtlocald)
367 rc = ReadDirectoryChangesW(rtlocald->h,
369 sizeof(rtlocald->buffer) / sizeof(TCHAR),
371 FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE,
377 merror("%s: ERROR: Unable to set directory for monitoring: %s",
378 ARGV0, rtlocald->dir);
385 int realtime_adddir(char *dir)
388 win32rtfim *rtlocald;
391 if(!syscheck.realtime)
397 /* Maximum limit for realtime on Windows. */
398 if(syscheck.realtime->fd > 256)
400 merror("%s: ERROR: Unable to add directory to real time "
401 "monitoring: '%s' - Maximum size permitted.", ARGV0, dir);
406 os_calloc(1, sizeof(win32rtfim), rtlocald);
409 rtlocald->h = CreateFile(dir,
411 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
414 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
418 if(rtlocald->h == INVALID_HANDLE_VALUE ||
423 merror("%s: ERROR: Unable to add directory to real time "
424 "monitoring: '%s'.", ARGV0, dir);
428 rtlocald->overlap.Offset = ++syscheck.realtime->fd;
432 /* Setting key for hash. */
434 snprintf(wdchar, 32, "%d", (int)rtlocald->overlap.Offset);
437 if(OSHash_Get(syscheck.realtime->dirtb, wdchar))
439 merror("%s: ERROR: Entry already in the real time hash: %s",
441 CloseHandle(rtlocald->overlap.hEvent);
448 /* Adding final elements to the hash. */
449 os_strdup(dir, rtlocald->dir);
451 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), rtlocald);
454 /* Adding directory to be monitored. */
455 realtime_win32read(rtlocald);
468 verbose("%s: ERROR: Unable to initalize real time file monitoring.", ARGV0);
472 int realtime_adddir(char *dir)
477 int realtime_process()