1 /* @(#) $Id: ./src/syscheckd/run_check.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2010 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
14 /* SCHED_BATCH is Linux specific and is only picked up with _GNU_SOURCE */
22 #include "os_crypto/md5/md5_op.h"
23 #include "os_crypto/sha1/sha1_op.h"
24 #include "os_crypto/md5_sha1/md5_sha1_op.h"
26 #include "rootcheck/rootcheck.h"
30 int c_read_file(char *file_name, char *oldsum, char *newsum);
33 /* Send syscheck message.
34 * Send a message related to syscheck change/addition.
36 int send_syscheck_msg(char *msg)
38 if(SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0)
40 merror(QUEUE_SEND, ARGV0);
42 if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
44 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
47 /* If we reach here, we can try to send it again */
48 SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ);
56 /* Send rootcheck message.
57 * Send a message related to rootcheck change/addition.
59 int send_rootcheck_msg(char *msg)
61 if(SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0)
63 merror(QUEUE_SEND, ARGV0);
65 if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
67 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
70 /* If we reach here, we can try to send it again */
71 SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ);
78 /* Sends syscheck db to the server.
82 /* Sending scan start message */
85 merror("%s: INFO: Starting syscheck scan (forwarding database).", ARGV0);
86 send_rootcheck_msg("Starting syscheck scan.");
90 sleep(syscheck.tsleep +10);
97 /* Sending scan ending message */
98 sleep(syscheck.tsleep +10);
102 merror("%s: INFO: Ending syscheck scan (forwarding database).", ARGV0);
103 send_rootcheck_msg("Ending syscheck scan.");
110 * Run periodicaly the integrity checking
117 time_t curr_time = 0;
119 time_t prev_time_rk = 0;
120 time_t prev_time_sk = 0;
127 /* To be used by select. */
129 struct timeval selecttime;
135 * SCHED_BATCH forces the kernel to assume this is a cpu intensive
137 * and gives it a lower priority. This keeps ossec-syscheckd
139 * the interactity of an ssh session when checksumming large files.
140 * This is available in kernel flavors >= 2.6.16
143 struct sched_param pri;
146 pri.sched_priority = 0;
147 status = sched_setscheduler(0, SCHED_BATCH, &pri);
149 debug1("%s: Setting SCHED_BATCH returned: %d", ARGV0, status);
154 verbose("%s: Starting daemon ..",ARGV0);
159 /* Some time to settle */
160 memset(curr_hour, '\0', 12);
161 sleep(syscheck.tsleep * 10);
165 /* If the scan time/day is set, reset the
166 * syscheck.time/rootcheck.time
168 if(syscheck.scan_time || syscheck.scan_day)
170 /* At least once a week. */
171 syscheck.time = 604800;
172 rootcheck.time = 604800;
176 /* Will create the db to store syscheck data */
177 if(syscheck.scan_on_start)
179 sleep(syscheck.tsleep * 15);
184 prev_time_rk = time(0);
189 /* Before entering in daemon mode itself */
190 prev_time_sk = time(0);
191 sleep(syscheck.tsleep * 10);
194 /* If the scan_time or scan_day is set, we need to handle the
195 * current day/time on the loop.
197 if(syscheck.scan_time || syscheck.scan_day)
200 p = localtime(&curr_time);
203 /* Assign hour/min/sec values */
204 snprintf(curr_hour, 9, "%02d:%02d:%02d",
210 curr_day = p->tm_mday;
214 if(syscheck.scan_time && syscheck.scan_day)
216 if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
217 (OS_IsonDay(p->tm_wday, syscheck.scan_day)))
223 else if(syscheck.scan_time)
225 if(OS_IsAfterTime(curr_hour, syscheck.scan_time))
230 else if(syscheck.scan_day)
232 if(OS_IsonDay(p->tm_wday, syscheck.scan_day))
240 /* Checking every SYSCHECK_WAIT */
247 /* Checking if syscheck should be restarted, */
248 run_now = os_check_restart_syscheck();
251 /* Checking if a day_time or scan_time is set. */
252 if(syscheck.scan_time || syscheck.scan_day)
254 p = localtime(&curr_time);
258 if(curr_day != p->tm_mday)
261 curr_day = p->tm_mday;
265 /* Checking for the time of the scan. */
266 if(!day_scanned && syscheck.scan_time && syscheck.scan_day)
268 /* Assign hour/min/sec values */
269 snprintf(curr_hour, 9, "%02d:%02d:%02d",
270 p->tm_hour, p->tm_min, p->tm_sec);
272 if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
273 (OS_IsonDay(p->tm_wday, syscheck.scan_day)))
280 else if(!day_scanned && syscheck.scan_time)
282 /* Assign hour/min/sec values */
283 snprintf(curr_hour, 9, "%02d:%02d:%02d",
284 p->tm_hour, p->tm_min, p->tm_sec);
286 if(OS_IsAfterTime(curr_hour, syscheck.scan_time))
293 /* Checking for the day of the scan. */
294 else if(!day_scanned && syscheck.scan_day)
296 if(OS_IsonDay(p->tm_wday, syscheck.scan_day))
306 /* If time elapsed is higher than the rootcheck_time,
309 if(syscheck.rootcheck)
311 if(((curr_time - prev_time_rk) > rootcheck.time) || run_now)
314 prev_time_rk = time(0);
319 /* If time elapsed is higher than the syscheck time,
322 if(((curr_time - prev_time_sk) > syscheck.time) || run_now)
324 /* We need to create the db, if scan on start is not set. */
325 if(syscheck.scan_on_start == 0)
327 sleep(syscheck.tsleep * 10);
329 sleep(syscheck.tsleep * 10);
331 syscheck.scan_on_start = 1;
337 /* Sending scan start message */
340 merror("%s: INFO: Starting syscheck scan.", ARGV0);
341 send_rootcheck_msg("Starting syscheck scan.");
346 /* Checking for registry changes on Windows */
351 /* Checking for changes */
356 /* Sending scan ending message */
357 sleep(syscheck.tsleep + 20);
360 merror("%s: INFO: Ending syscheck scan.", ARGV0);
361 send_rootcheck_msg("Ending syscheck scan.");
366 /* Sending database completed message */
367 send_syscheck_msg(HC_SK_DB_COMPLETED);
368 debug2("%s: DEBUG: Sending database completed message.", ARGV0);
371 prev_time_sk = time(0);
376 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
378 selecttime.tv_sec = SYSCHECK_WAIT;
379 selecttime.tv_usec = 0;
381 /* zero-out the fd_set */
384 FD_SET(syscheck.realtime->fd, &rfds);
386 run_now = select(syscheck.realtime->fd + 1, &rfds,
387 NULL, NULL, &selecttime);
390 merror("%s: ERROR: Select failed (for realtime fim).", ARGV0);
391 sleep(SYSCHECK_WAIT);
393 else if(run_now == 0)
397 else if (FD_ISSET (syscheck.realtime->fd, &rfds))
404 sleep(SYSCHECK_WAIT);
408 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
410 run_now = WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE);
411 if(run_now == WAIT_FAILED)
413 merror("%s: ERROR: WaitForSingleObjectEx failed (for realtime fim).", ARGV0);
414 sleep(SYSCHECK_WAIT);
423 sleep(SYSCHECK_WAIT);
428 sleep(SYSCHECK_WAIT);
437 * Read file information and return a pointer
440 int c_read_file(char *file_name, char *oldsum, char *newsum)
442 int size = 0, perm = 0, owner = 0, group = 0, md5sum = 0, sha1sum = 0;
451 strncpy(mf_sum, "xxx", 4);
452 strncpy(sf_sum, "xxx", 4);
456 /* Stating the file */
458 if(stat(file_name, &statbuf) < 0)
460 if(lstat(file_name, &statbuf) < 0)
463 char alert_msg[912 +2];
465 alert_msg[912 +1] = '\0';
466 snprintf(alert_msg, 912,"-1 %s", file_name);
467 send_syscheck_msg(alert_msg);
472 /* Getting the old sum values */
498 else if(oldsum[5] == 's')
502 else if(oldsum[5] == 'n')
508 /* Generating new checksum */
510 if(S_ISREG(statbuf.st_mode))
512 if(S_ISREG(statbuf.st_mode))
515 if(sha1sum || md5sum)
517 /* Generating checksums of the file. */
518 if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
520 strncpy(sf_sum, "xxx", 4);
521 strncpy(mf_sum, "xxx", 4);
526 /* If it is a link, we need to check if the actual file is valid. */
527 else if(S_ISLNK(statbuf.st_mode))
529 struct stat statbuf_lnk;
530 if(stat(file_name, &statbuf_lnk) == 0)
532 if(S_ISREG(statbuf_lnk.st_mode))
534 if(sha1sum || md5sum)
536 /* Generating checksums of the file. */
537 if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
539 strncpy(sf_sum, "xxx", 4);
540 strncpy(mf_sum, "xxx", 4);
550 /* chris: changed st_size int to long */
551 snprintf(newsum,255,"%ld:%d:%d:%d:%s:%s",
552 size == 0?0:(long)statbuf.st_size,
553 perm == 0?0:(int)statbuf.st_mode,
554 owner== 0?0:(int)statbuf.st_uid,
555 group== 0?0:(int)statbuf.st_gid,
556 md5sum == 0?"xxx":mf_sum,
557 sha1sum == 0?"xxx":sf_sum);