1 /* Copyright (C) 2009 Trend Micro Inc.
2 * All rights reserved.
3 *
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
7 * Foundation.
8 */
9
10 /* Syscheck
11 * Copyright (C) 2003 Daniel B. Cid <daniel@underlinux.com.br>
12 */
13
14 #include "shared.h"
15 #include "syscheck.h"
16 #include "rootcheck/rootcheck.h"
17
18 /* Prototypes */
19 static void read_internal(int debug_level);
20 #ifndef WIN32
21 static void help_syscheckd(void) __attribute__((noreturn));
22 #endif
23
24 syscheck_config syscheck;
25
26 #ifdef USE_MAGIC
27 #include <magic.h>
28 magic_t magic_cookie = 0;
29
30
init_magic(magic_t * cookie_ptr)31 void init_magic(magic_t *cookie_ptr)
32 {
33 if (!cookie_ptr || *cookie_ptr) {
34 return;
35 }
36
37 *cookie_ptr = magic_open(MAGIC_MIME_TYPE);
38
39 if (!*cookie_ptr) {
40 const char *err = magic_error(*cookie_ptr);
41 merror("%s: ERROR: Can't init libmagic: %s", ARGV0, err ? err : "unknown");
42 } else if (magic_load(*cookie_ptr, NULL) < 0) {
43 const char *err = magic_error(*cookie_ptr);
44 merror("%s: ERROR: Can't load magic file: %s", ARGV0, err ? err : "unknown");
45 magic_close(*cookie_ptr);
46 *cookie_ptr = 0;
47 }
48 }
49 #endif /* USE_MAGIC */
50
51 /* Read syscheck internal options */
read_internal(int debug_level)52 static void read_internal(int debug_level)
53 {
54 syscheck.tsleep = (unsigned int) getDefine_Int("syscheck", "sleep", 0, 64);
55 syscheck.sleep_after = getDefine_Int("syscheck", "sleep_after", 1, 9999);
56
57 /* Check current debug_level
58 * Command line setting takes precedence
59 */
60 if (debug_level == 0) {
61 debug_level = getDefine_Int("syscheck", "debug", 0, 2);
62 while (debug_level != 0) {
63 nowDebug();
64 debug_level--;
65 }
66 }
67
68 return;
69 }
70
71 #ifdef WIN32
72 /* syscheck main for Windows */
Start_win32_Syscheck()73 int Start_win32_Syscheck()
74 {
75 int debug_level = 0;
76 int r = 0;
77 char *cfg = DEFAULTCPATH;
78
79 /* Read internal options */
80 read_internal(debug_level);
81
82 debug1(STARTED_MSG, ARGV0);
83
84 /* Check if the configuration is present */
85 if (File_DateofChange(cfg) < 0) {
86 ErrorExit(NO_CONFIG, ARGV0, cfg);
87 }
88
89 /* Read syscheck config */
90 if ((r = Read_Syscheck_Config(cfg)) < 0) {
91 ErrorExit(CONFIG_ERROR, ARGV0, cfg);
92 } else if ((r == 1) || (syscheck.disabled == 1)) {
93 /* Disabled */
94 if (!syscheck.dir) {
95 merror(SK_NO_DIR, ARGV0);
96 dump_syscheck_entry(&syscheck, "", 0, 0, NULL);
97 } else if (!syscheck.dir[0]) {
98 merror(SK_NO_DIR, ARGV0);
99 }
100 syscheck.dir[0] = NULL;
101
102 if (!syscheck.registry) {
103 dump_syscheck_entry(&syscheck, "", 0, 1, NULL);
104 }
105 syscheck.registry[0] = NULL;
106
107 merror("%s: WARN: Syscheck disabled.", ARGV0);
108 }
109
110 /* Rootcheck config */
111 if (rootcheck_init(0) == 0) {
112 syscheck.rootcheck = 1;
113 } else {
114 syscheck.rootcheck = 0;
115 merror("%s: WARN: Rootcheck module disabled.", ARGV0);
116 }
117
118 /* Print options */
119 r = 0;
120 while (syscheck.registry[r] != NULL) {
121 verbose("%s: INFO: Monitoring registry entry: '%s'.",
122 ARGV0, syscheck.registry[r]);
123 r++;
124 }
125
126 /* Print directories to be monitored */
127 r = 0;
128 while (syscheck.dir[r] != NULL) {
129 char optstr[ 100 ];
130 verbose("%s: INFO: Monitoring directory: '%s', with options %s.",
131 ARGV0, syscheck.dir[r],
132 syscheck_opts2str(optstr, sizeof( optstr ), syscheck.opts[r]));
133 r++;
134 }
135
136 /* Print ignores. */
137 if(syscheck.ignore)
138 for (r = 0; syscheck.ignore[r] != NULL; r++)
139 verbose("%s: INFO: ignoring: '%s'",
140 ARGV0, syscheck.ignore[r]);
141
142
143 /* Print files with no diff. */
144 if (syscheck.nodiff){
145 r = 0;
146 while (syscheck.nodiff[r] != NULL) {
147 verbose("%s: INFO: No diff for file: '%s'",
148 ARGV0, syscheck.nodiff[r]);
149 r++;
150 }
151 }
152
153 /* Start up message */
154 verbose(STARTUP_MSG, ARGV0, getpid());
155
156 /* Some sync time */
157 sleep(syscheck.tsleep + 10);
158
159 /* Wait if agent started properly */
160 os_wait();
161
162 start_daemon();
163
164 exit(0);
165 }
166 #endif /* WIN32 */
167
168 #ifndef WIN32
169 /* Print help statement */
help_syscheckd()170 static void help_syscheckd()
171 {
172 print_header();
173 print_out(" %s: -[Vhdtf] [-c config]", ARGV0);
174 print_out(" -V Version and license message");
175 print_out(" -h This help message");
176 print_out(" -d Execute in debug mode. This parameter");
177 print_out(" can be specified multiple times");
178 print_out(" to increase the debug level.");
179 print_out(" -t Test configuration");
180 print_out(" -f Run in foreground");
181 print_out(" -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
182 print_out(" ");
183 exit(1);
184 }
185
186 /* Syscheck unix main */
main(int argc,char ** argv)187 int main(int argc, char **argv)
188 {
189 int c, r;
190 int debug_level = 0;
191 int test_config = 0, run_foreground = 0;
192 const char *cfg = DEFAULTCPATH;
193
194 /* Set the name */
195 OS_SetName(ARGV0);
196
197 while ((c = getopt(argc, argv, "Vtdhfc:")) != -1) {
198 switch (c) {
199 case 'V':
200 print_version();
201 break;
202 case 'h':
203 help_syscheckd();
204 break;
205 case 'd':
206 nowDebug();
207 debug_level ++;
208 break;
209 case 'f':
210 run_foreground = 1;
211 break;
212 case 'c':
213 if (!optarg) {
214 ErrorExit("%s: -c needs an argument", ARGV0);
215 }
216 cfg = optarg;
217 break;
218 case 't':
219 test_config = 1;
220 break;
221 default:
222 help_syscheckd();
223 break;
224 }
225 }
226
227 /* Read internal options */
228 read_internal(debug_level);
229
230 debug1(STARTED_MSG, ARGV0);
231
232 /* Check if the configuration is present */
233 if (File_DateofChange(cfg) < 0) {
234 ErrorExit(NO_CONFIG, ARGV0, cfg);
235 }
236
237 /* Read syscheck config */
238 if ((r = Read_Syscheck_Config(cfg)) < 0) {
239 ErrorExit(CONFIG_ERROR, ARGV0, cfg);
240 } else if ((r == 1) || (syscheck.disabled == 1)) {
241 if (!syscheck.dir) {
242 if (!test_config) {
243 merror(SK_NO_DIR, ARGV0);
244 }
245 dump_syscheck_entry(&syscheck, "", 0, 0, NULL);
246 } else if (!syscheck.dir[0]) {
247 if (!test_config) {
248 merror(SK_NO_DIR, ARGV0);
249 }
250 }
251 syscheck.dir[0] = NULL;
252 if (!test_config) {
253 merror("%s: WARN: Syscheck disabled.", ARGV0);
254 }
255 }
256
257 /* Rootcheck config */
258 if (rootcheck_init(test_config) == 0) {
259 syscheck.rootcheck = 1;
260 } else {
261 syscheck.rootcheck = 0;
262 merror("%s: WARN: Rootcheck module disabled.", ARGV0);
263 }
264
265 /* Exit if testing config */
266 if (test_config) {
267 exit(0);
268 }
269
270 /* Setup libmagic */
271 #ifdef USE_MAGIC
272 init_magic(&magic_cookie);
273 #endif
274
275 if (!run_foreground) {
276 nowDaemon();
277 goDaemon();
278 }
279
280 /* Initial time to settle */
281 sleep(syscheck.tsleep + 2);
282
283 /* Connect to the queue */
284 if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
285 merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno));
286
287 sleep(5);
288 if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
289 /* more 10 seconds of wait */
290 merror(QUEUE_ERROR, ARGV0, DEFAULTQPATH, strerror(errno));
291 sleep(10);
292 if ((syscheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
293 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
294 }
295 }
296 }
297
298 /* Start signal handling */
299 StartSIG(ARGV0);
300
301 /* Create pid */
302 if (CreatePID(ARGV0, getpid()) < 0) {
303 merror(PID_ERROR, ARGV0);
304 }
305
306 /* Start up message */
307 verbose(STARTUP_MSG, ARGV0, (int)getpid());
308
309 if (syscheck.rootcheck) {
310 verbose(STARTUP_MSG, "ossec-rootcheck", (int)getpid());
311 }
312
313 /* Print directories to be monitored */
314 r = 0;
315 while (syscheck.dir[r] != NULL) {
316 char optstr[ 100 ];
317 verbose("%s: INFO: Monitoring directory: '%s', with options %s.",
318 ARGV0, syscheck.dir[r],
319 syscheck_opts2str(optstr, sizeof( optstr ), syscheck.opts[r]));
320 r++;
321 }
322
323 /* Print ignores. */
324 if(syscheck.ignore)
325 for (r = 0; syscheck.ignore[r] != NULL; r++)
326 verbose("%s: INFO: ignoring: '%s'",
327 ARGV0, syscheck.ignore[r]);
328
329 /* Print files with no diff. */
330 if (syscheck.nodiff){
331 r = 0;
332 while (syscheck.nodiff[r] != NULL) {
333 verbose("%s: INFO: No diff for file: '%s'",
334 ARGV0, syscheck.nodiff[r]);
335 r++;
336 }
337 }
338
339 /* Check directories set for real time */
340 r = 0;
341 while (syscheck.dir[r] != NULL) {
342 if (syscheck.opts[r] & CHECK_REALTIME) {
343 #ifdef INOTIFY_ENABLED
344 verbose("%s: INFO: Directory set for real time monitoring: "
345 "'%s'.", ARGV0, syscheck.dir[r]);
346 #elif defined(WIN32)
347 verbose("%s: INFO: Directory set for real time monitoring: "
348 "'%s'.", ARGV0, syscheck.dir[r]);
349 #else
350 verbose("%s: WARN: Ignoring flag for real time monitoring on "
351 "directory: '%s'.", ARGV0, syscheck.dir[r]);
352 #endif
353 }
354 r++;
355 }
356
357 /* Some sync time */
358 sleep(syscheck.tsleep + 10);
359
360 /* Start the daemon */
361 start_daemon();
362 }
363
364 #endif /* !WIN32 */
365
366