1 /* @(#) $Id: ./src/remoted/manager.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
17 #include "os_net/os_net.h"
18 #include "os_crypto/md5/md5_op.h"
21 /* Internal structures */
22 typedef struct _file_sum
31 /* Internal functions prototypes */
32 void read_controlmsg(int agentid, char *msg);
37 /* Global vars, acessible every where */
45 /* For the last message tracking */
46 char *_msg[MAX_AGENTS +1];
47 char *_keep_alive[MAX_AGENTS +1];
48 int _changed[MAX_AGENTS +1];
52 /* pthread mutex variables */
53 pthread_mutex_t lastmsg_mutex;
54 pthread_cond_t awake_mutex;
58 /* save_controlmsg: Save a control message received
59 * from an agent. read_contromsg (other thread) is going
60 * to deal with it (only if message changed).
62 void save_controlmsg(int agentid, char *r_msg)
64 char msg_ack[OS_FLSIZE +1];
67 /* Replying to the agent. */
68 snprintf(msg_ack, OS_FLSIZE, "%s%s", CONTROL_HEADER, HC_ACK);
69 send_msg(agentid, msg_ack);
72 /* Checking if there is a keep alive already for this agent. */
73 if(_keep_alive[agentid] && _msg[agentid] &&
74 (strcmp(_msg[agentid], r_msg) == 0))
76 utimes(_keep_alive[agentid], NULL);
79 else if(strcmp(r_msg, HC_STARTUP) == 0)
88 char *random_leftovers;
92 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
94 merror(MUTEX_ERROR, ARGV0);
104 os_strdup(r_msg, _msg[agentid]);
107 /* Unlocking mutex. */
108 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
110 merror(MUTEX_ERROR, ARGV0);
115 r_msg = strchr(r_msg, '\n');
118 merror("%s: WARN: Invalid message from agent id: '%d'(uname)",
126 random_leftovers = strchr(r_msg, '\n');
129 *random_leftovers = '\0';
133 /* Updating the keep alive. */
134 if(!_keep_alive[agentid])
136 char agent_file[OS_SIZE_1024 +1];
137 agent_file[OS_SIZE_1024] = '\0';
139 /* Writting to the agent file */
140 snprintf(agent_file, OS_SIZE_1024, "%s/%s-%s",
142 keys.keyentries[agentid]->name,
143 keys.keyentries[agentid]->ip->ip);
145 os_strdup(agent_file, _keep_alive[agentid]);
149 /* Writing to the file. */
150 fp = fopen(_keep_alive[agentid], "w");
153 fprintf(fp, "%s\n", uname);
159 /* Locking now to notify of change. */
160 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
162 merror(MUTEX_ERROR, ARGV0);
167 /* Assign new values */
168 _changed[agentid] = 1;
169 modified_agentid = agentid;
172 /* Signal that new data is available */
173 pthread_cond_signal(&awake_mutex);
176 /* Unlocking mutex */
177 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
179 merror(MUTEX_ERROR, ARGV0);
189 /* f_files: Free the files memory
202 free(f_sum[i]->name);
214 /* c_files: Create the structure with the files and checksums
221 struct dirent *entry;
231 /* Creating merged file. */
232 os_realloc(f_sum, (f_size +2) * sizeof(file_sum *), f_sum);
233 os_calloc(1, sizeof(file_sum), f_sum[f_size]);
234 f_sum[f_size]->mark = 0;
235 f_sum[f_size]->name = NULL;
236 f_sum[f_size]->sum[0] = '\0';
237 MergeAppendFile(SHAREDCFG_FILE, NULL);
242 /* Opening the directory given */
243 dp = opendir(SHAREDCFG_DIR);
246 merror("%s: Error opening directory: '%s': %s ",
254 /* Reading directory */
255 while((entry = readdir(dp)) != NULL)
259 /* Just ignore . and .. */
260 if((strcmp(entry->d_name,".") == 0) ||
261 (strcmp(entry->d_name,"..") == 0))
266 snprintf(tmp_dir, 512, "%s/%s", SHAREDCFG_DIR, entry->d_name);
269 /* Leaving the shared config file for later. */
270 if(strcmp(tmp_dir, SHAREDCFG_FILE) == 0)
276 if(OS_MD5_File(tmp_dir, md5sum) != 0)
278 merror("%s: Error accessing file '%s'",ARGV0, tmp_dir);
283 f_sum = (file_sum **)realloc(f_sum, (f_size +2) * sizeof(file_sum *));
286 ErrorExit(MEM_ERROR,ARGV0);
289 f_sum[f_size] = calloc(1, sizeof(file_sum));
292 ErrorExit(MEM_ERROR,ARGV0);
296 strncpy(f_sum[f_size]->sum, md5sum, 32);
297 os_strdup(entry->d_name, f_sum[f_size]->name);
298 f_sum[f_size]->mark = 0;
301 MergeAppendFile(SHAREDCFG_FILE, tmp_dir);
306 f_sum[f_size] = NULL;
311 if(OS_MD5_File(SHAREDCFG_FILE, md5sum) != 0)
313 merror("%s: Error accessing file '%s'",ARGV0, SHAREDCFG_FILE);
314 f_sum[0]->sum[0] = '\0';
316 strncpy(f_sum[0]->sum, md5sum, 32);
319 os_strdup(SHAREDCFG_FILENAME, f_sum[0]->name);
326 /* send_file_toagent: Sends a file to the agent.
327 * Returns -1 on error
329 int send_file_toagent(int agentid, char *name, char *sum)
332 char file[OS_SIZE_1024 +1];
333 char buf[OS_SIZE_1024 +1];
338 snprintf(file, OS_SIZE_1024, "%s/%s",SHAREDCFG_DIR, name);
339 fp = fopen(file, "r");
342 merror(FOPEN_ERROR, ARGV0, file);
347 /* Sending the file name first */
348 snprintf(buf, OS_SIZE_1024, "%s%s%s %s\n",
349 CONTROL_HEADER, FILE_UPDATE_HEADER, sum, name);
351 if(send_msg(agentid, buf) == -1)
353 merror(SEC_ERROR,ARGV0);
359 /* Sending the file content */
360 while((n = fread(buf, 1, 900, fp)) > 0)
364 if(send_msg(agentid, buf) == -1)
366 merror(SEC_ERROR,ARGV0);
371 /* Sleep 1 every 30 messages -- no flood */
381 /* Sending the message to close the file */
382 snprintf(buf, OS_SIZE_1024, "%s%s", CONTROL_HEADER, FILE_CLOSE_HEADER);
383 if(send_msg(agentid, buf) == -1)
385 merror(SEC_ERROR,ARGV0);
398 /** void read_contromsg(int agentid, char *msg) v0.2.
399 * Reads the available control message from
402 void read_controlmsg(int agentid, char *msg)
408 msg = strchr(msg,'\n');
411 merror("%s: Invalid message from '%d' (uname)",ARGV0, agentid);
422 /* Nothing to share with agent */
436 msg = strchr(msg, '\n');
439 merror("%s: Invalid message from '%s' (strchr \\n)",
441 keys.keyentries[agentid]->ip->ip);
448 file = strchr(file, ' ');
451 merror("%s: Invalid message from '%s' (strchr ' ')",
453 keys.keyentries[agentid]->ip->ip);
461 /* New agents only have merged.mg. */
462 if(strcmp(file, SHAREDCFG_FILENAME) == 0)
464 if(strcmp(f_sum[0]->sum, md5) != 0)
466 debug1("%s: DEBUG Sending file '%s' to agent.", ARGV0,
468 if(send_file_toagent(agentid,f_sum[0]->name,f_sum[0]->sum)<0)
470 merror("%s: ERROR: Unable to send file '%s' to agent.",
492 else if(strcmp(f_sum[i]->name, file) != 0)
495 else if(strcmp(f_sum[i]->sum, md5) != 0)
496 f_sum[i]->mark = 1; /* Marked to update */
507 /* Updating each file marked */
513 if((f_sum[i]->mark == 1) ||
514 (f_sum[i]->mark == 0))
517 debug1("%s: Sending file '%s' to agent.", ARGV0, f_sum[i]->name);
518 if(send_file_toagent(agentid,f_sum[i]->name,f_sum[i]->sum) < 0)
520 merror("%s: Error sending file '%s' to agent.",
535 /** void *wait_for_msgs(void *none) v0.1
536 * Wait for new messages to read.
537 * The messages are going to be sent from save_controlmsg.
539 void *wait_for_msgs(void *none)
542 char msg[OS_SIZE_1024 +2];
545 /* Initializing the memory */
546 memset(msg, '\0', OS_SIZE_1024 +2);
549 /* should never leave this loop */
552 /* Every NOTIFY * 30 minutes, re read the files.
553 * If something changed, notify all agents
556 if((_ctime - _stime) > (NOTIFY_TIME*30))
566 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
568 merror(MUTEX_ERROR, ARGV0);
572 /* If no agent changed, wait for signal */
573 if(modified_agentid == -1)
575 pthread_cond_wait(&awake_mutex, &lastmsg_mutex);
578 /* Unlocking mutex */
579 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
581 merror(MUTEX_ERROR, ARGV0);
586 /* Checking if any agent is ready */
587 for(i = 0;i<keys.keysize; i++)
589 /* If agent wasn't changed, try next */
598 if(pthread_mutex_lock(&lastmsg_mutex) != 0)
600 merror(MUTEX_ERROR, ARGV0);
606 /* Copying the message to be analyzed */
607 strncpy(msg, _msg[i], OS_SIZE_1024);
610 if(modified_agentid >= i)
612 modified_agentid = -1;
618 /* Unlocking mutex */
619 if(pthread_mutex_unlock(&lastmsg_mutex) != 0)
621 merror(MUTEX_ERROR, ARGV0);
627 read_controlmsg(i, msg);
637 /* manager_init: Should be called before anything here */
638 void manager_init(int isUpdate)
646 debug1("%s: DEBUG: Running manager_init", ARGV0);
648 for(i=0; i<MAX_AGENTS +1; i++)
650 _keep_alive[i] = NULL;
655 /* Initializing mutexes */
658 pthread_mutex_init(&lastmsg_mutex, NULL);
659 pthread_cond_init(&awake_mutex, NULL);
662 modified_agentid = -1;