3 /* Copyright (C) 2009 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
11 * License details at the LICENSE file included with OSSEC or
12 * online at: http://www.ossec.net/en/licensing.html
18 #include "os_crypto/md5/md5_op.h"
19 #include "os_crypto/sha1/sha1_op.h"
20 #include "os_crypto/md5_sha1/md5_sha1_op.h"
27 int read_dir(char *dir_name, int opts, OSMatch *restriction);
30 /* int check_file(char *file_name)
31 * Checks if the file is already in the database.
33 int check_file(char *file_name)
35 if(OSHash_Get(syscheck.fp, file_name))
43 debug2("%s: DEBUG: new file '%s'.", ARGV0, file_name);
49 /* int read_file(char *file_name, int opts, int flag)
50 * Reads and generates the integrity data of a file.
52 int read_file(char *file_name, int opts, OSMatch *restriction)
59 /* Checking if file is to be ignored */
63 while(syscheck.ignore[i] != NULL)
65 if(strncasecmp(syscheck.ignore[i], file_name,
66 strlen(syscheck.ignore[i])) == 0)
75 /* Checking in the regex entry */
76 if(syscheck.ignore_regex)
79 while(syscheck.ignore_regex[i] != NULL)
81 if(OSMatch_Execute(file_name, strlen(file_name),
82 syscheck.ignore_regex[i]))
91 /* Win32 does not have lstat */
93 if(stat(file_name, &statbuf) < 0)
95 if(lstat(file_name, &statbuf) < 0)
98 merror("%s: Error accessing '%s'.",ARGV0, file_name);
102 if(S_ISDIR(statbuf.st_mode))
105 verbose("%s: Reading dir: %s\n",ARGV0, file_name);
108 return(read_dir(file_name, opts, restriction));
112 /* restricting file types. */
115 if(!OSMatch_Execute(file_name, strlen(file_name),
123 /* No S_ISLNK on windows */
125 else if(S_ISREG(statbuf.st_mode))
127 else if(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
137 strncpy(mf_sum, "xxx", 4);
138 strncpy(sf_sum, "xxx", 4);
139 strncpy(sf_sum2, "xxx", 4);
140 strncpy(sf_sum3, "xxx", 4);
143 /* Generating checksums. */
144 if((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM))
146 /* If it is a link, we need to check if dest is valid. */
148 if(S_ISLNK(statbuf.st_mode))
150 struct stat statbuf_lnk;
151 if(stat(file_name, &statbuf_lnk) == 0)
153 if(S_ISREG(statbuf_lnk.st_mode))
155 if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
157 strncpy(mf_sum, "xxx", 4);
158 strncpy(sf_sum, "xxx", 4);
163 else if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
166 if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
170 strncpy(mf_sum, "xxx", 4);
171 strncpy(sf_sum, "xxx", 4);
175 if(opts & CHECK_SEECHANGES)
182 if(opts & CHECK_SEECHANGES)
189 buf = OSHash_Get(syscheck.fp, file_name);
192 char alert_msg[912 +1];
194 alert_msg[912] = '\0';
196 if(opts & CHECK_SEECHANGES)
198 char *alertdump = seechanges_addfile(file_name);
207 snprintf(alert_msg, 912, "%c%c%c%c%c%c%d:%d:%d:%d:%s:%s",
208 opts & CHECK_SIZE?'+':'-',
209 opts & CHECK_PERM?'+':'-',
210 opts & CHECK_OWNER?'+':'-',
211 opts & CHECK_GROUP?'+':'-',
212 opts & CHECK_MD5SUM?'+':'-',
214 opts & CHECK_SIZE?(int)statbuf.st_size:0,
215 opts & CHECK_PERM?(int)statbuf.st_mode:0,
216 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
217 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
218 opts & CHECK_MD5SUM?mf_sum:"xxx",
219 opts & CHECK_SHA1SUM?sf_sum:"xxx");
221 if(OSHash_Add(syscheck.fp, strdup(file_name), strdup(alert_msg)) <= 0)
223 merror("%s: ERROR: Unable to add file to db: %s", ARGV0, file_name);
227 /* Sending the new checksum to the analysis server */
228 alert_msg[912 +1] = '\0';
229 snprintf(alert_msg, 912, "%d:%d:%d:%d:%s:%s %s",
230 opts & CHECK_SIZE?(int)statbuf.st_size:0,
231 opts & CHECK_PERM?(int)statbuf.st_mode:0,
232 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
233 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
234 opts & CHECK_MD5SUM?mf_sum:"xxx",
235 opts & CHECK_SHA1SUM?sf_sum:"xxx",
237 send_syscheck_msg(alert_msg);
241 char alert_msg[OS_MAXSTR +1];
247 alert_msg[OS_MAXSTR] = '\0';
249 /* If it returns < 0, we will already have alerted. */
250 if(c_read_file(file_name, buf, c_sum) < 0)
253 if(strcmp(c_sum, buf+6) != 0)
255 /* Sending the new checksum to the analysis server */
256 char *fullalert = NULL;
257 alert_msg[OS_MAXSTR] = '\0';
258 if(buf[5] == 's' || buf[5] == 'n')
260 fullalert = seechanges_addfile(file_name);
263 snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
269 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
274 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
276 send_syscheck_msg(alert_msg);
281 /* Sleeping in here too */
282 if(__counter >= (syscheck.sleep_after))
284 sleep(syscheck.tsleep);
291 verbose("%s: file '%s %s'",ARGV0, file_name, mf_sum);
297 verbose("%s: *** IRREG file: '%s'\n",ARGV0,file_name);
308 int read_dir(char *dir_name, int opts, OSMatch *restriction)
312 char f_name[PATH_MAX +2];
315 struct dirent *entry;
317 f_name[PATH_MAX +1] = '\0';
320 /* Directory should be valid */
321 if((dir_name == NULL)||((dir_size = strlen(dir_name)) > PATH_MAX))
323 merror(NULL_ERROR, ARGV0);
329 /* Opening the directory given */
330 dp = opendir(dir_name);
335 if(read_file(dir_name, opts, restriction) == 0)
341 char *(defaultfilesn[])= {
344 "C:\\WINDOWS/System32/eventcreate.exe",
345 "C:\\WINDOWS/System32/eventtriggers.exe",
346 "C:\\WINDOWS/System32/tlntsvr.exe",
347 "C:\\WINDOWS/System32/Tasks",
350 while(defaultfilesn[di] != NULL)
352 if(strcmp(defaultfilesn[di], dir_name) == 0)
359 if(defaultfilesn[di] == NULL)
361 merror("%s: WARN: Error opening directory: '%s': %s ",
362 ARGV0, dir_name, strerror(errno));
367 merror("%s: WARN: Error opening directory: '%s': %s ",
377 /* Checking for real time flag. */
378 if(opts & CHECK_REALTIME)
381 realtime_adddir(dir_name);
386 while((entry = readdir(dp)) != NULL)
390 /* Just ignore . and .. */
391 if((strcmp(entry->d_name,".") == 0) ||
392 (strcmp(entry->d_name,"..") == 0))
395 strncpy(f_name, dir_name, PATH_MAX);
402 /* checking if the file name is already null terminated */
403 if(*(s_name-1) != '/')
408 strncpy(s_name, entry->d_name, PATH_MAX - dir_size -2);
409 read_file(f_name, opts, restriction);
417 /* int run_dbcheck */
425 read_dir(syscheck.dir[i], syscheck.opts[i], syscheck.filerestrict[i]);
427 }while(syscheck.dir[i] != NULL);
434 * Creates the file database.
440 /* Creating store data */
441 syscheck.fp = OSHash_Create();
444 ErrorExit("%s: Unable to create syscheck database."
449 if(!OSHash_setSize(syscheck.fp, 2048))
451 merror(LIST_ERROR, ARGV0);
456 /* dir_name can't be null */
457 if((syscheck.dir == NULL) || (syscheck.dir[0] == NULL))
459 merror("%s: No directories to check.",ARGV0);
464 merror("%s: INFO: Starting syscheck database (pre-scan).", ARGV0);
467 /* Read all available directories */
471 if(read_dir(syscheck.dir[i], syscheck.opts[i], syscheck.filerestrict[i]) == 0)
474 if(syscheck.opts[i] & CHECK_REALTIME)
476 realtime_adddir(syscheck.dir[i]);
481 }while(syscheck.dir[i] != NULL);
484 merror("%s: INFO: Finished creating syscheck database (pre-scan "
485 "completed).", ARGV0);