X-Git-Url: http://ftp.carnet.hr/pub/carnet-debian/scm?a=blobdiff_plain;f=src%2Fsyscheckd%2Frun_realtime.c;h=575b97c39dc3754cbfec67a34ff2933273e7bb16;hb=HEAD;hp=efae8062277a79bc2cc0a54bd1c537aecd047053;hpb=914feba5d54f979cd5d7e69c349c3d01f630042a;p=ossec-hids.git diff --git a/src/syscheckd/run_realtime.c b/src/syscheckd/run_realtime.c old mode 100755 new mode 100644 index efae806..575b97c --- a/src/syscheckd/run_realtime.c +++ b/src/syscheckd/run_realtime.c @@ -1,15 +1,12 @@ -/* @(#) $Id: run_realtime.c,v 1.12 2009/12/01 15:40:08 dcid Exp $ */ - /* Copyright (C) 2009 Trend Micro Inc. * All right reserved. * * This program is a free software; you can redistribute it * and/or modify it under the terms of the GNU General Public - * License (version 3) as published by the FSF - Free Software + * License (version 2) as published by the FSF - Free Software * Foundation */ - #include #include #include @@ -18,231 +15,222 @@ #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 +#ifdef INOTIFY_ENABLED +#include +#define OS_SIZE_6144 6144 +#define OS_MAXSTR OS_SIZE_6144 /* Size for logs, sockets, etc */ +#else +#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" - -#ifdef USEINOTIFY -#include -#endif - +/* Prototypes */ +int realtime_checksumfile(const char *file_name) __attribute__((nonnull)); -/** Global functions for all realtime options. **/ -int c_read_file(char *file_name, char *oldsum, char *newsum); - - -/* 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[MAX_LINE +2]; - buf[MAX_LINE +1] = '\0'; - - - fseek(syscheck.fp, 0, SEEK_SET); - while(fgets(buf, MAX_LINE, syscheck.fp) != NULL) - { - if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n')) - { - char *n_buf; - - /* Removing the new line */ - n_buf = strchr(buf,'\n'); - if(n_buf == NULL) - continue; - - *n_buf = '\0'; + char *buf; + buf = (char *) OSHash_Get(syscheck.fp, file_name); + if (buf != NULL) { + char c_sum[256 + 2]; - /* First 6 characters are for internal use */ - n_buf = buf; - n_buf+=6; - - n_buf = strchr(n_buf, ' '); - if(n_buf) - { - n_buf++; - - /* Checking if name matches */ - if(strcmp(n_buf, file_name) == 0) - { - char c_sum[256 +2]; - c_sum[0] = '\0'; - c_sum[255] = '\0'; - - - /* If it returns < 0, we will already have alerted. */ - if(c_read_file(file_name, buf, c_sum) < 0) - continue; + 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(strcmp(c_sum, buf+6) != 0) - { - char alert_msg[912 +2]; + if (strcmp(c_sum, buf + 6) != 0) { + char alert_msg[OS_MAXSTR + 1]; - /* Sending the new checksum to the analysis server */ - alert_msg[912 +1] = '\0'; - snprintf(alert_msg, 912, "%s %s", c_sum, file_name); - send_syscheck_msg(alert_msg); + alert_msg[OS_MAXSTR] = '\0'; - return(1); - } + #ifdef WIN32 + snprintf(alert_msg, 912, "%s %s", c_sum, file_name); + #else + char *fullalert = NULL; - return(0); + 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 { + /* 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); + } - /* Adding entry if not in there. */ - fseek(syscheck.fp, 0, SEEK_END); - return(0); + return (0); } - - - -#ifdef USEINOTIFY +#ifdef INOTIFY_ENABLED #include - -#define REALTIME_MONITOR_FLAGS IN_MODIFY|IN_ATTRIB|IN_MOVED_TO|IN_DELETE|IN_MOVED_FROM +#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) - { - merror("%s: ERROR: Unable to add directory to real time " - "monitoring: '%s'. %d %d", ARGV0, dir, wd, errno); - } - else - { - char wdchar[32 +1]; + REALTIME_MONITOR_FLAGS); + if (wd < 0) { + merror("%s: ERROR: Unable to add directory to real time " + "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]; - - if(event->len) - { - char wdchar[32 +1]; - char final_name[MAX_LINE +1]; + } 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]; wdchar[32] = '\0'; final_name[MAX_LINE] = '\0'; snprintf(wdchar, 32, "%d", event->wd); - snprintf(final_name, MAX_LINE, "%s/%s", + 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); } @@ -250,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); @@ -271,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) - { - merror("%s: ERROR: real time call back called, but error is set.", + 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) - { - merror("%s: ERROR: real time call back called, but hash is empty.", + 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; @@ -318,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++; @@ -332,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); @@ -365,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) @@ -376,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, + &rtlocald->overlap, RTCallBack); - if(rc == 0) - { - merror("%s: ERROR: Unable to set directory for monitoring: %s", + 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)) - { - merror("%s: ERROR: Entry already in the real time hash: %s", + 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 */ +