X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?a=blobdiff_plain;ds=sidebyside;f=src%2Faddagent%2Fmanage_agents.c;h=ac39c1e662d33f6be4685fac15b928d1d3d6c224;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hp=9416449fa2deb94a9b568747c08421a38ed0f772;hpb=927951d1c1ad45ba9e7325f07d996154a91c911b;p=ossec-hids.git diff --git a/src/addagent/manage_agents.c b/src/addagent/manage_agents.c old mode 100755 new mode 100644 index 9416449..ac39c1e --- a/src/addagent/manage_agents.c +++ b/src/addagent/manage_agents.c @@ -1,84 +1,73 @@ -/* @(#) $Id: ./src/addagent/manage_agents.c, 2012/02/07 dcid Exp $ - */ - -/* Copyright (C) 2009 Trend Micro Inc. +/* Copyright (C) 2019 OSSEC Foundation * All rights reserved. * * This program is a free software; you can redistribute it * and/or modify it under the terms of the GNU General Public * License (version 2) as published by the FSF - Free Software * Foundation. - * - * License details at the LICENSE file included with OSSEC or - * online at: http://www.ossec.net/en/licensing.html */ - /* Manage agents tool - * Add/extract and remove agents from a server. + * Add/extract and remove agents from a server */ - #include "manage_agents.h" #include "os_crypto/md5/md5_op.h" +#include "external/cJSON/cJSON.h" #include - -/* Global internal variables */ +/* Global variables */ +int restart_necessary; +time_t time1; +time_t time2; +time_t time3; +long int rand1; +long int rand2; - -/* chomp: remove spaces, new lines, etc from a string */ +/* Remove spaces, newlines, etc from a string */ char *chomp(char *str) { char *tmp_str; - int size = 0; + ssize_t size; - /* Removing spaces from the beginning */ - while(*str == ' ' || *str == '\t') + /* Remove spaces from the beginning */ + while (*str == ' ' || *str == '\t') { str++; + } - - /* Removing any trailing new lines or \r */ - do - { + /* Remove any trailing newlines or \r */ + do { tmp_str = strchr(str, '\n'); - if(tmp_str) - { + if (tmp_str) { *tmp_str = '\0'; continue; } tmp_str = strchr(str, '\r'); - if(tmp_str) - { + if (tmp_str) { *tmp_str = '\0'; } - }while(tmp_str != NULL); + } while (tmp_str != NULL); - - /* Removing spaces at the end of the string */ + /* Remove spaces at the end of the string */ tmp_str = str; - size = strlen(str)-1; + size = (ssize_t) strlen(str) - 1; - while((size >= 0) && (tmp_str[size] == ' ' || tmp_str[size] == '\t')) - { + while ((size >= 0) && (tmp_str[size] == ' ' || tmp_str[size] == '\t')) { tmp_str[size] = '\0'; size--; } - return(str); + return (str); } - - -/* Add an agent */ -int add_agent() +int add_agent(int json_output) { int i = 1; FILE *fp; - char str1[STR_SIZE +1]; - char str2[STR_SIZE +1]; + char str1[STR_SIZE + 1]; + char str2[STR_SIZE + 1]; os_md5 md1; os_md5 md2; @@ -88,365 +77,493 @@ int add_agent() char *_id; char *_ip; - char name[FILE_SIZE +1]; - char id[FILE_SIZE +1]; - char ip[FILE_SIZE +1]; - os_ip *c_ip; + char name[FILE_SIZE + 1]; + char id[FILE_SIZE + 1] = { '\0' }; + char ip[FILE_SIZE + 1]; + os_ip c_ip; + c_ip.ip = NULL; + char authfile[257]; - /* Checking if we can open the auth_file */ - fp = fopen(AUTH_FILE,"a"); - if(!fp) - { - ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE); + if(willchroot > 0) { + snprintf(authfile, 256, "%s", AUTH_FILE); //XXX + } else { + const char *dir = DEFAULTDIR; + snprintf(authfile, 256, "%s/%s", dir, AUTH_FILE); //XXX } - fclose(fp); - - /* Allocating for c_ip */ - os_calloc(1, sizeof(os_ip), c_ip); + char *id_exist = NULL; + int force_antiquity; + + /* Check if we can open the auth_file */ + fp = fopen(authfile, "a"); + if (!fp) { + if (json_output) { + char buffer[1024]; + cJSON *json_root = cJSON_CreateObject(); + snprintf(buffer, 1023, "Could not open file '%s' due to [(%d)-(%s)]", AUTH_FILE, errno, strerror(errno)); + cJSON_AddNumberToObject(json_root, "error", 71); + cJSON_AddStringToObject(json_root, "description", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE, errno, strerror(errno)); + } + fclose(fp); - #ifndef WIN32 - chmod(AUTH_FILE, 0440); - #endif - /* Setting time 2 */ - time2 = time(0); +#ifndef WIN32 + if (chmod(authfile, 0440) == -1) { + if (json_output) { + char buffer[1024]; + cJSON *json_root = cJSON_CreateObject(); + snprintf(buffer, 1023, "Could not chmod object '%s' due to [(%d)-(%s)]", AUTH_FILE, errno, strerror(errno)); + cJSON_AddNumberToObject(json_root, "error", 71); + cJSON_AddStringToObject(json_root, "description", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + ErrorExit(CHMOD_ERROR, ARGV0, AUTH_FILE, errno, strerror(errno)); + } +#endif - /* Source is time1+ time2 +pid + ppid */ - #ifndef WIN32 - #ifdef __OpenBSD__ - srandomdev(); - #else - srandom(time2 + time1 + getpid() + getppid()); - #endif - #else - srandom(time2 + time1 + getpid()); - #endif + /* Set time 2 */ + time2 = time(0); rand1 = random(); + /* Zero strings */ + memset(str1, '\0', STR_SIZE + 1); + memset(str2, '\0', STR_SIZE + 1); - /* Zeroing strings */ - memset(str1,'\0', STR_SIZE +1); - memset(str2,'\0', STR_SIZE +1); - - - printf(ADD_NEW); + if (!json_output) + printf(ADD_NEW); + /* Get the name */ + memset(name, '\0', FILE_SIZE + 1); - /* Getting the name */ - memset(name, '\0', FILE_SIZE +1); - - do - { - printf(ADD_NAME); - fflush(stdout); + do { + if (!json_output) { + printf(ADD_NAME); + fflush(stdout); + } /* Read the agent's name from user environment. If it is invalid - * we should force user to provide a name from input device. */ + * we should force user to provide a name from input device. + */ _name = getenv("OSSEC_AGENT_NAME"); - if (_name == NULL || NameExist(_name) || !OS_IsValidName(_name)) - _name = read_from_user(); + if (_name == NULL || NameExist(_name) || !OS_IsValidName(_name)) { + if (json_output) { + cJSON *json_root = cJSON_CreateObject(); + cJSON_AddNumberToObject(json_root, "error", 76); + cJSON_AddStringToObject(json_root, "description", "Invalid name for agent"); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + _name = read_from_user(); - if(strcmp(_name, QUIT) == 0) - return(0); + } - strncpy(name, _name, FILE_SIZE -1); + if (strcmp(_name, QUIT) == 0) { + goto cleanup; + } - /* check the name */ - if(!OS_IsValidName(name)) - printf(INVALID_NAME,name); + strncpy(name, _name, FILE_SIZE - 1); + + /* Check the name */ + if (!OS_IsValidName(name)) { + printf(INVALID_NAME, name); + } /* Search for name -- no duplicates */ - if(NameExist(name)) + if (NameExist(name)) { printf(ADD_ERROR_NAME, name); + } + } while (NameExist(name) || !OS_IsValidName(name)); - } while(NameExist(name) || !OS_IsValidName(name)); - + /* Get IP */ + memset(ip, '\0', FILE_SIZE + 1); - /* Getting IP */ - memset(ip, '\0', FILE_SIZE +1); + do { + if (!json_output) { + printf(ADD_IP); + fflush(stdout); + } - do - { - printf(ADD_IP); - fflush(stdout); - /* Read IP address from user's environment. If that IP is invalid, - * force user to provide IP from input device */ - _ip = getenv("OSSEC_AGENT_IP"); - if (_ip == NULL || !OS_IsValidIP(_ip, c_ip)) - _ip = read_from_user(); + /* Read IP address from user's environment. If that IP is invalid, + * force user to provide IP from input device */ + _ip = getenv("OSSEC_AGENT_IP"); + if (_ip == NULL || !OS_IsValidIP(_ip, &c_ip)) { + if (json_output) { + cJSON *json_root = cJSON_CreateObject(); + cJSON_AddNumberToObject(json_root, "error", 77); + cJSON_AddStringToObject(json_root, "description", "Invalid IP for agent"); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + _ip = read_from_user(); - /* quit */ - if(strcmp(_ip, QUIT) == 0) - return(0); + } - strncpy(ip, _ip, FILE_SIZE -1); + /* Quit */ + if (strcmp(_ip, QUIT) == 0) { + goto cleanup; + } - if(!OS_IsValidIP(ip, c_ip)) - { - printf(IP_ERROR, ip); - _ip = NULL; - } + strncpy(ip, _ip, FILE_SIZE - 1); - } while(!_ip); + if (!OS_IsValidIP(ip, &c_ip)) { + printf(IP_ERROR, ip); + _ip = NULL; + } else if ((id_exist = IPExist(ip))) { + double antiquity = -1; + const char *env_remove_dup = getenv("OSSEC_REMOVE_DUPLICATED"); - do - { - /* Default ID */ - i = MAX_AGENTS + 32512; - snprintf(id, 8, "%03d", i); - while(!IDExist(id)) - { - i--; - snprintf(id, 8, "%03d", i); + if (env_remove_dup) { + force_antiquity = strtol(env_remove_dup, NULL, 10); + antiquity = OS_AgentAntiquity(id_exist); + } - /* No key present, use id 0 */ - if(i <= 0) - { - i = 0; - break; + if (env_remove_dup && (antiquity >= force_antiquity || antiquity < 0)) { + /* TODO: Save backup */ +#ifdef REUSE_ID + strncpy(id, id_exist, FILE_SIZE); +#endif + OS_RemoveAgent(id_exist); + } else { + /* TODO: Send alert */ + + if (json_output) { + cJSON *json_root = cJSON_CreateObject(); + cJSON_AddNumberToObject(json_root, "error", 79); + cJSON_AddStringToObject(json_root, "description", "Duplicated IP for agent"); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else { + printf(IP_DUP_ERROR, ip); + _ip = NULL; + } } } - snprintf(id, 8, "%03d", i+1); - - /* Getting ID */ - printf(ADD_ID, id); - fflush(stdout); - /* Get Agent id from environment. If 0, use default ID. If null, - * get from user input. If value from environment is invalid, - * we force user to specify an ID from the terminal. Otherwise, - * our program goes to infinite loop. */ - _id = getenv("OSSEC_AGENT_ID"); - if (_id == NULL || IDExist(_id) || !OS_IsValidID(_id)) { - _id = read_from_user(); - } + } while (!_ip); + + if (!*id) { + do { + /* Default ID */ + i = MAX_AGENTS + 32512; + snprintf(id, 8, "%03d", i); //XXX + while (!IDExist(id)) { + i--; + snprintf(id, 8, "%03d", i); + + /* No key present, use id 0 */ + if (i <= 0) { + i = 0; + break; + } + } + snprintf(id, 8, "%03d", i + 1); + + /* Get ID */ + if (!json_output) { + printf(ADD_ID, id); + fflush(stdout); + } + + + /* Get Agent ID from environment. If 0, use default ID. If null, + * get from user input. If value from environment is invalid, + * we force user to specify an ID from the terminal. Otherwise, + * our program goes to infinite loop. + */ + _id = getenv("OSSEC_AGENT_ID"); + if (_id == NULL || IDExist(_id) || !OS_IsValidID(_id)) { + _id = read_from_user(); + } + + /* Quit */ + if (strcmp(_id, QUIT) == 0) { + goto cleanup; + } + + if (_id[0] != '\0' && strcmp(_id, "0")) { + strncpy(id, _id, FILE_SIZE - 1); + } + + if (OS_IsValidID(id)) { + FormatID(id); + } else { + printf(INVALID_ID, id); + } + + /* Search for ID KEY -- no duplicates */ + if (IDExist(id)) { + printf(ADD_ERROR_ID, id); + } + + } while (IDExist(id) || !OS_IsValidID(id)); + } - /* If user specified 0 as Agent ID, he meant use default value. - * NOTE: a bad condistion can cause infinite loop. */ - if (strcmp(_id,"0") == 0) { - strncpy(_id, id, FILE_SIZE -1); - } + if (!json_output) { + printf(AGENT_INFO, id, name, ip); + fflush(stdout); + } - /* quit */ - if(strcmp(_id, QUIT) == 0) - return(0); + do { + if (!json_output) + printf(ADD_CONFIRM); - if(_id[0] != '\0') - { - strncpy(id, _id, FILE_SIZE -1); + /* Confirmation by an environment variable. The valid value is y/Y. + * If the user provides anything other string, it is considered as + * n/N; please note that the old code only accepts y/Y/n/N. So if + * the variable OSSEC_ACTION_CONFIRMED is 'foobar', the program will + * go into an infinite loop. + */ + user_input = getenv("OSSEC_ACTION_CONFIRMED"); + if (user_input == NULL) { + user_input = read_from_user(); } - if(!OS_IsValidID(id)) - printf(INVALID_ID, id); + /* If user accepts to add */ + if (user_input[0] == 'y' || user_input[0] == 'Y') { + time3 = time(0); + rand2 = random(); + + fp = fopen(authfile, "a"); + if (!fp) { + if (json_output) { + char buffer[1024]; + cJSON *json_root = cJSON_CreateObject(); + snprintf(buffer, 1023, "Could not open file '%s' due to [(%d)-(%s)]", KEYS_FILE, errno, strerror(errno)); + cJSON_AddNumberToObject(json_root, "error", 71); + cJSON_AddStringToObject(json_root, "description", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE, errno, strerror(errno)); + } +#ifndef WIN32 + if ((chmod(authfile, 0440)) != 0) { + if(json_output) { + char buffer[1024]; + snprintf(buffer, 1023, "%s: Could not chmod file %s due to [(%d)-(%s)]", ARGV0, authfile, errno, strerror(errno)); + cJSON *json_root = cJSON_CreateObject(); + cJSON_AddNumberToObject(json_root, "error", 76); + cJSON_AddStringToObject(json_root, "description", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(errno); + } else { + ErrorExit("%s: Cannot chmod %s: %s", ARGV0, authfile, strerror(errno)); + } + } +#endif - /* Search for ID KEY -- no duplicates */ - if(IDExist(id)) - printf(ADD_ERROR_ID, id); + /* Random 1: Time took to write the agent information + * Random 2: Time took to choose the action + * Random 3: All of this + time + pid + * Random 4: Md5 all of this + the name, key and IP + * Random 5: Final key + */ - } while(IDExist(id) || !OS_IsValidID(id)); + snprintf(str1, STR_SIZE, "%d%s%d", (int)(time3 - time2), name, (int)rand1); + snprintf(str2, STR_SIZE, "%d%s%s%d", (int)(time2 - time1), ip, id, (int)rand2); + OS_MD5_Str(str1, md1); + OS_MD5_Str(str2, md2); + snprintf(str1, STR_SIZE, "%s%d%d%d", md1, (int)getpid(), (int)random(), + (int)time3); + OS_MD5_Str(str1, md1); - printf(AGENT_INFO, id, name, ip); - fflush(stdout); + fprintf(fp, "%s %s %s %s%s\n", id, name, c_ip.ip, md1, md2); + fclose(fp); - do - { - printf(ADD_CONFIRM); - /* Confirmation by an environment variable. The valid value is y/Y. - * If the user provide anything other string, it is considered as - * n/N; please note that the old code only accepts y/Y/n/N. So if - * the variable OSSEC_ACTION_CONFIRMED is 'foobar', the program will - * go into an infinite loop. */ - user_input = getenv("OSSEC_ACTION_CONFIRMED"); - if (user_input == NULL) user_input = read_from_user(); + if (json_output) { + char buffer[1024]; + cJSON *json_root = cJSON_CreateObject(); + snprintf(buffer, 1023, "Agent added with ID %s", id); + cJSON_AddNumberToObject(json_root, "error", 0); + cJSON_AddStringToObject(json_root, "response", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + } else + printf(AGENT_ADD, id); - /* If user accepts to add */ - if(user_input[0] == 'y' || user_input[0] == 'Y') - { - time3 = time(0); - rand2 = random(); - fp = fopen(AUTH_FILE,"a"); - if(!fp) - { - ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE); + restart_necessary = 1; + break; + } else { /* if(user_input[0] == 'n' || user_input[0] == 'N') */ + printf(ADD_NOT); + break; } - #ifndef WIN32 - chmod(AUTH_FILE, 0440); - #endif + } while (1); + cleanup: + free(c_ip.ip); - /* Random 1: Time took to write the agent information. - * Random 2: Time took to choose the action. - * Random 3: All of this + time + pid - * Random 4: Md5 all of this + the name, key and ip - * Random 5: Final key - */ - - snprintf(str1, STR_SIZE, "%d%s%d",time3-time2, name, rand1); - snprintf(str2, STR_SIZE, "%d%s%s%d", time2-time1, ip, id, rand2); - - OS_MD5_Str(str1, md1); - OS_MD5_Str(str2, md2); - - snprintf(str1, STR_SIZE, "%s%d%d%d",md1,(int)getpid(), (int)random(), - time3); - OS_MD5_Str(str1, md1); - - fprintf(fp,"%s %s %s %s%s\n",id, name, c_ip->ip, md1,md2); - - fclose(fp); - - printf(AGENT_ADD); - restart_necessary = 1; - break; - } - else /* if(user_input[0] == 'n' || user_input[0] == 'N') */ - { - printf(ADD_NOT); - break; - } - - } while(1); - - return(0); + return (0); } - -/* remove an agent */ -int remove_agent() +int remove_agent(int json_output) { FILE *fp; char *user_input; - char u_id[FILE_SIZE +1]; + char u_id[FILE_SIZE + 1]; int id_exist; u_id[FILE_SIZE] = '\0'; - id_exist = FALSE; - if(!print_agents(0, 0, 0)) - { - printf(NO_AGENT); - return(0); + extern int willchroot; + char authfile[257]; + if(willchroot > 0) { + snprintf(authfile, 256, "%s", AUTH_FILE); //XXX + } else { + const char *dir = DEFAULTDIR; + snprintf(authfile, 256, "%s/%s", dir, AUTH_FILE); //XXX } + - do - { - printf(REMOVE_ID); - fflush(stdout); - user_input = getenv("OSSEC_AGENT_ID"); - if (user_input == NULL) { - user_input = read_from_user(); - } else { - printf("%s\n", user_input); - } + if (!(json_output || print_agents(0, 0, 0, 0))) { + printf(NO_AGENT); + return (0); + } - if(strcmp(user_input, QUIT) == 0) - return(0); + do { + if (!json_output) { + printf(REMOVE_ID); + fflush(stdout); + } - strncpy(u_id, user_input, FILE_SIZE); + user_input = getenv("OSSEC_AGENT_ID"); + if (user_input == NULL) { + user_input = read_from_user(); + } else if (!json_output) { + printf("%s\n", user_input); + } - id_exist = IDExist(user_input); + if (strcmp(user_input, QUIT) == 0) { + return (0); + } - if(!id_exist) - { - printf(NO_ID, user_input); + FormatID(user_input); + strncpy(u_id, user_input, FILE_SIZE); + + id_exist = IDExist(user_input); + + if (!id_exist) { + if (json_output) { + char buffer[1024]; + cJSON *json_root = cJSON_CreateObject(); + snprintf(buffer, 1023, "Invalid ID '%s' given. ID is not present", user_input); + cJSON_AddNumberToObject(json_root, "error", 78); + cJSON_AddStringToObject(json_root, "description", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + printf(NO_ID, user_input); + + + /* Exit here if we are using environment variables + * and our ID does not exist + */ + if (getenv("OSSEC_AGENT_ID")) { + return (1); + } + } + } while (!id_exist); + + do { + if (!json_output) { + printf(REMOVE_CONFIRM); + fflush(stdout); + } - /* Exit here if we are using environment variables - * and our ID does not exist - */ - if(getenv("OSSEC_AGENT_ID")) - return(1); - } - } while(!id_exist); - - do - { - printf(REMOVE_CONFIRM); - fflush(stdout); user_input = getenv("OSSEC_ACTION_CONFIRMED"); if (user_input == NULL) { - user_input = read_from_user(); - } else { - printf("%s\n", user_input); + user_input = read_from_user(); + } else if (!json_output) { + printf("%s\n", user_input); } - - /* If user confirm */ - if(user_input[0] == 'y' || user_input[0] == 'Y') - { - /* Getting full agent name */ + + /* If user confirms */ + if (user_input[0] == 'y' || user_input[0] == 'Y') { + /* Get full agent name */ char *full_name = getFullnameById(u_id); - if(!full_name) - { - printf(NO_ID, u_id); - return(1); + if (!full_name) { + if (json_output) { + char buffer[1024]; + cJSON *json_root = cJSON_CreateObject(); + snprintf(buffer, 1023, "Invalid ID '%s' given. ID is not present", u_id); + cJSON_AddNumberToObject(json_root, "error", 78); + cJSON_AddStringToObject(json_root, "description", buffer); + printf("%s", cJSON_PrintUnformatted(json_root)); + exit(1); + } else + printf(NO_ID, u_id); + return (1); } - fp = fopen(AUTH_FILE, "r+"); - if(!fp) - { + fp = fopen(authfile, "r+"); + if (!fp) { free(full_name); - ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE); + ErrorExit(FOPEN_ERROR, ARGV0, authfile, errno, strerror(errno)); } - #ifndef WIN32 - chmod(AUTH_FILE, 0440); - #endif - +#ifndef WIN32 + chmod(authfile, 0440); +#endif - /* Removing the agent, but keeping the id. */ + /* Remove the agent, but keep the id */ fsetpos(fp, &fp_pos); +#ifdef REUSE_ID + fprintf(fp, "#%s #*#*#*#*#*#*#*#*#*#*#", u_id); +#else fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id); +#endif fclose(fp); - - /* Remove counter for id */ + /* Remove counter for ID */ delete_agentinfo(full_name); OS_RemoveCounter(u_id); free(full_name); full_name = NULL; + if (json_output) { + cJSON *json_root = cJSON_CreateObject(); + cJSON_AddNumberToObject(json_root, "error", 0); + cJSON_AddStringToObject(json_root, "response", "Agent removed"); + printf("%s", cJSON_PrintUnformatted(json_root)); + } else + printf(REMOVE_DONE, u_id); - printf(REMOVE_DONE, u_id); restart_necessary = 1; break; - } - else /* if(user_input[0] == 'n' || user_input[0] == 'N') */ - { + } else { /* if(user_input[0] == 'n' || user_input[0] == 'N') */ printf(REMOVE_NOT); break; } + } while (1); - } while(1); - - return(0); + return (0); } - int list_agents(int cmdlist) { - if(!print_agents(0, 0, 0)) + if (!print_agents(0, 0, 0, 0)) { printf(NO_AGENT); + } printf("\n"); - if(!cmdlist) - { + if (!cmdlist) { printf(PRESS_ENTER); read_from_user(); } - return(0); - + return (0); } - -/* EOF */