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 alert_msg[OS_MAXSTR +1];
78 alert_msg[OS_MAXSTR] = '\0';
80 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
82 char *fullalert = NULL;
83 if(buf[5] == 's' || buf[5] == 'n')
85 fullalert = seechanges_addfile(file_name);
88 snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
94 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
99 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
102 send_syscheck_msg(alert_msg);
118 #include <sys/inotify.h>
121 #define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_FROM|IN_MOVED_TO|IN_CREATE|IN_DELETE|IN_DELETE_SELF
122 #define REALTIME_EVENT_SIZE (sizeof (struct inotify_event))
123 #define REALTIME_EVENT_BUFFER (2048 * (REALTIME_EVENT_SIZE + 16))
127 /* Starts real time monitoring using inotify. */
130 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
132 syscheck.realtime = calloc(1, sizeof(rtfim));
133 if(syscheck.realtime == NULL)
135 ErrorExit(MEM_ERROR, ARGV0);
137 syscheck.realtime->dirtb = (void *)OSHash_Create();
138 syscheck.realtime->fd = -1;
141 syscheck.realtime->fd = inotify_init();
142 if(syscheck.realtime->fd < 0)
144 merror("%s: ERROR: Unable to initialize inotify.", ARGV0);
154 /* Adds a directory to real time checking. */
155 int realtime_adddir(char *dir)
157 if(!syscheck.realtime)
163 /* Checking if it is ready to use. */
164 if(syscheck.realtime->fd < 0)
172 wd = inotify_add_watch(syscheck.realtime->fd,
174 REALTIME_MONITOR_FLAGS);
177 merror("%s: ERROR: Unable to add directory to real time "
178 "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno);
184 snprintf(wdchar, 32, "%d", wd);
186 /* Entry not present. */
187 if(!OSHash_Get(syscheck.realtime->dirtb, wdchar))
194 ErrorExit("%s: ERROR: Out of memory. Exiting.", ARGV0);
197 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), ndir);
198 debug1("%s: DEBUG: Directory added for real time monitoring: "
199 "'%s'.", ARGV0, ndir);
208 /* Process events in the real time queue. */
209 int realtime_process()
212 char buf[REALTIME_EVENT_BUFFER +1];
213 struct inotify_event *event;
215 buf[REALTIME_EVENT_BUFFER] = '\0';
218 len = read(syscheck.realtime->fd, buf, REALTIME_EVENT_BUFFER);
221 merror("%s: ERROR: Unable to read from real time buffer.", ARGV0);
227 event = (struct inotify_event *) &buf[i];
232 char final_name[MAX_LINE +1];
235 final_name[MAX_LINE] = '\0';
237 snprintf(wdchar, 32, "%d", event->wd);
239 snprintf(final_name, MAX_LINE, "%s/%s",
240 (char *)OSHash_Get(syscheck.realtime->dirtb, wdchar),
242 realtime_checksumfile(final_name);
245 i += REALTIME_EVENT_SIZE + event->len;
255 typedef struct _win32rtfim
264 int realtime_win32read(win32rtfim *rtlocald);
266 void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap)
273 char final_path[MAX_LINE +1];
275 win32rtfim *rtlocald;
277 PFILE_NOTIFY_INFORMATION pinfo;
278 TCHAR finalfile[MAX_PATH];
282 merror("%s: ERROR: real time call back called, but 0 bytes.", ARGV0);
286 if(dwerror != ERROR_SUCCESS)
288 merror("%s: ERROR: real time call back called, but error is set.",
294 /* Getting hash to parse the data. */
296 snprintf(wdchar, 32, "%d", (int)overlap->Offset);
297 rtlocald = OSHash_Get(syscheck.realtime->dirtb, wdchar);
300 merror("%s: ERROR: real time call back called, but hash is empty.",
309 pinfo = (PFILE_NOTIFY_INFORMATION) &rtlocald->buffer[offset];
310 offset += pinfo->NextEntryOffset;
312 lcount = WideCharToMultiByte(CP_ACP, 0, pinfo->FileName,
313 pinfo->FileNameLength / sizeof(WCHAR),
314 finalfile, MAX_PATH - 1, NULL, NULL);
315 finalfile[lcount] = TEXT('\0');
318 /* Change forward slashes to backslashes on finalfile. */
319 ptfile = strchr(finalfile, '\\');
325 ptfile = strchr(ptfile, '\\');
328 final_path[MAX_LINE] = '\0';
329 snprintf(final_path, MAX_LINE, "%s/%s", rtlocald->dir, finalfile);
332 /* Checking the change. */
333 realtime_checksumfile(final_path);
337 if(pinfo->Action == FILE_ACTION_ADDED)
338 else if(pinfo->Action == FILE_ACTION_REMOVED)
339 else if(pinfo->Action == FILE_ACTION_MODIFIED)
340 else if(pinfo->Action == FILE_ACTION_RENAMED_OLD_NAME)
341 else if(pinfo->Action == FILE_ACTION_RENAMED_NEW_NAME)
345 }while(pinfo->NextEntryOffset != 0);
348 realtime_win32read(rtlocald);
358 verbose("%s: INFO: Initializing real time file monitoring (not started).", ARGV0);
360 os_calloc(1, sizeof(rtfim), syscheck.realtime);
361 syscheck.realtime->dirtb = (void *)OSHash_Create();
362 syscheck.realtime->fd = -1;
363 syscheck.realtime->evt = CreateEvent(NULL, TRUE, FALSE, NULL);
367 int realtime_win32read(win32rtfim *rtlocald)
371 rc = ReadDirectoryChangesW(rtlocald->h,
373 sizeof(rtlocald->buffer) / sizeof(TCHAR),
375 FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE,
381 merror("%s: ERROR: Unable to set directory for monitoring: %s",
382 ARGV0, rtlocald->dir);
389 int realtime_adddir(char *dir)
392 win32rtfim *rtlocald;
395 if(!syscheck.realtime)
401 /* Maximum limit for realtime on Windows. */
402 if(syscheck.realtime->fd > 256)
404 merror("%s: ERROR: Unable to add directory to real time "
405 "monitoring: '%s' - Maximum size permitted.", ARGV0, dir);
410 os_calloc(1, sizeof(win32rtfim), rtlocald);
413 rtlocald->h = CreateFile(dir,
415 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
418 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
422 if(rtlocald->h == INVALID_HANDLE_VALUE ||
427 merror("%s: ERROR: Unable to add directory to real time "
428 "monitoring: '%s'.", ARGV0, dir);
432 rtlocald->overlap.Offset = ++syscheck.realtime->fd;
436 /* Setting key for hash. */
438 snprintf(wdchar, 32, "%d", (int)rtlocald->overlap.Offset);
441 if(OSHash_Get(syscheck.realtime->dirtb, wdchar))
443 merror("%s: ERROR: Entry already in the real time hash: %s",
445 CloseHandle(rtlocald->overlap.hEvent);
452 /* Adding final elements to the hash. */
453 os_strdup(dir, rtlocald->dir);
455 OSHash_Add(syscheck.realtime->dirtb, strdup(wdchar), rtlocald);
458 /* Adding directory to be monitored. */
459 realtime_win32read(rtlocald);
472 verbose("%s: ERROR: Unable to initalize real time file monitoring.", ARGV0);
476 int realtime_adddir(char *dir)
481 int realtime_process()