1 /* Copyright (C) 2019 OSSEC Foundation
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 * Add/extract and remove agents from a server
14 #include "manage_agents.h"
15 #include "os_crypto/md5/md5_op.h"
16 #include "external/cJSON/cJSON.h"
19 /* Global variables */
20 int restart_necessary;
28 /* Remove spaces, newlines, etc from a string */
29 char *chomp(char *str)
34 /* Remove spaces from the beginning */
35 while (*str == ' ' || *str == '\t') {
39 /* Remove any trailing newlines or \r */
41 tmp_str = strchr(str, '\n');
47 tmp_str = strchr(str, '\r');
51 } while (tmp_str != NULL);
53 /* Remove spaces at the end of the string */
55 size = (ssize_t) strlen(str) - 1;
57 while ((size >= 0) && (tmp_str[size] == ' ' || tmp_str[size] == '\t')) {
65 int add_agent(int json_output)
69 char str1[STR_SIZE + 1];
70 char str2[STR_SIZE + 1];
80 char name[FILE_SIZE + 1];
81 char id[FILE_SIZE + 1] = { '\0' };
82 char ip[FILE_SIZE + 1];
89 snprintf(authfile, 256, "%s", AUTH_FILE); //XXX
91 const char *dir = DEFAULTDIR;
92 snprintf(authfile, 256, "%s/%s", dir, AUTH_FILE); //XXX
96 char *id_exist = NULL;
99 /* Check if we can open the auth_file */
100 fp = fopen(authfile, "a");
104 cJSON *json_root = cJSON_CreateObject();
105 snprintf(buffer, 1023, "Could not open file '%s' due to [(%d)-(%s)]", AUTH_FILE, errno, strerror(errno));
106 cJSON_AddNumberToObject(json_root, "error", 71);
107 cJSON_AddStringToObject(json_root, "description", buffer);
108 printf("%s", cJSON_PrintUnformatted(json_root));
111 ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE, errno, strerror(errno));
117 if (chmod(authfile, 0440) == -1) {
120 cJSON *json_root = cJSON_CreateObject();
121 snprintf(buffer, 1023, "Could not chmod object '%s' due to [(%d)-(%s)]", AUTH_FILE, errno, strerror(errno));
122 cJSON_AddNumberToObject(json_root, "error", 71);
123 cJSON_AddStringToObject(json_root, "description", buffer);
124 printf("%s", cJSON_PrintUnformatted(json_root));
127 ErrorExit(CHMOD_ERROR, ARGV0, AUTH_FILE, errno, strerror(errno));
138 memset(str1, '\0', STR_SIZE + 1);
139 memset(str2, '\0', STR_SIZE + 1);
145 memset(name, '\0', FILE_SIZE + 1);
152 /* Read the agent's name from user environment. If it is invalid
153 * we should force user to provide a name from input device.
155 _name = getenv("OSSEC_AGENT_NAME");
156 if (_name == NULL || NameExist(_name) || !OS_IsValidName(_name)) {
158 cJSON *json_root = cJSON_CreateObject();
159 cJSON_AddNumberToObject(json_root, "error", 76);
160 cJSON_AddStringToObject(json_root, "description", "Invalid name for agent");
161 printf("%s", cJSON_PrintUnformatted(json_root));
164 _name = read_from_user();
168 if (strcmp(_name, QUIT) == 0) {
172 strncpy(name, _name, FILE_SIZE - 1);
175 if (!OS_IsValidName(name)) {
176 printf(INVALID_NAME, name);
179 /* Search for name -- no duplicates */
180 if (NameExist(name)) {
181 printf(ADD_ERROR_NAME, name);
183 } while (NameExist(name) || !OS_IsValidName(name));
186 memset(ip, '\0', FILE_SIZE + 1);
195 /* Read IP address from user's environment. If that IP is invalid,
196 * force user to provide IP from input device */
197 _ip = getenv("OSSEC_AGENT_IP");
198 if (_ip == NULL || !OS_IsValidIP(_ip, &c_ip)) {
200 cJSON *json_root = cJSON_CreateObject();
201 cJSON_AddNumberToObject(json_root, "error", 77);
202 cJSON_AddStringToObject(json_root, "description", "Invalid IP for agent");
203 printf("%s", cJSON_PrintUnformatted(json_root));
206 _ip = read_from_user();
211 if (strcmp(_ip, QUIT) == 0) {
215 strncpy(ip, _ip, FILE_SIZE - 1);
217 if (!OS_IsValidIP(ip, &c_ip)) {
218 printf(IP_ERROR, ip);
220 } else if ((id_exist = IPExist(ip))) {
221 double antiquity = -1;
223 const char *env_remove_dup = getenv("OSSEC_REMOVE_DUPLICATED");
225 if (env_remove_dup) {
226 force_antiquity = strtol(env_remove_dup, NULL, 10);
227 antiquity = OS_AgentAntiquity(id_exist);
230 if (env_remove_dup && (antiquity >= force_antiquity || antiquity < 0)) {
231 /* TODO: Save backup */
233 strncpy(id, id_exist, FILE_SIZE);
235 OS_RemoveAgent(id_exist);
237 /* TODO: Send alert */
240 cJSON *json_root = cJSON_CreateObject();
241 cJSON_AddNumberToObject(json_root, "error", 79);
242 cJSON_AddStringToObject(json_root, "description", "Duplicated IP for agent");
243 printf("%s", cJSON_PrintUnformatted(json_root));
246 printf(IP_DUP_ERROR, ip);
257 i = MAX_AGENTS + 32512;
258 snprintf(id, 8, "%03d", i); //XXX
259 while (!IDExist(id)) {
261 snprintf(id, 8, "%03d", i);
263 /* No key present, use id 0 */
269 snprintf(id, 8, "%03d", i + 1);
278 /* Get Agent ID from environment. If 0, use default ID. If null,
279 * get from user input. If value from environment is invalid,
280 * we force user to specify an ID from the terminal. Otherwise,
281 * our program goes to infinite loop.
283 _id = getenv("OSSEC_AGENT_ID");
284 if (_id == NULL || IDExist(_id) || !OS_IsValidID(_id)) {
285 _id = read_from_user();
289 if (strcmp(_id, QUIT) == 0) {
293 if (_id[0] != '\0' && strcmp(_id, "0")) {
294 strncpy(id, _id, FILE_SIZE - 1);
297 if (OS_IsValidID(id)) {
300 printf(INVALID_ID, id);
303 /* Search for ID KEY -- no duplicates */
305 printf(ADD_ERROR_ID, id);
308 } while (IDExist(id) || !OS_IsValidID(id));
312 printf(AGENT_INFO, id, name, ip);
321 /* Confirmation by an environment variable. The valid value is y/Y.
322 * If the user provides anything other string, it is considered as
323 * n/N; please note that the old code only accepts y/Y/n/N. So if
324 * the variable OSSEC_ACTION_CONFIRMED is 'foobar', the program will
325 * go into an infinite loop.
327 user_input = getenv("OSSEC_ACTION_CONFIRMED");
328 if (user_input == NULL) {
329 user_input = read_from_user();
332 /* If user accepts to add */
333 if (user_input[0] == 'y' || user_input[0] == 'Y') {
337 fp = fopen(authfile, "a");
341 cJSON *json_root = cJSON_CreateObject();
342 snprintf(buffer, 1023, "Could not open file '%s' due to [(%d)-(%s)]", KEYS_FILE, errno, strerror(errno));
343 cJSON_AddNumberToObject(json_root, "error", 71);
344 cJSON_AddStringToObject(json_root, "description", buffer);
345 printf("%s", cJSON_PrintUnformatted(json_root));
348 ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE, errno, strerror(errno));
351 if ((chmod(authfile, 0440)) != 0) {
354 snprintf(buffer, 1023, "%s: Could not chmod file %s due to [(%d)-(%s)]", ARGV0, authfile, errno, strerror(errno));
355 cJSON *json_root = cJSON_CreateObject();
356 cJSON_AddNumberToObject(json_root, "error", 76);
357 cJSON_AddStringToObject(json_root, "description", buffer);
358 printf("%s", cJSON_PrintUnformatted(json_root));
361 ErrorExit("%s: Cannot chmod %s: %s", ARGV0, authfile, strerror(errno));
366 /* Random 1: Time took to write the agent information
367 * Random 2: Time took to choose the action
368 * Random 3: All of this + time + pid
369 * Random 4: Md5 all of this + the name, key and IP
370 * Random 5: Final key
373 snprintf(str1, STR_SIZE, "%d%s%d", (int)(time3 - time2), name, (int)rand1);
374 snprintf(str2, STR_SIZE, "%d%s%s%d", (int)(time2 - time1), ip, id, (int)rand2);
376 OS_MD5_Str(str1, md1);
377 OS_MD5_Str(str2, md2);
379 snprintf(str1, STR_SIZE, "%s%d%d%d", md1, (int)getpid(), (int)random(),
381 OS_MD5_Str(str1, md1);
383 fprintf(fp, "%s %s %s %s%s\n", id, name, c_ip.ip, md1, md2);
388 cJSON *json_root = cJSON_CreateObject();
389 snprintf(buffer, 1023, "Agent added with ID %s", id);
390 cJSON_AddNumberToObject(json_root, "error", 0);
391 cJSON_AddStringToObject(json_root, "response", buffer);
392 printf("%s", cJSON_PrintUnformatted(json_root));
394 printf(AGENT_ADD, id);
397 restart_necessary = 1;
399 } else { /* if(user_input[0] == 'n' || user_input[0] == 'N') */
411 int remove_agent(int json_output)
415 char u_id[FILE_SIZE + 1];
418 u_id[FILE_SIZE] = '\0';
420 extern int willchroot;
423 snprintf(authfile, 256, "%s", AUTH_FILE); //XXX
425 const char *dir = DEFAULTDIR;
426 snprintf(authfile, 256, "%s/%s", dir, AUTH_FILE); //XXX
431 if (!(json_output || print_agents(0, 0, 0, 0))) {
442 user_input = getenv("OSSEC_AGENT_ID");
443 if (user_input == NULL) {
444 user_input = read_from_user();
445 } else if (!json_output) {
446 printf("%s\n", user_input);
449 if (strcmp(user_input, QUIT) == 0) {
453 FormatID(user_input);
454 strncpy(u_id, user_input, FILE_SIZE);
456 id_exist = IDExist(user_input);
461 cJSON *json_root = cJSON_CreateObject();
462 snprintf(buffer, 1023, "Invalid ID '%s' given. ID is not present", user_input);
463 cJSON_AddNumberToObject(json_root, "error", 78);
464 cJSON_AddStringToObject(json_root, "description", buffer);
465 printf("%s", cJSON_PrintUnformatted(json_root));
468 printf(NO_ID, user_input);
471 /* Exit here if we are using environment variables
472 * and our ID does not exist
474 if (getenv("OSSEC_AGENT_ID")) {
482 printf(REMOVE_CONFIRM);
487 user_input = getenv("OSSEC_ACTION_CONFIRMED");
488 if (user_input == NULL) {
489 user_input = read_from_user();
490 } else if (!json_output) {
491 printf("%s\n", user_input);
494 /* If user confirms */
495 if (user_input[0] == 'y' || user_input[0] == 'Y') {
496 /* Get full agent name */
497 char *full_name = getFullnameById(u_id);
501 cJSON *json_root = cJSON_CreateObject();
502 snprintf(buffer, 1023, "Invalid ID '%s' given. ID is not present", u_id);
503 cJSON_AddNumberToObject(json_root, "error", 78);
504 cJSON_AddStringToObject(json_root, "description", buffer);
505 printf("%s", cJSON_PrintUnformatted(json_root));
512 fp = fopen(authfile, "r+");
515 ErrorExit(FOPEN_ERROR, ARGV0, authfile, errno, strerror(errno));
518 chmod(authfile, 0440);
521 /* Remove the agent, but keep the id */
522 fsetpos(fp, &fp_pos);
524 fprintf(fp, "#%s #*#*#*#*#*#*#*#*#*#*#", u_id);
526 fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id);
531 /* Remove counter for ID */
532 delete_agentinfo(full_name);
533 OS_RemoveCounter(u_id);
538 cJSON *json_root = cJSON_CreateObject();
539 cJSON_AddNumberToObject(json_root, "error", 0);
540 cJSON_AddStringToObject(json_root, "response", "Agent removed");
541 printf("%s", cJSON_PrintUnformatted(json_root));
543 printf(REMOVE_DONE, u_id);
545 restart_necessary = 1;
547 } else { /* if(user_input[0] == 'n' || user_input[0] == 'N') */
556 int list_agents(int cmdlist)
558 if (!print_agents(0, 0, 0, 0)) {