X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=blobdiff_plain;f=src%2Fsyscheckd%2Frun_check.c;h=1bf45c6a2a5025389d3064ca75d42b2054e7e7bd;hp=8288e4895480005e8289b20bcdd19e28c2f7928a;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hpb=927951d1c1ad45ba9e7325f07d996154a91c911b diff --git a/src/syscheckd/run_check.c b/src/syscheckd/run_check.c old mode 100755 new mode 100644 index 8288e48..1bf45c6 --- a/src/syscheckd/run_check.c +++ b/src/syscheckd/run_check.c @@ -1,6 +1,3 @@ -/* @(#) $Id: ./src/syscheckd/run_check.c, 2011/09/08 dcid Exp $ - */ - /* Copyright (C) 2010 Trend Micro Inc. * All right reserved. * @@ -10,11 +7,15 @@ * Foundation */ - /* SCHED_BATCH is Linux specific and is only picked up with _GNU_SOURCE */ #ifdef __linux__ - #define _GNU_SOURCE - #include +#define _GNU_SOURCE +#include +#endif +#ifdef WIN32 +#include +#include +#include #endif #include "shared.h" @@ -22,124 +23,89 @@ #include "os_crypto/md5/md5_op.h" #include "os_crypto/sha1/sha1_op.h" #include "os_crypto/md5_sha1/md5_sha1_op.h" - #include "rootcheck/rootcheck.h" - -/** Prototypes **/ -int c_read_file(char *file_name, char *oldsum, char *newsum); +/* Prototypes */ +static void send_sk_db(void); -/* Send syscheck message. - * Send a message related to syscheck change/addition. - */ -int send_syscheck_msg(char *msg) +/* Send a message related to syscheck change/addition */ +int send_syscheck_msg(const char *msg) { - if(SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0) - { + if (SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0) { merror(QUEUE_SEND, ARGV0); - if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) - { + if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } - /* If we reach here, we can try to send it again */ + /* Try to send it again */ SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ); } - - return(0); + return (0); } - - -/* Send rootcheck message. - * Send a message related to rootcheck change/addition. - */ -int send_rootcheck_msg(char *msg) +/* Send a message related to rootcheck change/addition */ +int send_rootcheck_msg(const char *msg) { - if(SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) - { + if (SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) { merror(QUEUE_SEND, ARGV0); - if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0) - { + if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH); } - /* If we reach here, we can try to send it again */ + /* Try to send it again */ SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ); } - - return(0); + return (0); } - -/* Sends syscheck db to the server. - */ -void send_sk_db() +/* Send syscheck db to the server */ +static void send_sk_db() { - /* Sending scan start message */ - if(syscheck.dir[0]) - { + /* Send scan start message */ + if (syscheck.dir[0]) { merror("%s: INFO: Starting syscheck scan (forwarding database).", ARGV0); send_rootcheck_msg("Starting syscheck scan."); - } - else - { - sleep(syscheck.tsleep +10); + } else { return; } - create_db(1); - + create_db(); - /* Sending scan ending message */ - sleep(syscheck.tsleep +10); + /* Send scan ending message */ + sleep(syscheck.tsleep + 10); - if(syscheck.dir[0]) - { + if (syscheck.dir[0]) { merror("%s: INFO: Ending syscheck scan (forwarding database).", ARGV0); send_rootcheck_msg("Ending syscheck scan."); } } - - -/* start_daemon - * Run periodicaly the integrity checking - */ +/* Periodically run the integrity checker */ void start_daemon() { int day_scanned = 0; int curr_day = 0; - time_t curr_time = 0; - time_t prev_time_rk = 0; time_t prev_time_sk = 0; - char curr_hour[12]; - struct tm *p; - - /* To be used by select. */ - #ifdef USEINOTIFY +#ifdef INOTIFY_ENABLED + /* To be used by select */ struct timeval selecttime; fd_set rfds; - #endif - +#endif - /* - * SCHED_BATCH forces the kernel to assume this is a cpu intensive - * process - * and gives it a lower priority. This keeps ossec-syscheckd - * from reducing - * the interactity of an ssh session when checksumming large files. - * This is available in kernel flavors >= 2.6.16 + /* SCHED_BATCH forces the kernel to assume this is a cpu intensive + * process and gives it a lower priority. This keeps ossec-syscheckd + * from reducing the interactivity of an ssh session when checksumming + * large files. This is available in kernel flavors >= 2.6.16. */ - #ifdef SCHED_BATCH +#ifdef SCHED_BATCH struct sched_param pri; int status; @@ -147,395 +113,294 @@ void start_daemon() status = sched_setscheduler(0, SCHED_BATCH, &pri); debug1("%s: Setting SCHED_BATCH returned: %d", ARGV0, status); - #endif - - - #ifdef DEBUG - verbose("%s: Starting daemon ..",ARGV0); - #endif - +#endif +#ifdef DEBUG + verbose("%s: Starting daemon ..", ARGV0); +#endif /* Some time to settle */ memset(curr_hour, '\0', 12); sleep(syscheck.tsleep * 10); - - /* If the scan time/day is set, reset the * syscheck.time/rootcheck.time */ - if(syscheck.scan_time || syscheck.scan_day) - { - /* At least once a week. */ + if (syscheck.scan_time || syscheck.scan_day) { + /* At least once a week */ syscheck.time = 604800; rootcheck.time = 604800; } - /* Will create the db to store syscheck data */ - if(syscheck.scan_on_start) - { + if (syscheck.scan_on_start) { sleep(syscheck.tsleep * 15); send_sk_db(); - } - else - { - prev_time_rk = time(0); - } +#ifdef WIN32 + /* Check for registry changes on Windows */ + os_winreg_check(); +#endif + /* Send database completed message */ + send_syscheck_msg(HC_SK_DB_COMPLETED); + debug2("%s: DEBUG: Sending database completed message.", ARGV0); + } else { + prev_time_rk = time(0); + } /* Before entering in daemon mode itself */ prev_time_sk = time(0); sleep(syscheck.tsleep * 10); - /* If the scan_time or scan_day is set, we need to handle the * current day/time on the loop. */ - if(syscheck.scan_time || syscheck.scan_day) - { + if (syscheck.scan_time || syscheck.scan_day) { curr_time = time(0); p = localtime(&curr_time); - /* Assign hour/min/sec values */ snprintf(curr_hour, 9, "%02d:%02d:%02d", - p->tm_hour, - p->tm_min, - p->tm_sec); - + p->tm_hour, + p->tm_min, + p->tm_sec); curr_day = p->tm_mday; - - - if(syscheck.scan_time && syscheck.scan_day) - { - if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) && - (OS_IsonDay(p->tm_wday, syscheck.scan_day))) - { + if (syscheck.scan_time && syscheck.scan_day) { + if ((OS_IsAfterTime(curr_hour, syscheck.scan_time)) && + (OS_IsonDay(p->tm_wday, syscheck.scan_day))) { day_scanned = 1; } - } - - else if(syscheck.scan_time) - { - if(OS_IsAfterTime(curr_hour, syscheck.scan_time)) - { + } else if (syscheck.scan_time) { + if (OS_IsAfterTime(curr_hour, syscheck.scan_time)) { day_scanned = 1; } - } - else if(syscheck.scan_day) - { - if(OS_IsonDay(p->tm_wday, syscheck.scan_day)) - { + } else if (syscheck.scan_day) { + if (OS_IsonDay(p->tm_wday, syscheck.scan_day)) { day_scanned = 1; } } } - - /* Checking every SYSCHECK_WAIT */ - while(1) - { + /* Check every SYSCHECK_WAIT */ + while (1) { int run_now = 0; curr_time = time(0); - - /* Checking if syscheck should be restarted, */ + /* Check if syscheck should be restarted */ run_now = os_check_restart_syscheck(); - - /* Checking if a day_time or scan_time is set. */ - if(syscheck.scan_time || syscheck.scan_day) - { + /* Check if a day_time or scan_time is set */ + if (syscheck.scan_time || syscheck.scan_day) { p = localtime(&curr_time); - - /* Day changed. */ - if(curr_day != p->tm_mday) - { + /* Day changed */ + if (curr_day != p->tm_mday) { day_scanned = 0; curr_day = p->tm_mday; } - - /* Checking for the time of the scan. */ - if(!day_scanned && syscheck.scan_time && syscheck.scan_day) - { + /* Check for the time of the scan */ + if (!day_scanned && syscheck.scan_time && syscheck.scan_day) { /* Assign hour/min/sec values */ snprintf(curr_hour, 9, "%02d:%02d:%02d", - p->tm_hour, p->tm_min, p->tm_sec); + p->tm_hour, p->tm_min, p->tm_sec); - if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) && - (OS_IsonDay(p->tm_wday, syscheck.scan_day))) - { + if ((OS_IsAfterTime(curr_hour, syscheck.scan_time)) && + (OS_IsonDay(p->tm_wday, syscheck.scan_day))) { day_scanned = 1; run_now = 1; } - } - - else if(!day_scanned && syscheck.scan_time) - { + } else if (!day_scanned && syscheck.scan_time) { /* Assign hour/min/sec values */ snprintf(curr_hour, 9, "%02d:%02d:%02d", - p->tm_hour, p->tm_min, p->tm_sec); + p->tm_hour, p->tm_min, p->tm_sec); - if(OS_IsAfterTime(curr_hour, syscheck.scan_time)) - { + if (OS_IsAfterTime(curr_hour, syscheck.scan_time)) { run_now = 1; day_scanned = 1; } - } - - /* Checking for the day of the scan. */ - else if(!day_scanned && syscheck.scan_day) - { - if(OS_IsonDay(p->tm_wday, syscheck.scan_day)) - { + } else if (!day_scanned && syscheck.scan_day) { + /* Check for the day of the scan */ + if (OS_IsonDay(p->tm_wday, syscheck.scan_day)) { run_now = 1; day_scanned = 1; } } } - - - /* If time elapsed is higher than the rootcheck_time, - * run it. - */ - if(syscheck.rootcheck) - { - if(((curr_time - prev_time_rk) > rootcheck.time) || run_now) - { + /* If time elapsed is higher than the rootcheck_time, run it */ + if (syscheck.rootcheck) { + if (((curr_time - prev_time_rk) > rootcheck.time) || run_now) { run_rk_check(); prev_time_rk = time(0); } } - - /* If time elapsed is higher than the syscheck time, - * run syscheck time. - */ - if(((curr_time - prev_time_sk) > syscheck.time) || run_now) - { - /* We need to create the db, if scan on start is not set. */ - if(syscheck.scan_on_start == 0) - { + /* If time elapsed is higher than the syscheck time, run syscheck time */ + if (((curr_time - prev_time_sk) > syscheck.time) || run_now) { + if (syscheck.scan_on_start == 0) { + /* Need to create the db if scan on start is not set */ sleep(syscheck.tsleep * 10); send_sk_db(); sleep(syscheck.tsleep * 10); syscheck.scan_on_start = 1; - } - - - else - { - /* Sending scan start message */ - if(syscheck.dir[0]) - { + } else { + /* Send scan start message */ + if (syscheck.dir[0]) { merror("%s: INFO: Starting syscheck scan.", ARGV0); send_rootcheck_msg("Starting syscheck scan."); } - - - #ifdef WIN32 - /* Checking for registry changes on Windows */ +#ifdef WIN32 + /* Check for registry changes on Windows */ os_winreg_check(); - #endif - - - /* Checking for changes */ +#endif + /* Check for changes */ run_dbcheck(); } - - /* Sending scan ending message */ + /* Send scan ending message */ sleep(syscheck.tsleep + 20); - if(syscheck.dir[0]) - { + if (syscheck.dir[0]) { merror("%s: INFO: Ending syscheck scan.", ARGV0); send_rootcheck_msg("Ending syscheck scan."); } - - - /* Sending database completed message */ + /* Send database completed message */ send_syscheck_msg(HC_SK_DB_COMPLETED); debug2("%s: DEBUG: Sending database completed message.", ARGV0); - prev_time_sk = time(0); } - - #ifdef USEINOTIFY - if(syscheck.realtime && (syscheck.realtime->fd >= 0)) - { +#ifdef INOTIFY_ENABLED + if (syscheck.realtime && (syscheck.realtime->fd >= 0)) { selecttime.tv_sec = SYSCHECK_WAIT; selecttime.tv_usec = 0; /* zero-out the fd_set */ FD_ZERO (&rfds); - FD_SET(syscheck.realtime->fd, &rfds); run_now = select(syscheck.realtime->fd + 1, &rfds, NULL, NULL, &selecttime); - if(run_now < 0) - { + if (run_now < 0) { merror("%s: ERROR: Select failed (for realtime fim).", ARGV0); sleep(SYSCHECK_WAIT); - } - else if(run_now == 0) - { - /* Timeout. */ - } - else if (FD_ISSET (syscheck.realtime->fd, &rfds)) - { + } else if (run_now == 0) { + /* Timeout */ + } else if (FD_ISSET (syscheck.realtime->fd, &rfds)) { realtime_process(); } - } - else - { + } else { sleep(SYSCHECK_WAIT); } - - #elif WIN32 - if(syscheck.realtime && (syscheck.realtime->fd >= 0)) - { - run_now = WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE); - if(run_now == WAIT_FAILED) - { +#elif defined(WIN32) + if (syscheck.realtime && (syscheck.realtime->fd >= 0)) { + if (WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE) == WAIT_FAILED) { merror("%s: ERROR: WaitForSingleObjectEx failed (for realtime fim).", ARGV0); sleep(SYSCHECK_WAIT); - } - else - { + } else { sleep(1); } - } - else - { + } else { sleep(SYSCHECK_WAIT); } - - - #else +#else sleep(SYSCHECK_WAIT); - #endif +#endif } } - - - -/* c_read_file - * Read file information and return a pointer - * to the checksum - */ -int c_read_file(char *file_name, char *oldsum, char *newsum) +/* Read file information and return a pointer to the checksum */ +int c_read_file(const char *file_name, const char *oldsum, char *newsum) { int size = 0, perm = 0, owner = 0, group = 0, md5sum = 0, sha1sum = 0; - + int return_error = 0; struct stat statbuf; - os_md5 mf_sum; os_sha1 sf_sum; - - /* Cleaning sums */ + /* Clean sums */ strncpy(mf_sum, "xxx", 4); strncpy(sf_sum, "xxx", 4); - - - /* Stating the file */ - #ifdef WIN32 - if(stat(file_name, &statbuf) < 0) - #else - if(lstat(file_name, &statbuf) < 0) - #endif + /* Stat the file */ +#ifdef WIN32 + return_error = (stat(file_name, &statbuf) < 0); +#else + return_error = (lstat(file_name, &statbuf) < 0); +#endif + if (return_error) { - char alert_msg[912 +2]; + char alert_msg[PATH_MAX+4]; - alert_msg[912 +1] = '\0'; - snprintf(alert_msg, 912,"-1 %s", file_name); + alert_msg[PATH_MAX + 3] = '\0'; + snprintf(alert_msg, PATH_MAX + 4, "-1 %s", file_name); send_syscheck_msg(alert_msg); - return(-1); + return (-1); } - /* Getting the old sum values */ + /* Get the old sum values */ /* size */ - if(oldsum[0] == '+') + if (oldsum[0] == '+') { size = 1; + } /* perm */ - if(oldsum[1] == '+') + if (oldsum[1] == '+') { perm = 1; + } /* owner */ - if(oldsum[2] == '+') + if (oldsum[2] == '+') { owner = 1; + } /* group */ - if(oldsum[3] == '+') + if (oldsum[3] == '+') { group = 1; + } /* md5 sum */ - if(oldsum[4] == '+') + if (oldsum[4] == '+') { md5sum = 1; + } /* sha1 sum */ - if(oldsum[5] == '+') + if (oldsum[5] == '+') { sha1sum = 1; - - else if(oldsum[5] == 's') - { + } else if (oldsum[5] == 's') { sha1sum = 1; - } - else if(oldsum[5] == 'n') - { + } else if (oldsum[5] == 'n') { sha1sum = 0; } - - /* Generating new checksum */ - #ifdef WIN32 - if(S_ISREG(statbuf.st_mode)) - #else - if(S_ISREG(statbuf.st_mode)) - #endif + /* Generate new checksum */ + if (S_ISREG(statbuf.st_mode)) { - if(sha1sum || md5sum) - { - /* Generating checksums of the file. */ - if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0) - { + if (sha1sum || md5sum) { + /* Generate checksums of the file */ + if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) { strncpy(sf_sum, "xxx", 4); strncpy(mf_sum, "xxx", 4); } } } - #ifndef WIN32 - /* If it is a link, we need to check if the actual file is valid. */ - else if(S_ISLNK(statbuf.st_mode)) - { +#ifndef WIN32 + /* If it is a link, check if the actual file is valid */ + else if (S_ISLNK(statbuf.st_mode)) { struct stat statbuf_lnk; - if(stat(file_name, &statbuf_lnk) == 0) - { - if(S_ISREG(statbuf_lnk.st_mode)) - { - if(sha1sum || md5sum) - { - /* Generating checksums of the file. */ - if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0) - { + if (stat(file_name, &statbuf_lnk) == 0) { + if (S_ISREG(statbuf_lnk.st_mode)) { + if (sha1sum || md5sum) { + /* Generate checksums of the file */ + if (OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum, OS_BINARY) < 0) { strncpy(sf_sum, "xxx", 4); strncpy(mf_sum, "xxx", 4); } @@ -543,20 +408,62 @@ int c_read_file(char *file_name, char *oldsum, char *newsum) } } } - #endif +#endif newsum[0] = '\0'; newsum[255] = '\0'; - /* chris: changed st_size int to long */ - snprintf(newsum,255,"%ld:%d:%d:%d:%s:%s", - size == 0?0:(long)statbuf.st_size, - perm == 0?0:(int)statbuf.st_mode, - owner== 0?0:(int)statbuf.st_uid, - group== 0?0:(int)statbuf.st_gid, - md5sum == 0?"xxx":mf_sum, - sha1sum == 0?"xxx":sf_sum); - - return(0); -} +#ifndef WIN32 + snprintf(newsum, 255, "%ld:%d:%d:%d:%s:%s", + size == 0 ? 0 : (long)statbuf.st_size, + perm == 0 ? 0 : (int)statbuf.st_mode, + owner == 0 ? 0 : (int)statbuf.st_uid, + group == 0 ? 0 : (int)statbuf.st_gid, + md5sum == 0 ? "xxx" : mf_sum, + sha1sum == 0 ? "xxx" : sf_sum); +#else + HANDLE hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + DWORD dwErrorCode = GetLastError(); + char alert_msg[PATH_MAX+4]; + alert_msg[PATH_MAX + 3] = '\0'; + snprintf(alert_msg, PATH_MAX + 4, "CreateFile=%ld %s", dwErrorCode, file_name); + send_syscheck_msg(alert_msg); + return -1; + } -/* EOF */ + PSID pSidOwner = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + DWORD dwRtnCode = GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD); + if (dwRtnCode != ERROR_SUCCESS) { + DWORD dwErrorCode = GetLastError(); + CloseHandle(hFile); + char alert_msg[PATH_MAX+4]; + alert_msg[PATH_MAX + 3] = '\0'; + snprintf(alert_msg, PATH_MAX + 4, "GetSecurityInfo=%ld %s", dwErrorCode, file_name); + send_syscheck_msg(alert_msg); + return -1; + } + + LPSTR szSID = NULL; + ConvertSidToStringSid(pSidOwner, &szSID); + char* st_uid = NULL; + if( szSID ) { + st_uid = (char *) calloc( strlen(szSID) + 1, 1 ); + memcpy( st_uid, szSID, strlen(szSID) ); + } + LocalFree(szSID); + CloseHandle(hFile); + + snprintf(newsum, 255, "%ld:%d:%s:%d:%s:%s", + size == 0 ? 0 : (long)statbuf.st_size, + perm == 0 ? 0 : (int)statbuf.st_mode, + owner == 0 ? "0" : st_uid, + group == 0 ? 0 : (int)statbuf.st_gid, + md5sum == 0 ? "xxx" : mf_sum, + sha1sum == 0 ? "xxx" : sf_sum); + + free(st_uid); +#endif + + return (0); +}