-/* @(#) $Id: ./src/addagent/manage_keys.c, 2011/09/08 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
*/
-
#include "manage_agents.h"
#include "os_crypto/md5/md5_op.h"
+#include "external/cJSON/cJSON.h"
#include <stdlib.h>
-/* b64 function prototypes */
-char *decode_base64(const char *src);
-char *encode_base64(int size, char *src);
-char *trimwhitespace(char *str)
+/* Prototypes */
+static char *trimwhitespace(char *str);
+
+
+static char *trimwhitespace(char *str)
{
- char *end;
+ char *end;
- // Trim leading space
- while(isspace(*str)) str++;
+ /* Trim leading space */
+ while (isspace(*str)) {
+ str++;
+ }
- if(*str == 0) // All spaces?
- return str;
+ if (*str == 0) { /* All spaces? */
+ return str;
+ }
- // Trim trailing space
- end = str + strlen(str) - 1;
- while(end > str && isspace(*end)) end--;
+ /* Trim trailing space */
+ end = str + strlen(str) - 1;
+ while (end > str && isspace(*end)) {
+ end--;
+ }
- // Write new null terminator
- *(end+1) = 0;
+ /* Write new null terminator */
+ *(end + 1) = 0;
- return str;
+ return str;
}
/* Import a key */
-int k_import(char *cmdimport)
+int k_import(const char *cmdimport)
{
FILE *fp;
- char *user_input;
+ const char *user_input;
char *b64_dec;
- char *name; char *ip; char *tmp_key;
+ char *name;
+ char *ip;
+ char *tmp_key;
- char line_read[FILE_SIZE +1];
+ char line_read[FILE_SIZE + 1];
- #ifdef WIN32
- int result;
- int cmdlen;
- int caclslen;
- char *comspec;
- char *cacls;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- DWORD exit_code;
- #endif
+ char auth_file_tmp[] = AUTH_FILE;
+ char *keys_file = basename_ex(auth_file_tmp);
+ char tmp_path[strlen(TMP_DIR) + 1 + strlen(keys_file) + 6 + 1];
- /* Parsing user argument. */
- if(cmdimport)
- {
+ snprintf(tmp_path, sizeof(tmp_path), "%s/%sXXXXXX", TMP_DIR, keys_file);
+
+ /* Parse user argument */
+ if (cmdimport) {
user_input = cmdimport;
- }
- else
- {
+ } else {
printf(IMPORT_KEY);
user_input = getenv("OSSEC_AGENT_KEY");
if (user_input == NULL) {
- user_input = read_from_user();
+ user_input = read_from_user();
}
}
-
- /* quit */
- if(strcmp(user_input, QUIT) == 0)
- return(0);
+ /* Quit */
+ if (strcmp(user_input, QUIT) == 0) {
+ return (0);
+ }
b64_dec = decode_base64(user_input);
- if(b64_dec == NULL)
- {
+ if (b64_dec == NULL) {
printf(NO_KEY);
printf(PRESS_ENTER);
read_from_user();
- return(0);
+ return (0);
}
-
- memset(line_read, '\0', FILE_SIZE +1);
+ memset(line_read, '\0', FILE_SIZE + 1);
strncpy(line_read, b64_dec, FILE_SIZE);
-
name = strchr(b64_dec, ' ');
- if(name && strlen(line_read) < FILE_SIZE)
- {
+ if (name && strlen(line_read) < FILE_SIZE) {
*name = '\0';
name++;
ip = strchr(name, ' ');
- if(ip)
- {
+ if (ip) {
*ip = '\0';
ip++;
tmp_key = strchr(ip, ' ');
- if(!tmp_key)
- {
+ if (!tmp_key) {
printf(NO_KEY);
- return(0);
+ free(b64_dec);
+ return (0);
}
*tmp_key = '\0';
printf("\n");
printf(AGENT_INFO, b64_dec, name, ip);
- while(1)
- {
+ while (1) {
printf(ADD_CONFIRM);
fflush(stdout);
user_input = getenv("OSSEC_ACTION_CONFIRMED");
if (user_input == NULL) {
- user_input = read_from_user();
+ user_input = read_from_user();
}
- if(user_input[0] == 'y' || user_input[0] == 'Y')
- {
- fp = fopen(KEYS_FILE,"w");
- if(!fp)
- {
- ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE);
+ if (user_input[0] == 'y' || user_input[0] == 'Y') {
+ if (mkstemp_ex(tmp_path)) {
+ ErrorExit(MKSTEMP_ERROR, ARGV0, tmp_path, errno, strerror(errno));
}
- fprintf(fp,"%s\n",line_read);
- fclose(fp);
- #ifndef WIN32
- chmod(KEYS_FILE, 0440);
- #else
- /* Get cmd location from environment */
- comspec = getenv("COMSPEC");
- if (comspec == NULL || strncmp(comspec, "", strlen(comspec) == 0))
- {
- if(unlink(KEYS_FILE))
- {
- verbose(AGENT_DELETE_ERROR, KEYS_FILE);
+#ifndef WIN32
+ if (chmod(tmp_path, 0440) == -1) {
+ if (unlink(tmp_path)) {
+ verbose(DELETE_ERROR, ARGV0, tmp_path, errno, strerror(errno));
}
- ErrorExit(COMPSEC_ERROR);
- }
- /* Build cacls command */
- cacls = "echo y|cacls \"%s\" /T /G Administrators:f";
- caclslen = strlen(cacls) + strlen(KEYS_FILE);
- char caclscmd[caclslen];
- snprintf(caclscmd, caclslen, cacls, KEYS_FILE);
-
- /* Build final command */
- cmdlen = strlen(comspec) + 5 + caclslen;
- char cmd[cmdlen];
- snprintf(cmd, cmdlen, "%s /c %s", comspec, caclscmd);
-
- /* Log command being run */
- log2file("%s: INFO: Running the following command (%s)", ARGV0, cmd);
-
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
- ZeroMemory(&pi, sizeof(pi));
-
- if(!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
- &si, &pi))
- {
- if(unlink(KEYS_FILE))
- {
- verbose(AGENT_DELETE_ERROR, KEYS_FILE);
- }
- ErrorExit(PROC_ERROR, cmd);
+ ErrorExit(CHMOD_ERROR, ARGV0, tmp_path, errno, strerror(errno));
}
+#endif
- /* Wait until process exits */
- WaitForSingleObject(pi.hProcess, INFINITE);
-
- /* Get exit code from command */
- result = GetExitCodeProcess(pi.hProcess, &exit_code);
-
- /* Close process and thread */
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
-
- if (!result)
- {
- if(unlink(KEYS_FILE))
- {
- verbose(AGENT_DELETE_ERROR, KEYS_FILE);
+ fp = fopen(tmp_path, "w");
+ if (!fp) {
+ if (unlink(tmp_path)) {
+ verbose(DELETE_ERROR, ARGV0, tmp_path, errno, strerror(errno));
}
- ErrorExit(RESULT_ERROR, cmd, GetLastError());
+
+ ErrorExit(FOPEN_ERROR, ARGV0, tmp_path, errno, strerror(errno));
}
+ fprintf(fp, "%s\n", line_read);
+ fclose(fp);
- if (exit_code)
- {
- if(unlink(KEYS_FILE))
- {
- verbose(AGENT_DELETE_ERROR, KEYS_FILE);
+ if (rename_ex(tmp_path, KEYS_FILE)) {
+ if (unlink(tmp_path)) {
+ verbose(DELETE_ERROR, ARGV0, tmp_path, errno, strerror(errno));
}
- ErrorExit(CACLS_ERROR, cmd, exit_code);
+
+ ErrorExit(RENAME_ERROR, ARGV0, tmp_path, KEYS_FILE, errno, strerror(errno));
}
- #endif
- /* Removing sender counter. */
+ /* Remove sender counter */
OS_RemoveCounter("sender");
printf(ADDED);
printf(PRESS_ENTER);
read_from_user();
restart_necessary = 1;
- return(1);
- }
- else /* if(user_input[0] == 'n' || user_input[0] == 'N') */
- {
+
+ free(b64_dec);
+ return (1);
+ } else { /* if(user_input[0] == 'n' || user_input[0] == 'N') */
printf("%s", ADD_NOT);
- return(0);
+
+ free(b64_dec);
+ return (0);
}
}
}
printf(NO_KEY);
printf(PRESS_ENTER);
read_from_user();
- return(0);
+ free(b64_dec);
+ return (0);
}
-
-/* extract base64 for a specific agent */
-int k_extract(char *cmdextract)
+/* Extract base64 for a specific agent */
+int k_extract(const char *cmdextract, int json_output)
{
FILE *fp;
char *user_input;
char *b64_enc;
- char line_read[FILE_SIZE +1];
- char n_id[USER_SIZE +1];
-
-
- if(cmdextract)
- {
- user_input = cmdextract;
-
- if(!IDExist(user_input))
- {
- printf(NO_ID, user_input);
+ char line_read[FILE_SIZE + 1];
+ char n_id[USER_SIZE + 1];
+ cJSON *json_root = NULL;
+
+ if (json_output)
+ json_root = cJSON_CreateObject();
+
+ if (cmdextract) {
+ user_input = strdup(cmdextract);
+ FormatID(user_input);
+
+ if (!IDExist(user_input)) {
+ if (json_output) {
+ char buffer[1024];
+ snprintf(buffer, 1023, "Invalid ID '%s' given. ID is not present", user_input);
+ cJSON_AddNumberToObject(json_root, "error", 70);
+ cJSON_AddStringToObject(json_root, "description", buffer);
+ printf("%s", cJSON_PrintUnformatted(json_root));
+ } else
+ printf(NO_ID, user_input);
exit(1);
}
- }
-
- else
- {
- if(!print_agents(0, 0, 0))
- {
+ } else {
+ if (!print_agents(0, 0, 0, 0)) {
printf(NO_AGENT);
printf(PRESS_ENTER);
read_from_user();
- return(0);
+ return (0);
}
- do
- {
+ while (1) {
printf(EXTRACT_KEY);
fflush(stdout);
user_input = read_from_user();
/* quit */
- if(strcmp(user_input, QUIT) == 0)
- return(0);
+ if (strcmp(user_input, QUIT) == 0) {
+ return (0);
+ }
+
+ FormatID(user_input);
- if(!IDExist(user_input))
+ if (IDExist(user_input)) {
+ break;
+ } else {
printf(NO_ID, user_input);
+ }
- } while(!IDExist(user_input));
+ }
+ }
+
+ /* Try to open the auth file */
+ char authfile[257];
+ extern int willchroot;
+ if(willchroot > 0) {
+ snprintf(authfile, 256, "%s", AUTH_FILE); //XXX
+ } else {
+ const char *dir = DEFAULTDIR;
+ snprintf(authfile, 256, "%s/%s", dir, AUTH_FILE); //XXX
}
+ fp = fopen(authfile, "r");
+ if (!fp) {
+ if (json_output) {
+ char buffer[1024];
+ 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));
+
- /* Trying to open the auth file */
- fp = fopen(AUTH_FILE, "r");
- if(!fp)
- {
- ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE);
}
- fsetpos(fp, &fp_pos);
+ if (fsetpos(fp, &fp_pos)) {
+ if (json_output) {
+ cJSON_AddNumberToObject(json_root, "error", 72);
+ cJSON_AddStringToObject(json_root, "description", "Can not set fileposition");
+ printf("%s", cJSON_PrintUnformatted(json_root));
+ } else
+ merror("%s: Can not set fileposition.", ARGV0);
+ exit(1);
+ }
- memset(n_id, '\0', USER_SIZE +1);
- strncpy(n_id, user_input, USER_SIZE -1);
+ memset(n_id, '\0', USER_SIZE + 1);
+ strncpy(n_id, user_input, USER_SIZE - 1);
+
+ if (fgets(line_read, FILE_SIZE, fp) == NULL) {
+ if (json_output) {
+ cJSON_AddNumberToObject(json_root, "error", 73);
+ cJSON_AddStringToObject(json_root, "description", "Unable to handle keys file");
+ printf("%s", cJSON_PrintUnformatted(json_root));
+ } else
+ printf(ERROR_KEYS);
- if(fgets(line_read, FILE_SIZE, fp) == NULL)
- {
- printf(ERROR_KEYS);
- fclose(fp);
exit(1);
}
chomp(line_read);
-
- b64_enc = encode_base64(strlen(line_read),line_read);
- if(b64_enc == NULL)
- {
- printf(EXTRACT_ERROR);
- fclose(fp);
+ b64_enc = encode_base64(strlen(line_read), line_read);
+ if (b64_enc == NULL) {
+ if (json_output) {
+ cJSON_AddNumberToObject(json_root, "error", 74);
+ cJSON_AddStringToObject(json_root, "description", "Unable to extract agent key");
+ printf("%s", cJSON_PrintUnformatted(json_root));
+ } else
+ printf(EXTRACT_ERROR);
exit(1);
}
- printf(EXTRACT_MSG, n_id, b64_enc);
- if(!cmdextract)
- {
+ if (json_output) {
+ cJSON_AddNumberToObject(json_root, "error", 0);
+ cJSON_AddStringToObject(json_root, "response", b64_enc);
+ printf("%s", cJSON_PrintUnformatted(json_root));
+ } else
+ printf(EXTRACT_MSG, n_id, b64_enc);
+
+
+ if (!cmdextract) {
printf("\n" PRESS_ENTER);
read_from_user();
}
free(b64_enc);
fclose(fp);
- return(0);
+ return (0);
}
/* Bulk generate client keys from file */
-int k_bulkload(char *cmdbulk)
+int k_bulkload(const char *cmdbulk)
{
int i = 1;
FILE *fp, *infp;
- 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;
- char line[FILE_SIZE+1];
- char name[FILE_SIZE +1];
- char id[FILE_SIZE +1];
- char ip[FILE_SIZE+1];
- os_ip *c_ip;
+ char line[FILE_SIZE + 1];
+ char name[FILE_SIZE + 1];
+ char id[FILE_SIZE + 1];
+ char ip[FILE_SIZE + 1];
char delims[] = ",";
- char * token = NULL;
+ char *token = NULL;
- /* Checking if we can open the input file */
+ /* Check if we can open the input file */
printf("Opening: [%s]\n", cmdbulk);
- infp = fopen(cmdbulk,"r");
- if(!infp)
- {
- perror("Failed.");
- ErrorExit(FOPEN_ERROR, ARGV0, cmdbulk);
+ infp = fopen(cmdbulk, "r");
+ if (!infp) {
+ perror("Failed.");
+ ErrorExit(FOPEN_ERROR, ARGV0, cmdbulk, errno, strerror(errno));
}
+ /* Check if we can open the auth_file */
+ 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
+ }
- /* Checking if we can open the auth_file */
- fp = fopen(AUTH_FILE,"a");
- if(!fp)
- {
- ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE);
+ fp = fopen(authfile, "a");
+ if (!fp) {
+ ErrorExit(FOPEN_ERROR, ARGV0, authfile, errno, strerror(errno));
}
fclose(fp);
- /* Allocating for c_ip */
- os_calloc(1, sizeof(os_ip), c_ip);
-
- while(fgets(line, FILE_SIZE - 1, infp) != NULL)
- {
- if (1 >= strlen(trimwhitespace(line)))
- continue;
-
- memset(ip, '\0', FILE_SIZE +1);
- token = strtok(line, delims);
- strncpy(ip, trimwhitespace(token),FILE_SIZE -1);
-
- memset(name, '\0', FILE_SIZE +1);
- token = strtok(NULL, delims);
- strncpy(name, trimwhitespace(token),FILE_SIZE -1);
-
- #ifndef WIN32
- chmod(AUTH_FILE, 0440);
- #endif
-
- /* Setting time 2 */
- time2 = time(0);
-
-
- /* Source is time1+ time2 +pid + ppid */
- #ifndef WIN32
- #ifdef __OpenBSD__
- srandomdev();
- #else
- srandom(time2 + time1 + getpid() + getppid());
- #endif
- #else
- srandom(time2 + time1 + getpid());
- #endif
-
- rand1 = random();
-
-
- /* Zeroing strings */
- memset(str1,'\0', STR_SIZE +1);
- memset(str2,'\0', STR_SIZE +1);
-
-
- /* check the name */
- if(!OS_IsValidName(name))
- {
- printf(INVALID_NAME,name);
- continue;
- }
-
- /* Search for name -- no duplicates */
- if(NameExist(name))
- {
- printf(ADD_ERROR_NAME, name);
- continue;
- }
-
-
- if(!OS_IsValidIP(ip, c_ip))
- {
- printf(IP_ERROR, ip);
- continue;
- }
-
- /* Default ID */
- i = MAX_AGENTS + 32512;
- snprintf(id, 8, "%03d", i);
- 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);
-
- if(!OS_IsValidID(id))
- {
- printf(INVALID_ID, id);
- continue;
- }
-
- /* Search for ID KEY -- no duplicates */
- if(IDExist(id))
- {
- printf(NO_DEFAULT, i+1);
- continue;
- }
-
- printf(AGENT_INFO, id, name, ip);
- fflush(stdout);
-
-
- time3 = time(0);
- rand2 = random();
-
- fp = fopen(AUTH_FILE,"a");
- if(!fp)
- {
- ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE);
- }
- #ifndef WIN32
- chmod(AUTH_FILE, 0440);
- #endif
-
-
- /* 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, ip, md1,md2);
- fprintf(fp,"%s %s %s %s%s\n",id, name, c_ip->ip, md1,md2);
-
- fclose(fp);
-
- printf(AGENT_ADD);
- restart_necessary = 1;
- };
-
- fclose(infp);
- return(0);
-}
+ while (fgets(line, FILE_SIZE - 1, infp) != NULL) {
+ os_ip c_ip;
+ c_ip.ip = NULL;
+
+ if (1 >= strlen(trimwhitespace(line))) {
+ continue;
+ }
+ memset(ip, '\0', FILE_SIZE + 1);
+ token = strtok(line, delims);
+ strncpy(ip, trimwhitespace(token), FILE_SIZE - 1);
-/* EOF */
+ memset(name, '\0', FILE_SIZE + 1);
+ token = strtok(NULL, delims);
+ strncpy(name, trimwhitespace(token), FILE_SIZE - 1);
+
+#ifndef WIN32
+ if (chmod(authfile, 0440) == -1) {
+ ErrorExit(CHMOD_ERROR, ARGV0, authfile, errno, strerror(errno));
+ }
+#endif
+
+ /* Set time 2 */
+ time2 = time(0);
+
+ srandom_init();
+ rand1 = random();
+
+ /* Zero strings */
+ memset(str1, '\0', STR_SIZE + 1);
+ memset(str2, '\0', STR_SIZE + 1);
+
+ /* Check the name */
+ if (!OS_IsValidName(name)) {
+ printf(INVALID_NAME, name);
+ continue;
+ }
+
+ /* Search for name -- no duplicates */
+ if (NameExist(name)) {
+ printf(ADD_ERROR_NAME, name);
+ continue;
+ }
+
+ if (!OS_IsValidIP(ip, &c_ip)) {
+ printf(IP_ERROR, ip);
+ continue;
+ }
+
+ /* Default ID */
+ i = MAX_AGENTS + 32512;
+ snprintf(id, 8, "%03d", i);
+ 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);
+
+ if (!OS_IsValidID(id)) {
+ printf(INVALID_ID, id);
+ goto cleanup;
+ }
+
+ /* Search for ID KEY -- no duplicates */
+ if (IDExist(id)) {
+ printf(NO_DEFAULT, i + 1);
+ goto cleanup;
+ }
+
+ printf(AGENT_INFO, id, name, ip);
+ fflush(stdout);
+
+ time3 = time(0);
+ rand2 = random();
+
+ fp = fopen(authfile, "a");
+ if (!fp) {
+ ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE, errno, strerror(errno));
+ }
+#ifndef WIN32
+ if (chmod(authfile, 0440) == -1) {
+ ErrorExit(CHMOD_ERROR, ARGV0, authfile, errno, strerror(errno));
+ }
+#endif
+
+ /* 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", (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);
+
+ fprintf(fp, "%s %s %s %s%s\n", id, name, c_ip.ip, md1, md2);
+ fclose(fp);
+
+ printf(AGENT_ADD, id);
+ restart_necessary = 1;
+
+cleanup:
+ free(c_ip.ip);
+ };
+
+ fclose(infp);
+ return (0);
+}