1 /* Copyright (C) 2009 Trend Micro Inc.
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
12 #include "os_crypto/md5/md5_op.h"
13 #include "os_net/os_net.h"
16 /* Internal structures */
17 typedef struct _file_sum {
23 /* Internal functions prototypes */
24 static void read_controlmsg(unsigned int agentid, char *msg);
25 static int send_file_toagent(unsigned int agentid, const char *name, const char *sum);
26 static void f_files(void);
27 static void c_files(void);
30 static file_sum **f_sum;
34 /* For the last message tracking */
35 static char *_msg[MAX_AGENTS + 1];
36 static char *_keep_alive[MAX_AGENTS + 1];
37 static int _changed[MAX_AGENTS + 1];
38 static int modified_agentid;
40 /* pthread mutex variables */
41 static pthread_mutex_t lastmsg_mutex;
42 static pthread_cond_t awake_mutex;
45 /* Save a control message received from an agent
46 * read_controlmsg (other thread) is going to deal with it
47 * (only if message changed)
49 void save_controlmsg(unsigned int agentid, char *r_msg)
51 char msg_ack[OS_FLSIZE + 1];
53 /* Reply to the agent */
54 snprintf(msg_ack, OS_FLSIZE, "%s%s", CONTROL_HEADER, HC_ACK);
55 send_msg(agentid, msg_ack);
57 /* Check if there is a keep alive already for this agent */
58 if (_keep_alive[agentid] && _msg[agentid] &&
59 (strcmp(_msg[agentid], r_msg) == 0)) {
60 utimes(_keep_alive[agentid], NULL);
63 else if (strcmp(r_msg, HC_STARTUP) == 0) {
70 char *random_leftovers;
73 if (pthread_mutex_lock(&lastmsg_mutex) != 0) {
74 merror(MUTEX_ERROR, ARGV0);
82 os_strdup(r_msg, _msg[agentid]);
85 if (pthread_mutex_unlock(&lastmsg_mutex) != 0) {
86 merror(MUTEX_ERROR, ARGV0);
90 r_msg = strchr(r_msg, '\n');
92 merror("%s: WARN: Invalid message from agent id: '%d'(uname)",
99 random_leftovers = strchr(r_msg, '\n');
100 if (random_leftovers) {
101 *random_leftovers = '\0';
104 /* Update the keep alive */
105 if (!_keep_alive[agentid]) {
106 char agent_file[OS_SIZE_1024 + 1];
107 agent_file[OS_SIZE_1024] = '\0';
109 /* Write to the agent file */
110 snprintf(agent_file, OS_SIZE_1024, "%s/%s-%s",
112 keys.keyentries[agentid]->name,
113 keys.keyentries[agentid]->ip->ip);
114 os_strdup(agent_file, _keep_alive[agentid]);
117 /* Write to the file */
118 fp = fopen(_keep_alive[agentid], "w");
120 fprintf(fp, "%s\n", uname);
123 merror("ossec-remoted: ERROR: Could not open %s: %s", _keep_alive[agentid], strerror(errno));
127 /* Lock now to notify of change */
128 if (pthread_mutex_lock(&lastmsg_mutex) != 0) {
129 merror(MUTEX_ERROR, ARGV0);
133 /* Assign new values */
134 _changed[agentid] = 1;
135 modified_agentid = (int) agentid;
137 /* Signal that new data is available */
138 pthread_cond_signal(&awake_mutex);
141 if (pthread_mutex_unlock(&lastmsg_mutex) != 0) {
142 merror(MUTEX_ERROR, ARGV0);
149 /* Free the files memory */
150 static void f_files()
157 if (f_sum[i] == NULL) {
161 if (f_sum[i]->name) {
162 free(f_sum[i]->name);
173 /* Create the structure with the files and checksums */
174 static void c_files()
177 struct dirent *entry;
179 unsigned int f_size = 0;
183 /* Create merged file */
184 os_realloc(f_sum, (f_size + 2) * sizeof(file_sum *), f_sum);
185 os_calloc(1, sizeof(file_sum), f_sum[f_size]);
186 f_sum[f_size]->mark = 0;
187 f_sum[f_size]->name = NULL;
188 f_sum[f_size]->sum[0] = '\0';
189 MergeAppendFile(SHAREDCFG_FILE, NULL);
193 dp = opendir(SHAREDCFG_DIR);
195 merror("%s: Error opening directory: '%s': %s ",
203 while ((entry = readdir(dp)) != NULL) {
206 /* Ignore . and .. */
207 if ((strcmp(entry->d_name, ".") == 0) ||
208 (strcmp(entry->d_name, "..") == 0)) {
212 snprintf(tmp_dir, 512, "%s/%s", SHAREDCFG_DIR, entry->d_name);
214 /* Leave the shared config file for later */
215 if (strcmp(tmp_dir, SHAREDCFG_FILE) == 0) {
219 if (OS_MD5_File(tmp_dir, md5sum, OS_TEXT) != 0) {
220 merror("%s: Error accessing file '%s'", ARGV0, tmp_dir);
224 f_sum = (file_sum **)realloc(f_sum, (f_size + 2) * sizeof(file_sum *));
226 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
229 f_sum[f_size] = (file_sum *) calloc(1, sizeof(file_sum));
230 if (!f_sum[f_size]) {
231 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
234 strncpy(f_sum[f_size]->sum, md5sum, 32);
235 os_strdup(entry->d_name, f_sum[f_size]->name);
236 f_sum[f_size]->mark = 0;
238 MergeAppendFile(SHAREDCFG_FILE, tmp_dir);
243 f_sum[f_size] = NULL;
248 if (OS_MD5_File(SHAREDCFG_FILE, md5sum, OS_TEXT) != 0) {
249 merror("%s: Error accessing file '%s'", ARGV0, SHAREDCFG_FILE);
250 f_sum[0]->sum[0] = '\0';
252 strncpy(f_sum[0]->sum, md5sum, 32);
254 os_strdup(SHAREDCFG_FILENAME, f_sum[0]->name);
259 /* Send a file to the agent
260 * Returns -1 on error
262 static int send_file_toagent(unsigned int agentid, const char *name, const char *sum)
266 char file[OS_SIZE_1024 + 1];
267 char buf[OS_SIZE_1024 + 1];
270 snprintf(file, OS_SIZE_1024, "%s/%s", SHAREDCFG_DIR, name);
271 fp = fopen(file, "r");
273 merror(FOPEN_ERROR, ARGV0, file, errno, strerror(errno));
277 /* Send the file name first */
278 snprintf(buf, OS_SIZE_1024, "%s%s%s %s\n",
279 CONTROL_HEADER, FILE_UPDATE_HEADER, sum, name);
280 if (send_msg(agentid, buf) == -1) {
281 merror(SEC_ERROR, ARGV0);
286 /* Send the file contents */
287 while ((n = fread(buf, 1, 900, fp)) > 0) {
290 if (send_msg(agentid, buf) == -1) {
291 merror(SEC_ERROR, ARGV0);
296 /* Sleep 1 every 30 messages -- no flood */
304 /* Send the message to close the file */
305 snprintf(buf, OS_SIZE_1024, "%s%s", CONTROL_HEADER, FILE_CLOSE_HEADER);
306 if (send_msg(agentid, buf) == -1) {
307 merror(SEC_ERROR, ARGV0);
317 /* Read the available control message from the agent */
318 static void read_controlmsg(unsigned int agentid, char *msg)
323 msg = strchr(msg, '\n');
325 merror("%s: Invalid message from '%d' (uname)", ARGV0, agentid);
333 /* Nothing to share with agent */
338 while (*msg != '\0') {
345 msg = strchr(msg, '\n');
347 merror("%s: Invalid message from '%s' (strchr \\n)",
349 keys.keyentries[agentid]->ip->ip);
356 file = strchr(file, ' ');
358 merror("%s: Invalid message from '%s' (strchr ' ')",
360 keys.keyentries[agentid]->ip->ip);
367 /* New agents only have merged.mg */
368 if (strcmp(file, SHAREDCFG_FILENAME) == 0) {
369 if (strcmp(f_sum[0]->sum, md5) != 0) {
370 debug1("%s: DEBUG Sending file '%s' to agent.", ARGV0,
372 if (send_file_toagent(agentid, f_sum[0]->name, f_sum[0]->sum) < 0) {
373 merror("%s: ERROR: Unable to send file '%s' to agent.",
389 if (f_sum[i] == NULL) {
393 else if (strcmp(f_sum[i]->name, file) != 0) {
397 else if (strcmp(f_sum[i]->sum, md5) != 0) {
398 f_sum[i]->mark = 1; /* Marked to update */
408 /* Update each marked file */
410 if (f_sum[i] == NULL) {
414 if ((f_sum[i]->mark == 1) ||
415 (f_sum[i]->mark == 0)) {
417 debug1("%s: Sending file '%s' to agent.", ARGV0, f_sum[i]->name);
418 if (send_file_toagent(agentid, f_sum[i]->name, f_sum[i]->sum) < 0) {
419 merror("%s: Error sending file '%s' to agent.",
431 /* Wait for new messages to read
432 * The messages will be sent using save_controlmsg
434 void *wait_for_msgs(__attribute__((unused)) void *none)
437 char msg[OS_SIZE_1024 + 2];
439 /* Initialize the memory */
440 memset(msg, '\0', OS_SIZE_1024 + 2);
442 /* Should never leave this loop */
445 /* Every NOTIFY * 30 minutes, re-read the files
446 * If something changed, notify all agents
449 if ((_ctime - _stime) > (NOTIFY_TIME * 30)) {
457 if (pthread_mutex_lock(&lastmsg_mutex) != 0) {
458 merror(MUTEX_ERROR, ARGV0);
462 /* If no agent changed, wait for signal */
463 if (modified_agentid == -1) {
464 pthread_cond_wait(&awake_mutex, &lastmsg_mutex);
468 if (pthread_mutex_unlock(&lastmsg_mutex) != 0) {
469 merror(MUTEX_ERROR, ARGV0);
473 /* Check if any agent is ready */
474 for (i = 0; i < keys.keysize; i++) {
475 /* If agent wasn't changed, try next */
476 if (_changed[i] != 1) {
483 if (pthread_mutex_lock(&lastmsg_mutex) != 0) {
484 merror(MUTEX_ERROR, ARGV0);
489 /* Copy the message to be analyzed */
490 strncpy(msg, _msg[i], OS_SIZE_1024);
493 if (modified_agentid >= (int) i) {
494 modified_agentid = -1;
501 if (pthread_mutex_unlock(&lastmsg_mutex) != 0) {
502 merror(MUTEX_ERROR, ARGV0);
507 read_controlmsg(i, msg);
515 /* Should be called before anything here */
516 void manager_init(int isUpdate)
525 debug1("%s: DEBUG: Running manager_init", ARGV0);
527 modified_agentid = -1;
529 for (i = 0; i < MAX_AGENTS + 1; i++) {
530 _keep_alive[i] = NULL;
535 /* Initialize mutexes */
537 pthread_mutex_init(&lastmsg_mutex, NULL);
538 pthread_cond_init(&awake_mutex, NULL);