3 /* Copyright (C) 2010 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
13 /* SCHED_BATCH is Linux specific and is only picked up with _GNU_SOURCE */
21 #include "os_crypto/md5/md5_op.h"
22 #include "os_crypto/sha1/sha1_op.h"
23 #include "os_crypto/md5_sha1/md5_sha1_op.h"
25 #include "rootcheck/rootcheck.h"
29 int c_read_file(char *file_name, char *oldsum, char *newsum);
32 /* Send syscheck message.
33 * Send a message related to syscheck change/addition.
35 int send_syscheck_msg(char *msg)
37 if(SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ) < 0)
39 merror(QUEUE_SEND, ARGV0);
41 if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
43 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
46 /* If we reach here, we can try to send it again */
47 SendMSG(syscheck.queue, msg, SYSCHECK, SYSCHECK_MQ);
55 /* Send rootcheck message.
56 * Send a message related to rootcheck change/addition.
58 int send_rootcheck_msg(char *msg)
60 if(SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0)
62 merror(QUEUE_SEND, ARGV0);
64 if((syscheck.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
66 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
69 /* If we reach here, we can try to send it again */
70 SendMSG(syscheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ);
77 /* Sends syscheck db to the server.
81 /* Sending scan start message */
84 merror("%s: INFO: Starting syscheck scan (forwarding database).", ARGV0);
85 send_rootcheck_msg("Starting syscheck scan.");
89 sleep(syscheck.tsleep +10);
96 /* Sending scan ending message */
97 sleep(syscheck.tsleep +10);
101 merror("%s: INFO: Ending syscheck scan (forwarding database).", ARGV0);
102 send_rootcheck_msg("Ending syscheck scan.");
109 * Run periodicaly the integrity checking
116 time_t curr_time = 0;
118 time_t prev_time_rk = 0;
119 time_t prev_time_sk = 0;
126 /* To be used by select. */
128 struct timeval selecttime;
134 * SCHED_BATCH forces the kernel to assume this is a cpu intensive
136 * and gives it a lower priority. This keeps ossec-syscheckd
138 * the interactity of an ssh session when checksumming large files.
139 * This is available in kernel flavors >= 2.6.16
142 struct sched_param pri;
145 pri.sched_priority = 0;
146 status = sched_setscheduler(0, SCHED_BATCH, &pri);
148 debug1("%s: Setting SCHED_BATCH returned: %d", ARGV0, status);
153 verbose("%s: Starting daemon ..",ARGV0);
158 /* Some time to settle */
159 memset(curr_hour, '\0', 12);
160 sleep(syscheck.tsleep * 10);
164 /* If the scan time/day is set, reset the
165 * syscheck.time/rootcheck.time
167 if(syscheck.scan_time || syscheck.scan_day)
169 /* At least once a week. */
170 syscheck.time = 604800;
171 rootcheck.time = 604800;
175 /* Will create the db to store syscheck data */
176 if(syscheck.scan_on_start)
178 sleep(syscheck.tsleep * 15);
183 prev_time_rk = time(0);
188 /* Before entering in daemon mode itself */
189 prev_time_sk = time(0);
190 sleep(syscheck.tsleep * 10);
193 /* If the scan_time or scan_day is set, we need to handle the
194 * current day/time on the loop.
196 if(syscheck.scan_time || syscheck.scan_day)
199 p = localtime(&curr_time);
202 /* Assign hour/min/sec values */
203 snprintf(curr_hour, 9, "%02d:%02d:%02d",
209 curr_day = p->tm_mday;
213 if(syscheck.scan_time && syscheck.scan_day)
215 if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
216 (OS_IsonDay(p->tm_wday, syscheck.scan_day)))
222 else if(syscheck.scan_time)
224 if(OS_IsAfterTime(curr_hour, syscheck.scan_time))
229 else if(syscheck.scan_day)
231 if(OS_IsonDay(p->tm_wday, syscheck.scan_day))
239 #if defined (USEINOTIFY) || defined (WIN32)
240 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
241 verbose("%s: INFO: Starting real time file monitoring.", ARGV0);
245 /* Checking every SYSCHECK_WAIT */
252 /* Checking if syscheck should be restarted, */
253 run_now = os_check_restart_syscheck();
256 /* Checking if a day_time or scan_time is set. */
257 if(syscheck.scan_time || syscheck.scan_day)
259 p = localtime(&curr_time);
263 if(curr_day != p->tm_mday)
266 curr_day = p->tm_mday;
270 /* Checking for the time of the scan. */
271 if(!day_scanned && syscheck.scan_time && syscheck.scan_day)
273 if((OS_IsAfterTime(curr_hour, syscheck.scan_time)) &&
274 (OS_IsonDay(p->tm_wday, syscheck.scan_day)))
281 else if(!day_scanned && syscheck.scan_time)
283 /* Assign hour/min/sec values */
284 snprintf(curr_hour, 9, "%02d:%02d:%02d",
285 p->tm_hour, p->tm_min, p->tm_sec);
287 if(OS_IsAfterTime(curr_hour, syscheck.scan_time))
294 /* Checking for the day of the scan. */
295 else if(!day_scanned && syscheck.scan_day)
297 if(OS_IsonDay(p->tm_wday, syscheck.scan_day))
307 /* If time elapsed is higher than the rootcheck_time,
310 if(syscheck.rootcheck)
312 if(((curr_time - prev_time_rk) > rootcheck.time) || run_now)
315 prev_time_rk = time(0);
320 /* If time elapsed is higher than the syscheck time,
323 if(((curr_time - prev_time_sk) > syscheck.time) || run_now)
325 /* We need to create the db, if scan on start is not set. */
326 if(syscheck.scan_on_start == 0)
328 sleep(syscheck.tsleep * 10);
330 sleep(syscheck.tsleep * 10);
332 syscheck.scan_on_start = 1;
338 /* Sending scan start message */
341 merror("%s: INFO: Starting syscheck scan.", ARGV0);
342 send_rootcheck_msg("Starting syscheck scan.");
347 /* Checking for registry changes on Windows */
352 /* Checking for changes */
357 /* Sending scan ending message */
358 sleep(syscheck.tsleep + 20);
361 merror("%s: INFO: Ending syscheck scan.", ARGV0);
362 send_rootcheck_msg("Ending syscheck scan.");
367 /* Sending database completed message */
368 send_syscheck_msg(HC_SK_DB_COMPLETED);
369 debug2("%s: DEBUG: Sending database completed message.", ARGV0);
372 prev_time_sk = time(0);
377 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
379 selecttime.tv_sec = SYSCHECK_WAIT;
380 selecttime.tv_usec = 0;
382 /* zero-out the fd_set */
385 FD_SET(syscheck.realtime->fd, &rfds);
387 run_now = select(syscheck.realtime->fd + 1, &rfds,
388 NULL, NULL, &selecttime);
391 merror("%s: ERROR: Select failed (for realtime fim).", ARGV0);
392 sleep(SYSCHECK_WAIT);
394 else if(run_now == 0)
398 else if (FD_ISSET (syscheck.realtime->fd, &rfds))
405 sleep(SYSCHECK_WAIT);
409 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
411 run_now = WaitForSingleObjectEx(syscheck.realtime->evt, SYSCHECK_WAIT * 1000, TRUE);
412 if(run_now == WAIT_FAILED)
414 merror("%s: ERROR: WaitForSingleObjectEx failed (for realtime fim).", ARGV0);
415 sleep(SYSCHECK_WAIT);
424 sleep(SYSCHECK_WAIT);
429 sleep(SYSCHECK_WAIT);
438 * Read file information and return a pointer
441 int c_read_file(char *file_name, char *oldsum, char *newsum)
443 int size = 0, perm = 0, owner = 0, group = 0, md5sum = 0, sha1sum = 0, seechanges = 0;
452 strncpy(mf_sum, "xxx", 4);
453 strncpy(sf_sum, "xxx", 4);
457 /* Stating the file */
459 if(stat(file_name, &statbuf) < 0)
461 if(lstat(file_name, &statbuf) < 0)
464 char alert_msg[912 +2];
466 alert_msg[912 +1] = '\0';
467 snprintf(alert_msg, 912,"-1 %s", file_name);
468 send_syscheck_msg(alert_msg);
473 /* Getting the old sum values */
499 else if(oldsum[5] == 's')
504 else if(oldsum[5] == 'n')
511 /* Generating new checksum */
513 if(S_ISREG(statbuf.st_mode))
515 if(S_ISREG(statbuf.st_mode))
518 if(sha1sum || md5sum)
520 /* Generating checksums of the file. */
521 if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
523 strncpy(sf_sum, "xxx", 4);
524 strncpy(mf_sum, "xxx", 4);
529 /* If it is a link, we need to check if the actual file is valid. */
530 else if(S_ISLNK(statbuf.st_mode))
532 struct stat statbuf_lnk;
533 if(stat(file_name, &statbuf_lnk) == 0)
535 if(S_ISREG(statbuf_lnk.st_mode))
537 if(sha1sum || md5sum)
539 /* Generating checksums of the file. */
540 if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
542 strncpy(sf_sum, "xxx", 4);
543 strncpy(mf_sum, "xxx", 4);
553 snprintf(newsum,255,"%d:%d:%d:%d:%s:%s",
554 size == 0?0:(int)statbuf.st_size,
555 perm == 0?0:(int)statbuf.st_mode,
556 owner== 0?0:(int)statbuf.st_uid,
557 group== 0?0:(int)statbuf.st_gid,
558 md5sum == 0?"xxx":mf_sum,
559 sha1sum == 0?"xxx":sf_sum);