1 /* @(#) $Id: create_db.c,v 1.28 2009/10/02 19:28:34 dcid Exp $ */
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 3) 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"
23 /* flags for read_dir and read_file */
30 int read_dir(char *dir_name, int opts, int flag);
33 /* int check_file(char *file_name)
34 * Checks if the file is already in the database.
36 int check_file(char *file_name)
38 char buf[MAX_LINE +2];
39 buf[MAX_LINE +1] = '\0';
41 while(fgets(buf, MAX_LINE, syscheck.fp) != NULL)
43 if((buf[0] != '#') && (buf[0] != ' ') && (buf[0] != '\n'))
47 /* Removing the new line */
48 n_buf = strchr(buf,'\n');
55 /* First 6 characters are for internal use */
59 n_buf = strchr(n_buf, ' ');
64 /* Checking if name matches */
65 if(strcmp(n_buf, file_name) == 0)
74 debug2("%s: DEBUG: new file '%s'.", ARGV0, file_name);
80 /* int read_file(char *file_name, int opts, int flag)
81 * Reads and generates the integrity data of a file.
83 int read_file(char *file_name, int opts, int flag)
85 int check_file_new = 0;
88 /* Checking if file is to be ignored */
92 while(syscheck.ignore[i] != NULL)
94 if(strncasecmp(syscheck.ignore[i], file_name,
95 strlen(syscheck.ignore[i])) == 0)
104 /* Checking in the regex entry */
105 if(syscheck.ignore_regex)
108 while(syscheck.ignore_regex[i] != NULL)
110 if(OSMatch_Execute(file_name, strlen(file_name),
111 syscheck.ignore_regex[i]))
120 /* Win32 does not have lstat */
122 if(stat(file_name, &statbuf) < 0)
124 if(lstat(file_name, &statbuf) < 0)
127 merror("%s: Error accessing '%s'.",ARGV0, file_name);
131 if(S_ISDIR(statbuf.st_mode))
134 verbose("%s: Reading dir: %s\n",ARGV0, file_name);
137 return(read_dir(file_name, opts, flag));
141 /* No S_ISLNK on windows */
143 else if(S_ISREG(statbuf.st_mode))
145 else if(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
152 /* If check_db, we just need to verify that the file is
153 * already present. If not, we add it.
157 /* File in the database already */
158 fseek(syscheck.fp, 0, SEEK_SET);
159 if(check_file(file_name))
161 /* Sleeping in here too */
163 if(__counter >= (3 * syscheck.sleep_after))
165 if(__counter >= (syscheck.sleep_after))
168 sleep(syscheck.tsleep);
175 fseek(syscheck.fp, 0, SEEK_END);
181 strncpy(mf_sum, "xxx", 4);
182 strncpy(sf_sum, "xxx", 4);
185 /* Generating checksums. */
186 if((opts & CHECK_MD5SUM) || (opts & CHECK_SHA1SUM))
188 /* If it is a link, we need to check if dest is valid. */
190 if(S_ISLNK(statbuf.st_mode))
192 struct stat statbuf_lnk;
193 if(stat(file_name, &statbuf_lnk) == 0)
195 if(S_ISREG(statbuf_lnk.st_mode))
197 if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
199 strncpy(mf_sum, "xxx", 4);
200 strncpy(sf_sum, "xxx", 4);
205 else if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
208 if(OS_MD5_SHA1_File(file_name, mf_sum, sf_sum) < 0)
212 strncpy(mf_sum, "xxx", 4);
213 strncpy(sf_sum, "xxx", 4);
219 fprintf(syscheck.fp,"%c%c%c%c%c%c%d:%d:%d:%d:%s:%s %s\n",
220 opts & CHECK_SIZE?'+':'-',
221 opts & CHECK_PERM?'+':'-',
222 opts & CHECK_OWNER?'+':'-',
223 opts & CHECK_GROUP?'+':'-',
224 opts & CHECK_MD5SUM?'+':'-',
225 opts & CHECK_SHA1SUM?'+':'-',
226 opts & CHECK_SIZE?(int)statbuf.st_size:0,
227 opts & CHECK_PERM?(int)statbuf.st_mode:0,
228 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
229 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
230 opts & CHECK_MD5SUM?mf_sum:"xxx",
231 opts & CHECK_SHA1SUM?sf_sum:"xxx",
238 char alert_msg[912 +2];
240 /* Sending the new checksum to the analysis server */
241 alert_msg[912 +1] = '\0';
242 snprintf(alert_msg, 912, "%d:%d:%d:%d:%s:%s %s",
243 opts & CHECK_SIZE?(int)statbuf.st_size:0,
244 opts & CHECK_PERM?(int)statbuf.st_mode:0,
245 opts & CHECK_OWNER?(int)statbuf.st_uid:0,
246 opts & CHECK_GROUP?(int)statbuf.st_gid:0,
247 opts & CHECK_MD5SUM?mf_sum:"xxx",
248 opts & CHECK_SHA1SUM?sf_sum:"xxx",
250 send_syscheck_msg(alert_msg);
254 /* Sleeping in here too */
256 if(__counter >= (3 * syscheck.sleep_after))
258 if(__counter >= (2 * syscheck.sleep_after))
261 sleep(syscheck.tsleep);
268 verbose("%s: file '%s %s'",ARGV0, file_name, mf_sum);
274 verbose("%s: *** IRREG file: '%s'\n",ARGV0,file_name);
285 int read_dir(char *dir_name, int opts, int flag)
289 char f_name[PATH_MAX +2];
292 struct dirent *entry;
294 f_name[PATH_MAX +1] = '\0';
297 /* Directory should be valid */
298 if((dir_name == NULL)||((dir_size = strlen(dir_name)) > PATH_MAX))
300 if(flag == CREATE_DB)
301 merror(NULL_ERROR, ARGV0);
307 /* Opening the directory given */
308 dp = opendir(dir_name);
313 if(read_file(dir_name, opts, flag) == 0)
317 if(flag == CREATE_DB)
321 char *(defaultfilesn[])= {
324 "C:\\WINDOWS/System32/eventcreate.exe",
325 "C:\\WINDOWS/System32/eventtriggers.exe",
326 "C:\\WINDOWS/System32/tlntsvr.exe",
327 "C:\\WINDOWS/System32/Tasks",
330 while(defaultfilesn[di] != NULL)
332 if(strcmp(defaultfilesn[di], dir_name) == 0)
339 if(defaultfilesn[di] == NULL)
341 merror("%s: WARN: Error opening directory: '%s': %s ",
342 ARGV0, dir_name, strerror(errno));
347 merror("%s: WARN: Error opening directory: '%s': %s ",
358 /* Checking for real time flag. */
359 if(opts & CHECK_REALTIME)
362 realtime_adddir(dir_name);
367 while((entry = readdir(dp)) != NULL)
371 /* Just ignore . and .. */
372 if((strcmp(entry->d_name,".") == 0) ||
373 (strcmp(entry->d_name,"..") == 0))
376 strncpy(f_name, dir_name, PATH_MAX);
383 /* checking if the file name is already null terminated */
384 if(*(s_name-1) != '/')
389 strncpy(s_name, entry->d_name, PATH_MAX - dir_size -2);
390 read_file(f_name, opts, flag);
399 * Checks database for new files.
405 /* Read all available directories */
409 read_dir(syscheck.dir[i], syscheck.opts[i], CHECK_DB);
411 }while(syscheck.dir[i] != NULL);
419 * Creates the file database.
421 int create_db(int delete_db)
425 syscheck.fp = fopen(syscheck.db, "w+"); /* Read and write */
428 ErrorExit("%s: Unable to create syscheck database "
429 "at '%s'. Exiting.",ARGV0,syscheck.db);
434 /* Creating a local fp only */
441 /* dir_name can't be null */
442 if((syscheck.dir == NULL) || (syscheck.dir[0] == NULL))
444 merror("%s: No directories to check.",ARGV0);
449 merror("%s: INFO: Starting syscheck database (pre-scan).", ARGV0);
452 /* Read all available directories */
456 if(read_dir(syscheck.dir[i], syscheck.opts[i], CREATE_DB) == 0)
459 if(syscheck.opts[i] & CHECK_REALTIME)
461 realtime_adddir(syscheck.dir[i]);
466 }while(syscheck.dir[i] != NULL);
469 merror("%s: INFO: Finished creating syscheck database (pre-scan "
470 "completed).", ARGV0);