X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=blobdiff_plain;f=src%2Fsyscheckd%2Frun_realtime.c;h=575b97c39dc3754cbfec67a34ff2933273e7bb16;hp=20d8fb22168b0647080a1c6d19ebb81e48bbae02;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hpb=927951d1c1ad45ba9e7325f07d996154a91c911b diff --git a/src/syscheckd/run_realtime.c b/src/syscheckd/run_realtime.c old mode 100755 new mode 100644 index 20d8fb2..575b97c --- a/src/syscheckd/run_realtime.c +++ b/src/syscheckd/run_realtime.c @@ -1,6 +1,3 @@ -/* @(#) $Id: ./src/syscheckd/run_realtime.c, 2011/09/08 dcid Exp $ - */ - /* Copyright (C) 2009 Trend Micro Inc. * All right reserved. * @@ -10,7 +7,6 @@ * Foundation */ - #include #include #include @@ -19,25 +15,11 @@ #include #include - #ifdef WIN32 -#include -#include -#include - #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 #define OS_SIZE_6144 6144 #define OS_MAXSTR OS_SIZE_6144 /* Size for logs, sockets, etc */ @@ -45,191 +27,196 @@ #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 it returns < 0, we will already have 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]; - alert_msg[OS_MAXSTR] = '\0'; - #ifdef WIN32 - snprintf(alert_msg, 912, "%s %s", c_sum, file_name); - #else - char *fullalert = NULL; - if(buf[5] == 's' || buf[5] == 'n') - { - fullalert = seechanges_addfile(file_name); - if(fullalert) - { + if (strcmp(c_sum, buf + 6) != 0) { + char alert_msg[OS_MAXSTR + 1]; + + alert_msg[OS_MAXSTR] = '\0'; + + #ifdef WIN32 + snprintf(alert_msg, 912, "%s %s", c_sum, file_name); + #else + char *fullalert = NULL; + + 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); - } - #endif - 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 - #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) - { + 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]; + "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]; + } 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]; + if (event->len) { + char wdchar[32 + 1]; + char final_name[MAX_LINE + 1]; wdchar[32] = '\0'; final_name[MAX_LINE] = '\0'; @@ -239,6 +226,11 @@ int realtime_process() 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); } @@ -246,20 +238,17 @@ int realtime_process() } } - 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); @@ -267,45 +256,39 @@ void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap) { 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) - { + 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) - { + 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; @@ -314,11 +297,9 @@ void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap) 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++; @@ -328,31 +309,15 @@ void CALLBACK RTCallBack(DWORD dwerror, DWORD dwBytes, LPOVERLAPPED overlap) 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); @@ -361,7 +326,8 @@ int realtime_start() 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) @@ -372,116 +338,98 @@ 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, RTCallBack); - if(rc == 0) - { + 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)) - { + 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 */ +