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
15 #include "os_crypto/md5/md5_op.h"
16 #include "agentlessd.h"
20 /* Saves agentless entry for the control tools to gather. */
21 int save_agentless_entry(char *host, char *script, char *agttype)
24 char sys_location[1024 +1];
26 sys_location[1024] = '\0';
27 snprintf(sys_location, 1024, "%s/(%s) %s",
28 AGENTLESS_ENTRYDIRPATH, script, host);
30 fp = fopen(sys_location, "w");
33 fprintf(fp, "type: %s\n", agttype);
38 merror(FOPEN_ERROR, ARGV0, sys_location);
46 /* send integrity checking message. */
47 int send_intcheck_msg(char *script, char *host, char *msg)
49 char sys_location[1024 +1];
51 sys_location[1024] = '\0';
52 snprintf(sys_location, 1024, "(%s) %s->%s", script, host, SYSCHECK);
54 if(SendMSG(lessdc.queue, msg, sys_location, SYSCHECK_MQ) < 0)
56 merror(QUEUE_SEND, ARGV0);
58 if((lessdc.queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
60 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
63 /* If we reach here, we can try to send it again */
64 SendMSG(lessdc.queue, msg, sys_location, SYSCHECK_MQ);
72 /* Send generic log message. */
73 int send_log_msg(char *script, char *host, char *msg)
75 char sys_location[1024 +1];
77 sys_location[1024] = '\0';
78 snprintf(sys_location, 1024, "(%s) %s->%s", script, host, SYSCHECK);
80 if(SendMSG(lessdc.queue, msg, sys_location, LOCALFILE_MQ) < 0)
82 merror(QUEUE_SEND, ARGV0);
83 if((lessdc.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0)
85 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
88 /* If we reach here, we can try to send it again */
89 SendMSG(lessdc.queue, msg, sys_location, LOCALFILE_MQ);
96 /* Generate diffs alerts. */
97 int gen_diff_alert(char *host, char *script, int alert_diff_time)
103 char diff_alert[4096 +1];
106 diff_alert[4096] = '\0';
108 snprintf(buf, 2048, "%s/%s->%s/diff.%d",
109 DIFF_DIR_PATH, host, script, alert_diff_time);
111 fp = fopen(buf, "r");
114 merror("%s: ERROR: Unable to generate diff alert.", ARGV0);
118 n = fread(buf, 1, 2048 -1, fp);
121 merror("%s: ERROR: Unable to generate diff alert (fread).", ARGV0);
127 /* We need to clear the last new line. */
129 tmp_str = strrchr(buf, '\n');
134 /* Weird diff with only one large line. */
146 /* Getting up to 8 line changes. */
149 while(tmp_str && (*tmp_str != '\0'))
151 tmp_str = strchr(tmp_str, '\n');
164 /* Creating alert. */
165 snprintf(diff_alert, 4096 -1, "ossec: agentless: Change detected:\n%s%s",
171 snprintf(buf, 1024, "(%s) %s->agentless", script, host);
173 if(SendMSG(lessdc.queue, diff_alert, buf, LOCALFILE_MQ) < 0)
175 merror(QUEUE_SEND, ARGV0);
177 if((lessdc.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0)
179 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
182 /* If we reach here, we can try to send it again */
183 SendMSG(lessdc.queue, diff_alert, buf, LOCALFILE_MQ);
186 save_agentless_entry(host, script, "diff");
194 /* Checks if the file has changed */
195 int check_diff_file(char *host, char *script)
198 char old_location[1024 +1];
199 char new_location[1024 +1];
200 char tmp_location[1024 +1];
201 char diff_cmd[2048 +1];
206 old_location[1024] = '\0';
207 new_location[1024] = '\0';
208 tmp_location[1024] = '\0';
209 diff_cmd[2048] = '\0';
211 snprintf(new_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, script,
213 snprintf(old_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, script,
217 /* If the file is not there, rename new location to last location. */
218 if(OS_MD5_File(old_location, md5sum_old) != 0)
220 if(rename(new_location, old_location) != 0)
222 merror(RENAME_ERROR, ARGV0, new_location);
227 /* Get md5sum of the new file. */
228 if(OS_MD5_File(new_location, md5sum_new) != 0)
230 merror("%s: ERROR: Invalid internal state (missing '%s').",
231 ARGV0, new_location);
235 /* If they match, keep the old file and remove the new. */
236 if(strcmp(md5sum_new, md5sum_old) == 0)
238 unlink(new_location);
243 /* Saving the old file at timestamp and renaming new to last. */
244 date_of_change = File_DateofChange(old_location);
245 snprintf(tmp_location, 1024, "%s/%s->%s/state.%d", DIFF_DIR_PATH, host, script,
247 rename(old_location, tmp_location);
248 rename(new_location, old_location);
252 date_of_change = File_DateofChange(old_location);
253 snprintf(diff_cmd, 2048, "diff \"%s\" \"%s\" > \"%s/%s->%s/diff.%d\" "
255 tmp_location, old_location,
256 DIFF_DIR_PATH, host, script, date_of_change);
257 if(system(diff_cmd) != 256)
259 merror("%s: ERROR: Unable to run diff for %s->%s",
260 ARGV0, host, script);
265 /* Generate alert. */
266 gen_diff_alert(host, script, date_of_change);
274 /* get the diff file. */
275 FILE *open_diff_file(char *host, char *script)
278 char sys_location[1024 +1];
280 sys_location[1024] = '\0';
281 snprintf(sys_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host, script,
285 fp = fopen(sys_location, "w");
287 /* If we can't open, try creating the directory. */
290 snprintf(sys_location, 1024, "%s/%s->%s", DIFF_DIR_PATH, host, script);
291 if(IsDir(sys_location) == -1)
293 if(mkdir(sys_location, 0770) == -1)
295 merror(MKDIR_ERROR, ARGV0, sys_location);
300 snprintf(sys_location, 1024, "%s/%s->%s/%s", DIFF_DIR_PATH, host,
301 script, DIFF_NEW_FILE);
302 fp = fopen(sys_location, "w");
305 merror(FOPEN_ERROR, ARGV0, sys_location);
315 /* Run periodic commands. */
316 int run_periodic_cmd(agentlessd_entries *entry, int test_it)
320 char buf[OS_SIZE_2048 +1];
321 char command[OS_SIZE_1024 +1];
323 FILE *fp_store = NULL;
328 command[OS_SIZE_1024] = '\0';
331 while(entry->server[i])
334 if(entry->server[i][0] == '\0')
341 /* We only test for the first server entry. */
345 snprintf(command, OS_SIZE_1024,
346 "%s/%s test test >/dev/null 2>&1",
347 AGENTLESSDIRPATH, entry->type);
348 ret_code = system(command);
350 /* Checking if the test worked. */
353 if(ret_code == 32512)
355 merror("%s: ERROR: Expect command not found (or bad "
356 "arguments) for '%s'.",
359 merror("%s: ERROR: Test failed for '%s' (%d). Ignoring.",
360 ARGV0, entry->type, ret_code/256);
361 entry->error_flag = 99;
365 verbose("%s: INFO: Test passed for '%s'.", ARGV0, entry->type);
369 if(entry->server[i][0] == 's')
371 snprintf(command, OS_SIZE_1024, "%s/%s \"use_su\" \"%s\" %s 2>&1",
372 AGENTLESSDIRPATH, entry->type, entry->server[i] +1,
375 else if(entry->server[i][0] == 'o')
377 snprintf(command, OS_SIZE_1024, "%s/%s \"use_sudo\" \"%s\" %s 2>&1",
378 AGENTLESSDIRPATH, entry->type, entry->server[i] +1,
383 snprintf(command, OS_SIZE_1024, "%s/%s \"%s\" %s 2>&1",
384 AGENTLESSDIRPATH, entry->type, entry->server[i] +1,
388 fp = popen(command, "r");
391 while(fgets(buf, OS_SIZE_2048, fp) != NULL)
393 /* Removing new lines or carriage returns. */
394 tmp_str = strchr(buf, '\r');
397 tmp_str = strchr(buf, '\n');
401 if(strncmp(buf, "ERROR: ", 7) == 0)
403 merror("%s: ERROR: %s: %s: %s", ARGV0,
404 entry->type, entry->server[i] +1, buf +7);
408 else if(strncmp(buf, "INFO: ", 6) == 0)
410 verbose("%s: INFO: %s: %s: %s", ARGV0,
411 entry->type, entry->server[i] +1, buf +6);
413 else if(strncmp(buf, "FWD: ", 4) == 0)
416 send_intcheck_msg(entry->type, entry->server[i]+1,
419 else if(strncmp(buf, "LOG: ", 4) == 0)
422 send_log_msg(entry->type, entry->server[i]+1,
425 else if((entry->state & LESSD_STATE_DIFF) &&
426 (strncmp(buf, "STORE: ", 7) == 0))
428 fp_store = open_diff_file(entry->server[i]+1,
433 fprintf(fp_store, "%s\n", buf);
437 debug1("%s: DEBUG: buffer: %s", ARGV0, buf);
446 check_diff_file(entry->server[i] +1, entry->type);
450 save_agentless_entry(entry->server[i] +1,
451 entry->type, "syscheck");
457 merror("%s: ERROR: popen failed on '%s' for '%s'.", ARGV0,
458 entry->type, entry->server[i] +1);
475 /* Main agentlessd */
486 char str[OS_SIZE_1024 +1];
489 /* Waiting a few seconds to settle */
491 memset(str, '\0', OS_SIZE_1024 +1);
494 /* Getting currently time before starting */
499 thismonth = p->tm_mon;
500 thisyear = p->tm_year+1900;
503 /* Connecting to the message queue
506 if((lessdc.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0)
508 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE);
513 /* Main monitor loop */
521 /* Day changed, deal with log files */
522 if(today != p->tm_mday)
525 thismonth = p->tm_mon;
526 thisyear = p->tm_year+1900;
530 while(lessdc.entries[i])
532 if(lessdc.entries[i]->error_flag >= 10)
534 if(lessdc.entries[i]->error_flag != 99)
536 merror("%s: ERROR: Too many failures for '%s'. Ignoring it.",
537 ARGV0, lessdc.entries[i]->type);
538 lessdc.entries[i]->error_flag = 99;
547 /* Run the check again if the frequency has elapsed. */
548 if((lessdc.entries[i]->state & LESSD_STATE_PERIODIC) &&
549 ((lessdc.entries[i]->current_state +
550 lessdc.entries[i]->frequency) < tm))
552 run_periodic_cmd(lessdc.entries[i], test_it);
554 lessdc.entries[i]->current_state = tm;
562 /* We only check every minute */