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
11 #include "manage_agents.h"
12 #include "os_crypto/md5/md5_op.h"
14 /* Global variables */
17 /*Number bit of int type*/
18 #define INT_BIT_SIZE (sizeof(int)*CHAR_BIT)
19 /*Enable bit at a position*/
20 #define SetBit(Array,pos) ( Array[(pos/INT_BIT_SIZE)] |= (1 << (pos%INT_BIT_SIZE)) )
21 /*Check state of bit at a */
22 #define TestBit(Array,pos) ( Array[(pos/INT_BIT_SIZE)] & (1 << (pos%INT_BIT_SIZE)) )
24 int *MapIDToBitArray()
27 char line_read[FILE_SIZE + 1];
28 line_read[FILE_SIZE] = '\0';
30 int max = MAX_AGENTS + AUTHD_FIRST_ID;
32 fp = fopen(AUTH_FILE, "r");
34 fp = fopen(KEYSFILE_PATH, "r");
41 os_calloc(MAX_AGENTS/INT_BIT_SIZE + 1, sizeof(int), arrayID);
43 while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
46 if (line_read[0] == '#') {
50 name = strchr(line_read, ' ');
53 int name_num=atoi(line_read);
54 /*Enable bit at ID already allocated*/
55 if (name_num >= AUTHD_FIRST_ID && name_num < max) {
56 SetBit(arrayID, (name_num-AUTHD_FIRST_ID));
65 char *OS_AddNewAgent(const char *name, const char *ip, const char *id)
70 char str1[STR_SIZE + 1];
71 char str2[STR_SIZE + 1];
74 char nid[9] = { '\0' };
79 snprintf(str1, STR_SIZE, "%d%s%d%s", (int)time(0), name, (int)random(), muname);
80 snprintf(str2, STR_SIZE, "%s%s%ld", ip, id, (long int)random());
81 OS_MD5_Str(str1, md1);
82 OS_MD5_Str(str2, md2);
89 arrayID=(int *)MapIDToBitArray();
90 if (arrayID != NULL) {
91 /*Find first item in bit array which is not marked as allocated*/
92 for (i=0; i<MAX_AGENTS; i++) {
93 if(!TestBit(arrayID, i)) {
94 snprintf(nid, 8, "%d", (i + AUTHD_FIRST_ID));
100 if (i == MAX_AGENTS) {
111 char authentication_file[2048 + 1];
112 snprintf(authentication_file, 2048, "%s%s", DEFAULTDIR, AUTH_FILE);
114 fp = fopen(authentication_file, "a");
119 os_calloc(2048, sizeof(char), finals);
121 snprintf(finals, 2048, "%s %s any %s%s", id, name, md1, md2);
123 snprintf(finals, 2048, "%s %s %s %s%s", id, name, ip, md1, md2);
125 fprintf(fp, "%s\n", finals);
131 int OS_RemoveAgent(const char *u_id) {
136 id_exist = IDExist(u_id);
141 fp = fopen(isChroot() ? AUTH_FILE : KEYSFILE_PATH, "r+");
147 if((chmod(AUTH_FILE, 0440)) < 0) {
148 merror("addagent: ERROR: Cannot chmod %s: %s", AUTH_FILE, strerror(errno));
156 char buf_discard[OS_BUFFER_SIZE];
159 if (stat(AUTH_FILE, &fp_stat) < 0) {
164 buffer = malloc(fp_stat.st_size);
170 fsetpos(fp, &fp_pos);
172 fseek(fp, 0, SEEK_SET);
173 fp_read = fread(buffer, sizeof(char), fp_seek, fp);
174 fgets(buf_discard, OS_BUFFER_SIZE - 1, fp);
177 fp_read += fread(buffer + fp_read, sizeof(char), fp_stat.st_size, fp);
180 fp = fopen(AUTH_FILE, "w");
187 fwrite(buffer, sizeof(char), fp_read, fp);
190 /* Remove the agent, but keep the id */
191 fsetpos(fp, &fp_pos);
192 fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id);
196 full_name = getFullnameById(u_id);
198 delete_agentinfo(full_name);
200 /* Remove counter for ID */
201 OS_RemoveCounter(u_id);
205 int OS_IsValidID(const char *id)
209 /* ID must not be null */
216 /* Check ID length, it should contain max. 8 characters */
221 /* Check ID if it contains only numeric characters [0-9] */
222 for (i = 0; i < id_len; i++) {
223 if (!(isdigit((int)id[i]))) {
231 /* Get full agent name (name + IP) of ID */
232 char *getFullnameById(const char *id)
235 char line_read[FILE_SIZE + 1];
236 line_read[FILE_SIZE] = '\0';
238 /* ID must not be null */
243 fp = fopen(AUTH_FILE, "r");
248 while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
253 if (line_read[0] == '#') {
257 name = strchr(line_read, ' ');
261 if (strcmp(line_read, id) != 0) {
272 ip = strchr(name, ' ');
278 tmp_str = strchr(ip, ' ');
282 tmp_str = strchr(ip, '/');
287 /* If we reached here, we found the IP and name */
288 os_calloc(1, FILE_SIZE, final_str);
289 snprintf(final_str, FILE_SIZE - 1, "%s-%s", name, ip);
302 /* ID Search (is valid ID) */
303 int IDExist(const char *id)
306 char line_read[FILE_SIZE + 1];
307 line_read[FILE_SIZE] = '\0';
309 /* ID must not be null */
315 fp = fopen(AUTH_FILE, "r");
317 fp = fopen(KEYSFILE_PATH, "r");
324 fseek(fp, 0, SEEK_SET);
325 fgetpos(fp, &fp_pos);
327 while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
330 if (line_read[0] == '#') {
331 fgetpos(fp, &fp_pos);
335 name = strchr(line_read, ' ');
340 if (strcmp(line_read, id) == 0) {
342 return (1); /*(fp_pos);*/
346 fgetpos(fp, &fp_pos);
353 /* Validate agent name */
354 int OS_IsValidName(const char *u_name)
356 size_t i, uname_length = strlen(u_name);
358 /* We must have something in the name */
359 if (uname_length < 2 || uname_length > 128) {
363 /* Check if it contains any non-alphanumeric characters */
364 for (i = 0; i < uname_length; i++) {
365 if ( !( isalnum((int)u_name[i]) || (u_name[i] == '-') ||
366 (u_name[i] == '_') || (u_name[i] == '.') ||
367 (u_name[i] == ':') ) ) {
375 int NameExist(const char *u_name)
378 char line_read[FILE_SIZE + 1];
379 line_read[FILE_SIZE] = '\0';
389 fp = fopen(AUTH_FILE, "r");
391 fp = fopen(KEYSFILE_PATH, "r");
398 fseek(fp, 0, SEEK_SET);
399 fgetpos(fp, &fp_pos);
401 while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
404 if (line_read[0] == '#') {
408 name = strchr(line_read, ' ');
417 ip = strchr(name, ' ');
420 if (strcmp(u_name, name) == 0) {
426 fgetpos(fp, &fp_pos);
433 /* Returns the ID of an agent, or NULL if not found */
434 char *IPExist(const char *u_ip)
437 char *name, *ip, *pass;
438 char line_read[FILE_SIZE + 1];
439 line_read[FILE_SIZE] = '\0';
441 if (!(u_ip && strncmp(u_ip, "any", 3)) || strchr(u_ip, '/'))
445 fp = fopen(AUTH_FILE, "r");
447 fp = fopen(KEYSFILE_PATH, "r");
452 fseek(fp, 0, SEEK_SET);
453 fgetpos(fp, &fp_pos);
455 while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
456 if (line_read[0] == '#') {
460 name = strchr(line_read, ' ');
468 ip = strchr(name, ' ');
472 pass = strchr(ip, ' ');
475 if (strcmp(u_ip, ip) == 0) {
478 return strdup(line_read);
484 fgetpos(fp, &fp_pos);
491 /* Returns the number of seconds since last agent connection, or -1 if error. */
492 double OS_AgentAntiquity(const char *id)
494 struct stat file_stat;
495 char file_name[OS_FLSIZE];
496 char *full_name = getFullnameById(id);
502 snprintf(file_name, OS_FLSIZE - 1, "%s/%s", AGENTINFO_DIR, full_name);
504 if (stat(file_name, &file_stat) < 0) {
513 return difftime(time(NULL), file_stat.st_mtime);
516 /* Print available agents */
517 int print_agents(int print_status, int active_only, int csv_output, cJSON *json_output)
521 char line_read[FILE_SIZE + 1];
522 line_read[FILE_SIZE] = '\0';
524 fp = fopen(AUTH_FILE, "r");
529 fseek(fp, 0, SEEK_SET);
531 memset(line_read, '\0', FILE_SIZE);
533 while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
536 if (line_read[0] == '#') {
540 name = strchr(line_read, ' ');
551 ip = strchr(name, ' ');
556 key = strchr(ip, ' ');
559 if (!total && !print_status) {
560 printf(PRINT_AVAILABLE);
565 int agt_status = get_agent_status(name, ip);
566 if (active_only && (agt_status != GA_STATUS_ACTIVE)) {
571 printf("%s,%s,%s,%s,\n", line_read, name, ip, print_agent_status(agt_status));
572 } else if (json_output) {
573 cJSON *json_agent = cJSON_CreateObject();
578 cJSON_AddStringToObject(json_agent, "id", line_read);
579 cJSON_AddStringToObject(json_agent, "name", name);
580 cJSON_AddStringToObject(json_agent, "ip", ip);
581 cJSON_AddStringToObject(json_agent, "status", print_agent_status(agt_status));
582 cJSON_AddItemToArray(json_output, json_agent);
584 printf(PRINT_AGENT_STATUS, line_read, name, ip, print_agent_status(agt_status));
587 printf(PRINT_AGENT, line_read, name, ip);
594 /* Only print agentless for non-active only searches */
595 if (!active_only && print_status) {
596 const char *aip = NULL;
600 if (!csv_output && !json_output) {
601 printf("\nList of agentless devices:\n");
604 dirp = opendir(AGENTLESS_ENTRYDIR);
606 while ((dp = readdir(dirp)) != NULL) {
607 if (strncmp(dp->d_name, ".", 1) == 0) {
611 aip = strchr(dp->d_name, '@');
619 printf("na,%s,%s,agentless,\n", dp->d_name, aip);
621 printf(" ID: na, Name: %s, IP: %s, agentless\n",
637 void FormatID(char *id) {
642 number = strtol(id, &end, 10);
645 sprintf(id, "%03d", number);