1 /* @(#) $Id: manager.c,v 1.47 2009/06/24 18:53:07 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
16 #include "os_net/os_net.h"
17 #include "os_crypto/md5/md5_op.h"
20 /* Internal structures */
21 typedef struct _file_sum
30 /* Internal functions prototypes */
31 void read_controlmsg(int agentid, char *msg);
36 /* Global vars, acessible every where */
44 /* For the last message tracking */
45 char *_msg[MAX_AGENTS +1];
46 char *_keep_alive[MAX_AGENTS +1];
47 int _changed[MAX_AGENTS +1];
51 /* pthread mutex variables */
52 pthread_mutex_t lastmsg_mutex;
53 pthread_cond_t awake_mutex;
57 /* save_controlmsg: Save a control message received
58 * from an agent. read_contromsg (other thread) is going
59 * to deal with it (only if message changed).
61 void save_controlmsg(int agentid, char *r_msg)
63 char msg_ack[OS_FLSIZE +1];
66 /* Replying to the agent. */
67 snprintf(msg_ack, OS_FLSIZE, "%s%s", CONTROL_HEADER, HC_ACK);
68 send_msg(agentid, msg_ack);
71 /* Checking if there is a keep alive already for this agent. */
72 if(_keep_alive[agentid] && _msg[agentid] &&
73 (strcmp(_msg[agentid], r_msg) == 0))
75 utimes(_keep_alive[agentid], NULL);
78 else if(strcmp(r_msg, HC_STARTUP) == 0)
90 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
92 merror(MUTEX_ERROR, ARGV0);
102 os_strdup(r_msg, _msg[agentid]);
105 /* Unlocking mutex. */
106 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
108 merror(MUTEX_ERROR, ARGV0);
113 r_msg = strchr(r_msg, '\n');
116 merror("%s: WARN: Invalid message from agent id: '%d'(uname)",
126 /* Updating the keep alive. */
127 if(!_keep_alive[agentid])
129 char agent_file[OS_SIZE_1024 +1];
130 agent_file[OS_SIZE_1024] = '\0';
132 /* Writting to the agent file */
133 snprintf(agent_file, OS_SIZE_1024, "%s/%s-%s",
135 keys.keyentries[agentid]->name,
136 keys.keyentries[agentid]->ip->ip);
138 os_strdup(agent_file, _keep_alive[agentid]);
142 /* Writing to the file. */
143 fp = fopen(_keep_alive[agentid], "w");
146 fprintf(fp, "%s\n", uname);
152 /* Locking now to notify of change. */
153 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
155 merror(MUTEX_ERROR, ARGV0);
160 /* Assign new values */
161 _changed[agentid] = 1;
162 modified_agentid = agentid;
165 /* Signal that new data is available */
166 pthread_cond_signal(&awake_mutex);
169 /* Unlocking mutex */
170 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
172 merror(MUTEX_ERROR, ARGV0);
182 /* f_files: Free the files memory
195 free(f_sum[i]->name);
207 /* c_files: Create the structure with the files and checksums
214 struct dirent *entry;
224 /* Creating merged file. */
225 os_realloc(f_sum, (f_size +2) * sizeof(file_sum *), f_sum);
226 os_calloc(1, sizeof(file_sum), f_sum[f_size]);
227 f_sum[f_size]->mark = 0;
228 f_sum[f_size]->name = NULL;
229 f_sum[f_size]->sum[0] = '\0';
230 MergeAppendFile(SHAREDCFG_FILE, NULL);
235 /* Opening the directory given */
236 dp = opendir(SHAREDCFG_DIR);
239 merror("%s: Error opening directory: '%s': %s ",
247 /* Reading directory */
248 while((entry = readdir(dp)) != NULL)
252 /* Just ignore . and .. */
253 if((strcmp(entry->d_name,".") == 0) ||
254 (strcmp(entry->d_name,"..") == 0))
259 snprintf(tmp_dir, 512, "%s/%s", SHAREDCFG_DIR, entry->d_name);
262 /* Leaving the shared config file for later. */
263 if(strcmp(tmp_dir, SHAREDCFG_FILE) == 0)
269 if(OS_MD5_File(tmp_dir, md5sum) != 0)
271 merror("%s: Error accessing file '%s'",ARGV0, tmp_dir);
276 f_sum = (file_sum **)realloc(f_sum, (f_size +2) * sizeof(file_sum *));
279 ErrorExit(MEM_ERROR,ARGV0);
282 f_sum[f_size] = calloc(1, sizeof(file_sum));
285 ErrorExit(MEM_ERROR,ARGV0);
289 strncpy(f_sum[f_size]->sum, md5sum, 32);
290 os_strdup(entry->d_name, f_sum[f_size]->name);
291 f_sum[f_size]->mark = 0;
294 MergeAppendFile(SHAREDCFG_FILE, tmp_dir);
299 f_sum[f_size] = NULL;
304 if(OS_MD5_File(SHAREDCFG_FILE, md5sum) != 0)
306 merror("%s: Error accessing file '%s'",ARGV0, SHAREDCFG_FILE);
307 f_sum[0]->sum[0] = '\0';
309 strncpy(f_sum[0]->sum, md5sum, 32);
312 os_strdup(SHAREDCFG_FILENAME, f_sum[0]->name);
319 /* send_file_toagent: Sends a file to the agent.
320 * Returns -1 on error
322 int send_file_toagent(int agentid, char *name, char *sum)
325 char file[OS_SIZE_1024 +1];
326 char buf[OS_SIZE_1024 +1];
331 snprintf(file, OS_SIZE_1024, "%s/%s",SHAREDCFG_DIR, name);
332 fp = fopen(file, "r");
335 merror(FOPEN_ERROR, ARGV0, file);
340 /* Sending the file name first */
341 snprintf(buf, OS_SIZE_1024, "%s%s%s %s\n",
342 CONTROL_HEADER, FILE_UPDATE_HEADER, sum, name);
344 if(send_msg(agentid, buf) == -1)
346 merror(SEC_ERROR,ARGV0);
352 /* Sending the file content */
353 while((n = fread(buf, 1, 900, fp)) > 0)
357 if(send_msg(agentid, buf) == -1)
359 merror(SEC_ERROR,ARGV0);
364 /* Sleep 1 every 30 messages -- no flood */
374 /* Sending the message to close the file */
375 snprintf(buf, OS_SIZE_1024, "%s%s", CONTROL_HEADER, FILE_CLOSE_HEADER);
376 if(send_msg(agentid, buf) == -1)
378 merror(SEC_ERROR,ARGV0);
391 /** void read_contromsg(int agentid, char *msg) v0.2.
392 * Reads the available control message from
395 void read_controlmsg(int agentid, char *msg)
401 msg = strchr(msg,'\n');
404 merror("%s: Invalid message from '%d' (uname)",ARGV0, agentid);
415 /* Nothing to share with agent */
429 msg = strchr(msg, '\n');
432 merror("%s: Invalid message from '%s' (strchr \\n)",
434 keys.keyentries[agentid]->ip->ip);
441 file = strchr(file, ' ');
444 merror("%s: Invalid message from '%s' (strchr ' ')",
446 keys.keyentries[agentid]->ip->ip);
454 /* New agents only have merged.mg. */
455 if(strcmp(file, SHAREDCFG_FILENAME) == 0)
457 if(strcmp(f_sum[0]->sum, md5) != 0)
459 debug1("%s: DEBUG Sending file '%s' to agent.", ARGV0,
461 if(send_file_toagent(agentid,f_sum[0]->name,f_sum[0]->sum)<0)
463 merror("%s: ERROR: Unable to send file '%s' to agent.",
485 else if(strcmp(f_sum[i]->name, file) != 0)
488 else if(strcmp(f_sum[i]->sum, md5) != 0)
489 f_sum[i]->mark = 1; /* Marked to update */
500 /* Updating each file marked */
506 if((f_sum[i]->mark == 1) ||
507 (f_sum[i]->mark == 0))
510 debug1("%s: Sending file '%s' to agent.", ARGV0, f_sum[i]->name);
511 if(send_file_toagent(agentid,f_sum[i]->name,f_sum[i]->sum) < 0)
513 merror("%s: Error sending file '%s' to agent.",
528 /** void *wait_for_msgs(void *none) v0.1
529 * Wait for new messages to read.
530 * The messages are going to be sent from save_controlmsg.
532 void *wait_for_msgs(void *none)
535 char msg[OS_SIZE_1024 +2];
538 /* Initializing the memory */
539 memset(msg, '\0', OS_SIZE_1024 +2);
542 /* should never leave this loop */
545 /* Every NOTIFY * 30 minutes, re read the files.
546 * If something changed, notify all agents
549 if((_ctime - _stime) > (NOTIFY_TIME*30))
559 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
561 merror(MUTEX_ERROR, ARGV0);
565 /* If no agent changed, wait for signal */
566 if(modified_agentid == -1)
568 pthread_cond_wait(&awake_mutex, &lastmsg_mutex);
571 /* Unlocking mutex */
572 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
574 merror(MUTEX_ERROR, ARGV0);
579 /* Checking if any agent is ready */
580 for(i = 0;i<keys.keysize; i++)
582 /* If agent wasn't changed, try next */
591 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
593 merror(MUTEX_ERROR, ARGV0);
599 /* Copying the message to be analyzed */
600 strncpy(msg, _msg[i], OS_SIZE_1024);
603 if(modified_agentid >= i)
605 modified_agentid = -1;
611 /* Unlocking mutex */
612 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
614 merror(MUTEX_ERROR, ARGV0);
620 read_controlmsg(i, msg);
630 /* manager_init: Should be called before anything here */
631 void manager_init(int isUpdate)
639 debug1("%s: DEBUG: Running manager_init", ARGV0);
641 for(i=0; i<MAX_AGENTS +1; i++)
643 _keep_alive[i] = NULL;
648 /* Initializing mutexes */
651 pthread_mutex_init(&lastmsg_mutex, NULL);
652 pthread_cond_init(&awake_mutex, NULL);
655 modified_agentid = -1;