1 /* @(#) $Id: ./src/syscheckd/create_db.c, 2011/11/02 dcid Exp $
4 /* Copyright (C) 2009 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
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/en/licensing.html
19 #include "os_crypto/md5/md5_op.h"
20 #include "os_crypto/sha1/sha1_op.h"
21 #include "os_crypto/md5_sha1/md5_sha1_op.h"
28 int read_dir(char *dir_name, int opts, OSMatch *restriction);
31 /* int check_file(char *file_name)
32 * Checks if the file is already in the database.
34 int check_file(char *file_name)
36 if(OSHash_Get(syscheck.fp, file_name))
44 debug2("%s: DEBUG: new file '%s'.", ARGV0, file_name);
50 /* int read_file(char *file_name, int opts, int flag)
51 * Reads and generates the integrity data of a file.
53 int read_file(char *file_name, int opts, OSMatch *restriction)
60 /* Checking if file is to be ignored */
64 while(syscheck.ignore[i] != NULL)
66 if(strncasecmp(syscheck.ignore[i], file_name,
67 strlen(syscheck.ignore[i])) == 0)
76 /* Checking in the regex entry */
77 if(syscheck.ignore_regex)
80 while(syscheck.ignore_regex[i] != NULL)
82 if(OSMatch_Execute(file_name, strlen(file_name),
83 syscheck.ignore_regex[i]))
92 /* Win32 does not have lstat */
94 if(stat(file_name, &statbuf) < 0)
96 if(lstat(file_name, &statbuf) < 0)
99 merror("%s: Error accessing '%s'.",ARGV0, file_name);
103 if(S_ISDIR(statbuf.st_mode))
106 verbose("%s: Reading dir: %s\n",ARGV0, file_name);
109 return(read_dir(file_name, opts, restriction));
113 /* restricting file types. */
116 if(!OSMatch_Execute(file_name, strlen(file_name),
124 /* No S_ISLNK on windows */
126 if(S_ISREG(statbuf.st_mode))
128 if(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
138 strncpy(mf_sum, "xxx", 4);
139 strncpy(sf_sum, "xxx", 4);
140 strncpy(sf_sum2, "xxx", 4);
141 strncpy(sf_sum3, "xxx", 4);
144 /* Generating checksums. */
145 if((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM))
147 /* If it is a link, we need to check if dest is valid. */
149 if(S_ISLNK(statbuf.st_mode))
151 struct stat statbuf_lnk;
152 if(stat(file_name, &statbuf_lnk) == 0)
154 if(S_ISREG(statbuf_lnk.st_mode))
156 if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
158 strncpy(mf_sum, "xxx", 4);
159 strncpy(sf_sum, "xxx", 4);
164 else if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
167 if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
171 strncpy(mf_sum, "xxx", 4);
172 strncpy(sf_sum, "xxx", 4);
176 if(opts & CHECK_SEECHANGES)
183 if(opts & CHECK_SEECHANGES)
190 buf = OSHash_Get(syscheck.fp, file_name);
193 char alert_msg[912 +1];
195 alert_msg[912] = '\0';
197 if(opts & CHECK_SEECHANGES)
199 char *alertdump = seechanges_addfile(file_name);
208 snprintf(alert_msg, 912, "%c%c%c%c%c%c%d:%d:%d:%d:%s:%s",
209 opts & CHECK_SIZE?'+':'-',
210 opts & CHECK_PERM?'+':'-',
211 opts & CHECK_OWNER?'+':'-',
212 opts & CHECK_GROUP?'+':'-',
213 opts & CHECK_MD5SUM?'+':'-',
215 opts & CHECK_SIZE?(int)statbuf.st_size:0,
216 opts & CHECK_PERM?(int)statbuf.st_mode:0,
217 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
218 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
219 opts & CHECK_MD5SUM?mf_sum:"xxx",
220 opts & CHECK_SHA1SUM?sf_sum:"xxx");
222 if(OSHash_Add(syscheck.fp, strdup(file_name), strdup(alert_msg)) <= 0)
224 merror("%s: ERROR: Unable to add file to db: %s", ARGV0, file_name);
228 /* Sending the new checksum to the analysis server */
229 alert_msg[912] = '\0';
230 snprintf(alert_msg, 912, "%d:%d:%d:%d:%s:%s %s",
231 opts & CHECK_SIZE?(int)statbuf.st_size:0,
232 opts & CHECK_PERM?(int)statbuf.st_mode:0,
233 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
234 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
235 opts & CHECK_MD5SUM?mf_sum:"xxx",
236 opts & CHECK_SHA1SUM?sf_sum:"xxx",
238 send_syscheck_msg(alert_msg);
242 char alert_msg[OS_MAXSTR +1];
248 alert_msg[OS_MAXSTR] = '\0';
250 /* If it returns < 0, we will already have alerted. */
251 if(c_read_file(file_name, buf, c_sum) < 0)
254 if(strcmp(c_sum, buf+6) != 0)
256 /* Sending the new checksum to the analysis server */
257 char *fullalert = NULL;
258 alert_msg[OS_MAXSTR] = '\0';
259 if(buf[5] == 's' || buf[5] == 'n')
261 fullalert = seechanges_addfile(file_name);
264 snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
270 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
275 snprintf(alert_msg, 912, "%s %s", c_sum, file_name);
277 send_syscheck_msg(alert_msg);
282 /* Sleeping in here too */
283 if(__counter >= (syscheck.sleep_after))
285 sleep(syscheck.tsleep);
292 verbose("%s: file '%s %s'",ARGV0, file_name, mf_sum);
298 verbose("%s: *** IRREG file: '%s'\n",ARGV0,file_name);
309 int read_dir(char *dir_name, int opts, OSMatch *restriction)
313 char f_name[PATH_MAX +2];
316 struct dirent *entry;
318 f_name[PATH_MAX +1] = '\0';
321 /* Directory should be valid */
322 if((dir_name == NULL)||((dir_size = strlen(dir_name)) > PATH_MAX))
324 merror(NULL_ERROR, ARGV0);
330 /* Opening the directory given */
331 dp = opendir(dir_name);
336 if(read_file(dir_name, opts, restriction) == 0)
342 char *(defaultfilesn[])= {
345 "C:\\WINDOWS/System32/eventcreate.exe",
346 "C:\\WINDOWS/System32/eventtriggers.exe",
347 "C:\\WINDOWS/System32/tlntsvr.exe",
348 "C:\\WINDOWS/System32/Tasks",
351 while(defaultfilesn[di] != NULL)
353 if(strcmp(defaultfilesn[di], dir_name) == 0)
360 if(defaultfilesn[di] == NULL)
362 merror("%s: WARN: Error opening directory: '%s': %s ",
363 ARGV0, dir_name, strerror(errno));
368 merror("%s: WARN: Error opening directory: '%s': %s ",
378 /* Checking for real time flag. */
379 if(opts & CHECK_REALTIME)
382 realtime_adddir(dir_name);
387 while((entry = readdir(dp)) != NULL)
391 /* Just ignore . and .. */
392 if((strcmp(entry->d_name,".") == 0) ||
393 (strcmp(entry->d_name,"..") == 0))
396 strncpy(f_name, dir_name, PATH_MAX);
403 /* checking if the file name is already null terminated */
404 if(*(s_name-1) != '/')
409 strncpy(s_name, entry->d_name, PATH_MAX - dir_size -2);
411 /* Check integrity of the file */
412 read_file(f_name, opts, restriction);
420 /* int run_dbcheck */
426 while(syscheck.dir[i] != NULL)
428 read_dir(syscheck.dir[i], syscheck.opts[i], syscheck.filerestrict[i]);
437 * Creates the file database.
443 /* Creating store data */
444 syscheck.fp = OSHash_Create();
447 ErrorExit("%s: Unable to create syscheck database."
452 if(!OSHash_setSize(syscheck.fp, 2048))
454 merror(LIST_ERROR, ARGV0);
459 /* dir_name can't be null */
460 if((syscheck.dir == NULL) || (syscheck.dir[0] == NULL))
462 merror("%s: No directories to check.",ARGV0);
467 merror("%s: INFO: Starting syscheck database (pre-scan).", ARGV0);
470 /* Read all available directories */
474 if(read_dir(syscheck.dir[i], syscheck.opts[i], syscheck.filerestrict[i]) == 0)
477 if(syscheck.opts[i] & CHECK_REALTIME)
479 realtime_adddir(syscheck.dir[i]);
484 }while(syscheck.dir[i] != NULL);
486 #if defined (USEINOTIFY) || defined (WIN32)
487 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
488 verbose("%s: INFO: Real time file monitoring started.", ARGV0);
491 merror("%s: INFO: Finished creating syscheck database (pre-scan "
492 "completed).", ARGV0);