-/* @(#) $Id$ */
-
/* Copyright (C) 2009 Trend Micro Inc.
* All rights reserved.
*
* Foundation
*/
+#include <time.h>
+#include "manage_agents.h"
+#include "os_crypto/md5/md5_op.h"
+/* Global variables */
+fpos_t fp_pos;
-#include "manage_agents.h"
+/*Number bit of int type*/
+#define INT_BIT_SIZE (sizeof(int)*CHAR_BIT)
+/*Enable bit at a position*/
+#define SetBit(Array,pos) ( Array[(pos/INT_BIT_SIZE)] |= (1 << (pos%INT_BIT_SIZE)) )
+/*Check state of bit at a */
+#define TestBit(Array,pos) ( Array[(pos/INT_BIT_SIZE)] & (1 << (pos%INT_BIT_SIZE)) )
+
+int *MapIDToBitArray()
+{
+ FILE *fp;
+ char line_read[FILE_SIZE + 1];
+ line_read[FILE_SIZE] = '\0';
+ int *arrayID;
+ int max = MAX_AGENTS + AUTHD_FIRST_ID;
+ if (isChroot()) {
+ fp = fopen(AUTH_FILE, "r");
+ } else {
+ fp = fopen(KEYSFILE_PATH, "r");
+ }
+
+ if (!fp) {
+ return (NULL);
+ }
+
+ os_calloc(MAX_AGENTS/INT_BIT_SIZE + 1, sizeof(int), arrayID);
+
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
+ char *name;
+
+ if (line_read[0] == '#') {
+ continue;
+ }
+
+ name = strchr(line_read, ' ');
+ if (name) {
+ *name = '\0';
+ int name_num=atoi(line_read);
+ /*Enable bit at ID already allocated*/
+ if (name_num >= AUTHD_FIRST_ID && name_num < max) {
+ SetBit(arrayID, (name_num-AUTHD_FIRST_ID));
+ }
+ }
+
+ }
+ fclose(fp);
+ return arrayID;
+}
+
+char *OS_AddNewAgent(const char *name, const char *ip, const char *id)
+{
+ FILE *fp;
+ os_md5 md1;
+ os_md5 md2;
+ char str1[STR_SIZE + 1];
+ char str2[STR_SIZE + 1];
+ char *muname;
+ char *finals;
+ char nid[9] = { '\0' };
+
+ srandom_init();
+ muname = getuname();
+
+ snprintf(str1, STR_SIZE, "%d%s%d%s", (int)time(0), name, (int)random(), muname);
+ snprintf(str2, STR_SIZE, "%s%s%ld", ip, id, (long int)random());
+ OS_MD5_Str(str1, md1);
+ OS_MD5_Str(str2, md2);
+
+ free(muname);
+
+ if (id == NULL) {
+ int *arrayID;
+ int i;
+ arrayID=(int *)MapIDToBitArray();
+ if (arrayID != NULL) {
+ /*Find first item in bit array which is not marked as allocated*/
+ for (i=0; i<MAX_AGENTS; i++) {
+ if(!TestBit(arrayID, i)) {
+ snprintf(nid, 8, "%d", (i + AUTHD_FIRST_ID));
+ break;
+ }
+ }
+ os_free(arrayID);
+
+ if (i == MAX_AGENTS) {
+ return (NULL);
+ }
+ }
+ else {
+ return (NULL);
+ }
+
+ id = nid;
+ }
+
+ char authentication_file[2048 + 1];
+ snprintf(authentication_file, 2048, "%s%s", DEFAULTDIR, AUTH_FILE);
+
+ fp = fopen(authentication_file, "a");
+ if (!fp) {
+ return (NULL);
+ }
+
+ os_calloc(2048, sizeof(char), finals);
+ if (ip == NULL) {
+ snprintf(finals, 2048, "%s %s any %s%s", id, name, md1, md2);
+ } else {
+ snprintf(finals, 2048, "%s %s %s %s%s", id, name, ip, md1, md2);
+ }
+ fprintf(fp, "%s\n", finals);
+
+ fclose(fp);
+ return (finals);
+}
+
+int OS_RemoveAgent(const char *u_id) {
+ FILE *fp;
+ int id_exist;
+ char *full_name;
+
+ id_exist = IDExist(u_id);
+
+ if (!id_exist)
+ return 0;
+
+ fp = fopen(isChroot() ? AUTH_FILE : KEYSFILE_PATH, "r+");
+
+ if (!fp)
+ return 0;
+
+#ifndef WIN32
+ if((chmod(AUTH_FILE, 0440)) < 0) {
+ merror("addagent: ERROR: Cannot chmod %s: %s", AUTH_FILE, strerror(errno));
+ }
+#endif
+
+#ifdef REUSE_ID
+ long fp_seek;
+ size_t fp_read;
+ char *buffer;
+ char buf_discard[OS_BUFFER_SIZE];
+ struct stat fp_stat;
+
+ if (stat(AUTH_FILE, &fp_stat) < 0) {
+ fclose(fp);
+ return 0;
+ }
+
+ buffer = malloc(fp_stat.st_size);
+ if (!buffer) {
+ fclose(fp);
+ return 0;
+ }
+
+ fsetpos(fp, &fp_pos);
+ fp_seek = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ fp_read = fread(buffer, sizeof(char), fp_seek, fp);
+ fgets(buf_discard, OS_BUFFER_SIZE - 1, fp);
+
+ if (!feof(fp))
+ fp_read += fread(buffer + fp_read, sizeof(char), fp_stat.st_size, fp);
+
+ fclose(fp);
+ fp = fopen(AUTH_FILE, "w");
+
+ if (!fp) {
+ free(buffer);
+ return 0;
+ }
+
+ fwrite(buffer, sizeof(char), fp_read, fp);
+#else
+ /* Remove the agent, but keep the id */
+ fsetpos(fp, &fp_pos);
+ fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id);
+#endif
+ fclose(fp);
+
+ full_name = getFullnameById(u_id);
+ if (full_name)
+ delete_agentinfo(full_name);
+
+ /* Remove counter for ID */
+ OS_RemoveCounter(u_id);
+ return 1;
+}
-int OS_IsValidID(char *id)
+int OS_IsValidID(const char *id)
{
- int id_len = 0;
- int i = 0;
-
- /* ID must not be null */
- if(!id)
- return(0);
+ size_t id_len, i;
+
+ /* ID must not be null */
+ if (!id) {
+ return (0);
+ }
id_len = strlen(id);
- /* Check ID length, it should contain max. 5 characters */
- if (id_len > 8)
- return(0);
+ /* Check ID length, it should contain max. 8 characters */
+ if (id_len > 8) {
+ return (0);
+ }
/* Check ID if it contains only numeric characters [0-9] */
- for(i = 0; i < id_len; i++)
- {
- if(!(isdigit((int)id[i])))
- return(0);
+ for (i = 0; i < id_len; i++) {
+ if (!(isdigit((int)id[i]))) {
+ return (0);
+ }
}
-
- return(1);
-}
+ return (1);
+}
-/* Get full agent name (name + ip) of ID.
- */
-char *getFullnameById(char *id)
+/* Get full agent name (name + IP) of ID */
+char *getFullnameById(const char *id)
{
FILE *fp;
- char line_read[FILE_SIZE +1];
+ char line_read[FILE_SIZE + 1];
line_read[FILE_SIZE] = '\0';
/* ID must not be null */
- if(!id)
- return(NULL);
+ if (!id) {
+ return (NULL);
+ }
fp = fopen(AUTH_FILE, "r");
- if(!fp)
- return(NULL);
-
+ if (!fp) {
+ return (NULL);
+ }
- while(fgets(line_read, FILE_SIZE -1, fp) != NULL)
- {
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
char *name;
char *ip;
char *tmp_str;
- if(line_read[0] == '#')
- {
+ if (line_read[0] == '#') {
continue;
}
name = strchr(line_read, ' ');
- if(name)
- {
+ if (name) {
*name = '\0';
/* Didn't match */
- if(strcmp(line_read,id) != 0)
- {
+ if (strcmp(line_read, id) != 0) {
continue;
}
name++;
/* Removed entry */
- if(*name == '#')
- {
+ if (*name == '#') {
continue;
}
-
+
ip = strchr(name, ' ');
- if(ip)
- {
+ if (ip) {
*ip = '\0';
ip++;
- /* Cleaning up ip */
+ /* Clean up IP */
tmp_str = strchr(ip, ' ');
- if(tmp_str)
- {
+ if (tmp_str) {
char *final_str;
*tmp_str = '\0';
tmp_str = strchr(ip, '/');
- if(tmp_str)
+ if (tmp_str) {
*tmp_str = '\0';
+ }
/* If we reached here, we found the IP and name */
os_calloc(1, FILE_SIZE, final_str);
- snprintf(final_str, FILE_SIZE -1, "%s-%s", name, ip);
+ snprintf(final_str, FILE_SIZE - 1, "%s-%s", name, ip);
fclose(fp);
- return(final_str);
+ return (final_str);
}
}
}
}
fclose(fp);
- return(NULL);
+ return (NULL);
}
-
/* ID Search (is valid ID) */
-int IDExist(char *id)
+int IDExist(const char *id)
{
FILE *fp;
- char line_read[FILE_SIZE +1];
+ char line_read[FILE_SIZE + 1];
line_read[FILE_SIZE] = '\0';
-
- /* ID must not be null */
- if(!id)
- return(0);
- fp = fopen(AUTH_FILE, "r");
- if(!fp)
- return(0);
-
+ /* ID must not be null */
+ if (!id) {
+ return (0);
+ }
+
+ if (isChroot()) {
+ fp = fopen(AUTH_FILE, "r");
+ } else {
+ fp = fopen(KEYSFILE_PATH, "r");
+ }
+
+ if (!fp) {
+ return (0);
+ }
+
fseek(fp, 0, SEEK_SET);
fgetpos(fp, &fp_pos);
-
- while(fgets(line_read,FILE_SIZE -1, fp) != NULL)
- {
+
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
char *name;
- if(line_read[0] == '#')
- {
+ if (line_read[0] == '#') {
fgetpos(fp, &fp_pos);
continue;
}
-
+
name = strchr(line_read, ' ');
- if(name)
- {
+ if (name) {
*name = '\0';
name++;
- if(strcmp(line_read,id) == 0)
- {
+ if (strcmp(line_read, id) == 0) {
fclose(fp);
return (1); /*(fp_pos);*/
}
}
fclose(fp);
- return(0);
+ return (0);
}
-
-/* Validate agent name.
- */
-int OS_IsValidName(char *u_name)
+/* Validate agent name */
+int OS_IsValidName(const char *u_name)
{
- int i = 0;
+ size_t i, uname_length = strlen(u_name);
/* We must have something in the name */
- if(strlen(u_name) < 2 || strlen(u_name) > 128)
- return(0);
+ if (uname_length < 2 || uname_length > 128) {
+ return (0);
+ }
- /* check if it contains any non-alphanumeric characters */
- for(i = 0; i < strlen(u_name); i++)
- {
- if(!isalnum((int)u_name[i]) && (u_name[i] != '-') &&
- (u_name[i] != '_') && (u_name[i] != '.'))
- return(0);
+ /* Check if it contains any non-alphanumeric characters */
+ for (i = 0; i < uname_length; i++) {
+ if ( !( isalnum((int)u_name[i]) || (u_name[i] == '-') ||
+ (u_name[i] == '_') || (u_name[i] == '.') ||
+ (u_name[i] == ':') ) ) {
+ return (0);
+ }
}
- return(1);
+ return (1);
}
-
-/* Is_Name (is valid name) */
-int NameExist(char *u_name)
+int NameExist(const char *u_name)
{
FILE *fp;
- char line_read[FILE_SIZE +1];
+ char line_read[FILE_SIZE + 1];
line_read[FILE_SIZE] = '\0';
- if((!u_name)||
- (*u_name == '\0')||
- (*u_name == '\r')||
- (*u_name == '\n'))
- return(0);
+ if ((!u_name) ||
+ (*u_name == '\0') ||
+ (*u_name == '\r') ||
+ (*u_name == '\n')) {
+ return (0);
+ }
- fp = fopen(AUTH_FILE, "r");
- if(!fp)
- return(0);
+ if (isChroot()) {
+ fp = fopen(AUTH_FILE, "r");
+ } else {
+ fp = fopen(KEYSFILE_PATH, "r");
+ }
+ if (!fp) {
+ return (0);
+ }
fseek(fp, 0, SEEK_SET);
fgetpos(fp, &fp_pos);
-
- while(fgets(line_read, FILE_SIZE-1, fp) != NULL)
- {
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
char *name;
- if(line_read[0] == '#')
+ if (line_read[0] == '#') {
continue;
+ }
name = strchr(line_read, ' ');
- if(name)
- {
+ if (name) {
char *ip;
name++;
- if(*name == '#')
- {
+ if (*name == '#') {
continue;
}
-
+
ip = strchr(name, ' ');
- if(ip)
- {
+ if (ip) {
*ip = '\0';
- if(strcmp(u_name, name) == 0)
- {
+ if (strcmp(u_name, name) == 0) {
fclose(fp);
- return(1);
+ return (1);
}
}
}
}
fclose(fp);
- return(0);
+ return (0);
}
+/* Returns the ID of an agent, or NULL if not found */
+char *IPExist(const char *u_ip)
+{
+ FILE *fp;
+ char *name, *ip, *pass;
+ char line_read[FILE_SIZE + 1];
+ line_read[FILE_SIZE] = '\0';
+
+ if (!(u_ip && strncmp(u_ip, "any", 3)) || strchr(u_ip, '/'))
+ return NULL;
+
+ if (isChroot())
+ fp = fopen(AUTH_FILE, "r");
+ else
+ fp = fopen(KEYSFILE_PATH, "r");
-/* print available agents */
-int print_agents(int print_status, int active_only, int csv_output)
+ if (!fp)
+ return NULL;
+
+ fseek(fp, 0, SEEK_SET);
+ fgetpos(fp, &fp_pos);
+
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
+ if (line_read[0] == '#') {
+ continue;
+ }
+
+ name = strchr(line_read, ' ');
+ if (name) {
+ name++;
+
+ if (*name == '#') {
+ continue;
+ }
+
+ ip = strchr(name, ' ');
+ if (ip) {
+ ip++;
+
+ pass = strchr(ip, ' ');
+ if (pass) {
+ *pass = '\0';
+ if (strcmp(u_ip, ip) == 0) {
+ fclose(fp);
+ name[-1] = '\0';
+ return strdup(line_read);
+ }
+ }
+ }
+ }
+
+ fgetpos(fp, &fp_pos);
+ }
+
+ fclose(fp);
+ return NULL;
+}
+
+/* Returns the number of seconds since last agent connection, or -1 if error. */
+double OS_AgentAntiquity(const char *id)
+{
+ struct stat file_stat;
+ char file_name[OS_FLSIZE];
+ char *full_name = getFullnameById(id);
+
+ if (!full_name) {
+ return -1;
+ }
+
+ snprintf(file_name, OS_FLSIZE - 1, "%s/%s", AGENTINFO_DIR, full_name);
+
+ if (stat(file_name, &file_stat) < 0) {
+ if(full_name) {
+ free(full_name);
+ }
+ return -1;
+ }
+
+ free(full_name);
+
+ return difftime(time(NULL), file_stat.st_mtime);
+}
+
+/* Print available agents */
+int print_agents(int print_status, int active_only, int csv_output, cJSON *json_output)
{
int total = 0;
FILE *fp;
- char line_read[FILE_SIZE +1];
+ char line_read[FILE_SIZE + 1];
line_read[FILE_SIZE] = '\0';
fp = fopen(AUTH_FILE, "r");
- if(!fp)
- return(0);
+ if (!fp) {
+ return (0);
+ }
fseek(fp, 0, SEEK_SET);
-
- memset(line_read,'\0',FILE_SIZE);
-
- while(fgets(line_read, FILE_SIZE -1, fp) != NULL)
- {
+
+ memset(line_read, '\0', FILE_SIZE);
+
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
char *name;
- if(line_read[0] == '#')
+ if (line_read[0] == '#') {
continue;
-
+ }
+
name = strchr(line_read, ' ');
- if(name)
- {
+ if (name) {
char *ip;
*name = '\0';
name++;
-
- /* Removed agent. */
- if(*name == '#')
- {
+ /* Removed agent */
+ if (*name == '#') {
continue;
}
-
+
ip = strchr(name, ' ');
- if(ip)
- {
+ if (ip) {
char *key;
*ip = '\0';
ip++;
key = strchr(ip, ' ');
- if(key)
- {
+ if (key) {
*key = '\0';
- if(!total && !print_status)
+ if (!total && !print_status) {
printf(PRINT_AVAILABLE);
+ }
total++;
-
- if(print_status)
- {
+ if (print_status) {
int agt_status = get_agent_status(name, ip);
- if(active_only && (agt_status != GA_STATUS_ACTIVE))
- {
+ if (active_only && (agt_status != GA_STATUS_ACTIVE)) {
continue;
}
-
- if(csv_output)
- {
- printf("%s,%s,%s,%s,\n", line_read, name, ip,
- print_agent_status(agt_status));
- }
- else
- {
- printf(PRINT_AGENT_STATUS, line_read, name, ip,
- print_agent_status(agt_status));
+
+ if (csv_output) {
+ printf("%s,%s,%s,%s,\n", line_read, name, ip, print_agent_status(agt_status));
+ } else if (json_output) {
+ cJSON *json_agent = cJSON_CreateObject();
+
+ if (!json_agent)
+ return 0;
+
+ cJSON_AddStringToObject(json_agent, "id", line_read);
+ cJSON_AddStringToObject(json_agent, "name", name);
+ cJSON_AddStringToObject(json_agent, "ip", ip);
+ cJSON_AddStringToObject(json_agent, "status", print_agent_status(agt_status));
+ cJSON_AddItemToArray(json_output, json_agent);
+ } else {
+ printf(PRINT_AGENT_STATUS, line_read, name, ip, print_agent_status(agt_status));
}
- }
- else
- {
+ } else {
printf(PRINT_AGENT, line_read, name, ip);
}
}
-
}
}
}
-
/* Only print agentless for non-active only searches */
- if(!active_only && print_status)
- {
- char *aip = NULL;
+ if (!active_only && print_status) {
+ const char *aip = NULL;
DIR *dirp;
struct dirent *dp;
-
- if(!csv_output)
- {
+
+ if (!csv_output && !json_output) {
printf("\nList of agentless devices:\n");
}
dirp = opendir(AGENTLESS_ENTRYDIR);
- if(dirp)
- {
- while ((dp = readdir(dirp)) != NULL)
- {
- if(strncmp(dp->d_name, ".", 1) == 0)
- {
+ if (dirp) {
+ while ((dp = readdir(dirp)) != NULL) {
+ if (strncmp(dp->d_name, ".", 1) == 0) {
continue;
}
aip = strchr(dp->d_name, '@');
- if(aip)
- {
+ if (aip) {
aip++;
- }
- else
- {
+ } else {
aip = "<na>";
}
- if(csv_output)
- {
+ if (csv_output) {
printf("na,%s,%s,agentless,\n", dp->d_name, aip);
- }
- else
- {
+ } else {
printf(" ID: na, Name: %s, IP: %s, agentless\n",
dp->d_name, aip);
}
}
fclose(fp);
- if(total)
- return(1);
-
- return(0);
+ if (total) {
+ return (1);
+ }
+
+ return (0);
}
+void FormatID(char *id) {
+ int number;
+ char *end;
+
+ if (id && *id) {
+ number = strtol(id, &end, 10);
-/* EOF */
+ if (!*end) {
+ sprintf(id, "%03d", number);
+ }
+ }
+}