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);
110 /* Directory links are not supported */
111 if (GetFileAttributes(file_name) & FILE_ATTRIBUTE_REPARSE_POINT) {
112 merror("%s: WARN: Links are not supported: '%s'", ARGV0, file_name);
116 return(read_dir(file_name, opts, restriction));
120 /* restricting file types. */
123 if(!OSMatch_Execute(file_name, strlen(file_name),
131 /* No S_ISLNK on windows */
133 if(S_ISREG(statbuf.st_mode))
135 if(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
145 strncpy(mf_sum, "xxx", 4);
146 strncpy(sf_sum, "xxx", 4);
147 strncpy(sf_sum2, "xxx", 4);
148 strncpy(sf_sum3, "xxx", 4);
151 /* Generating checksums. */
152 if((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM))
154 /* If it is a link, we need to check if dest is valid. */
156 if(S_ISLNK(statbuf.st_mode))
158 struct stat statbuf_lnk;
159 if(stat(file_name, &statbuf_lnk) == 0)
161 if(S_ISREG(statbuf_lnk.st_mode))
163 if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
165 strncpy(mf_sum, "xxx", 4);
166 strncpy(sf_sum, "xxx", 4);
171 else if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
174 if(OS_MD5_SHA1_File(file_name, syscheck.prefilter_cmd, mf_sum, sf_sum) < 0)
178 strncpy(mf_sum, "xxx", 4);
179 strncpy(sf_sum, "xxx", 4);
183 if(opts & CHECK_SEECHANGES)
190 if(opts & CHECK_SEECHANGES)
197 buf = OSHash_Get(syscheck.fp, file_name);
200 char alert_msg[916 +1]; /* 912 -> 916 to accommodate a long */
202 alert_msg[916] = '\0';
205 if(opts & CHECK_SEECHANGES)
207 char *alertdump = seechanges_addfile(file_name);
217 snprintf(alert_msg, 916, "%c%c%c%c%c%c%ld:%d:%d:%d:%s:%s",
218 opts & CHECK_SIZE?'+':'-',
219 opts & CHECK_PERM?'+':'-',
220 opts & CHECK_OWNER?'+':'-',
221 opts & CHECK_GROUP?'+':'-',
222 opts & CHECK_MD5SUM?'+':'-',
224 opts & CHECK_SIZE?(long)statbuf.st_size:0,
225 opts & CHECK_PERM?(int)statbuf.st_mode:0,
226 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
227 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
228 opts & CHECK_MD5SUM?mf_sum:"xxx",
229 opts & CHECK_SHA1SUM?sf_sum:"xxx");
231 if(OSHash_Add(syscheck.fp, strdup(file_name), strdup(alert_msg)) <= 0)
233 merror("%s: ERROR: Unable to add file to db: %s", ARGV0, file_name);
237 /* Sending the new checksum to the analysis server */
238 alert_msg[916] = '\0';
240 /* changed by chris st_size int to long, 912 to 916*/
241 snprintf(alert_msg, 916, "%ld:%d:%d:%d:%s:%s %s",
242 opts & CHECK_SIZE?(long)statbuf.st_size:0,
243 opts & CHECK_PERM?(int)statbuf.st_mode:0,
244 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
245 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
246 opts & CHECK_MD5SUM?mf_sum:"xxx",
247 opts & CHECK_SHA1SUM?sf_sum:"xxx",
249 send_syscheck_msg(alert_msg);
253 char alert_msg[OS_MAXSTR +1];
259 alert_msg[OS_MAXSTR] = '\0';
261 /* If it returns < 0, we will already have alerted. */
262 if(c_read_file(file_name, buf, c_sum) < 0)
265 if(strcmp(c_sum, buf+6) != 0)
267 /* Sending the new checksum to the analysis server */
268 alert_msg[OS_MAXSTR] = '\0';
270 snprintf(alert_msg, 916, "%s %s", c_sum, file_name);
272 char *fullalert = NULL;
273 if(buf[5] == 's' || buf[5] == 'n')
275 fullalert = seechanges_addfile(file_name);
278 snprintf(alert_msg, OS_MAXSTR, "%s %s\n%s", c_sum, file_name, fullalert);
284 snprintf(alert_msg, 916, "%s %s", c_sum, file_name);
289 snprintf(alert_msg, 916, "%s %s", c_sum, file_name);
292 send_syscheck_msg(alert_msg);
297 /* Sleeping in here too */
298 if(__counter >= (syscheck.sleep_after))
300 sleep(syscheck.tsleep);
307 verbose("%s: file '%s %s'",ARGV0, file_name, mf_sum);
313 verbose("%s: *** IRREG file: '%s'\n",ARGV0,file_name);
324 int read_dir(char *dir_name, int opts, OSMatch *restriction)
328 char f_name[PATH_MAX +2];
331 struct dirent *entry;
333 f_name[PATH_MAX +1] = '\0';
336 /* Directory should be valid */
337 if((dir_name == NULL)||((dir_size = strlen(dir_name)) > PATH_MAX))
339 merror(NULL_ERROR, ARGV0);
345 /* Opening the directory given */
346 dp = opendir(dir_name);
351 if(read_file(dir_name, opts, restriction) == 0)
357 char *(defaultfilesn[])= {
360 "C:\\WINDOWS/System32/eventcreate.exe",
361 "C:\\WINDOWS/System32/eventtriggers.exe",
362 "C:\\WINDOWS/System32/tlntsvr.exe",
363 "C:\\WINDOWS/System32/Tasks",
366 while(defaultfilesn[di] != NULL)
368 if(strcmp(defaultfilesn[di], dir_name) == 0)
375 if(defaultfilesn[di] == NULL)
377 merror("%s: WARN: Error opening directory: '%s': %s ",
378 ARGV0, dir_name, strerror(errno));
383 merror("%s: WARN: Error opening directory: '%s': %s ",
393 /* Checking for real time flag. */
394 if(opts & CHECK_REALTIME)
397 realtime_adddir(dir_name);
402 while((entry = readdir(dp)) != NULL)
406 /* Just ignore . and .. */
407 if((strcmp(entry->d_name,".") == 0) ||
408 (strcmp(entry->d_name,"..") == 0))
411 strncpy(f_name, dir_name, PATH_MAX);
418 /* checking if the file name is already null terminated */
419 if(*(s_name-1) != '/')
424 strncpy(s_name, entry->d_name, PATH_MAX - dir_size -2);
426 /* Check integrity of the file */
427 read_file(f_name, opts, restriction);
435 /* int run_dbcheck */
441 while(syscheck.dir[i] != NULL)
443 read_dir(syscheck.dir[i], syscheck.opts[i], syscheck.filerestrict[i]);
452 * Creates the file database.
458 /* Creating store data */
459 syscheck.fp = OSHash_Create();
462 ErrorExit("%s: Unable to create syscheck database."
467 if(!OSHash_setSize(syscheck.fp, 2048))
469 merror(LIST_ERROR, ARGV0);
474 /* dir_name can't be null */
475 if((syscheck.dir == NULL) || (syscheck.dir[0] == NULL))
477 merror("%s: No directories to check.",ARGV0);
482 merror("%s: INFO: Starting syscheck database (pre-scan).", ARGV0);
485 /* Read all available directories */
489 if(read_dir(syscheck.dir[i], syscheck.opts[i], syscheck.filerestrict[i]) == 0)
492 if(syscheck.opts[i] & CHECK_REALTIME)
494 realtime_adddir(syscheck.dir[i]);
499 }while(syscheck.dir[i] != NULL);
501 #if defined (USEINOTIFY) || defined (WIN32)
502 if(syscheck.realtime && (syscheck.realtime->fd >= 0))
503 verbose("%s: INFO: Real time file monitoring started.", ARGV0);
506 merror("%s: INFO: Finished creating syscheck database (pre-scan "
507 "completed).", ARGV0);