-/* @(#) $Id: ./src/addagent/main.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
* Foundation
*/
-
-
#include "manage_agents.h"
#include <stdlib.h>
-/** help **/
-void helpmsg()
+/* Prototypes */
+static void helpmsg(void) __attribute__((noreturn));
+static void print_banner(void);
+#ifndef WIN32
+static void manage_shutdown(int sig) __attribute__((noreturn));
+#endif
+
+
+#if defined(__MINGW32__)
+static int setenv(const char *name, const char *val, __attribute__((unused)) int overwrite)
{
- printf("\nOSSEC HIDS %s: Manage agents.\n", ARGV0);
- printf("Available options:\n");
- printf("\t-h This help message.\n");
- printf("\t-V Display OSSEC version.\n");
- printf("\t-l List available agents.\n");
- printf("\t-e <id> Extracts key for an agent (Manager only).\n");
- printf("\t-i <id> Import authentication key (Agent only).\n");
- printf("\t-f <file> Bulk generate client keys from file. (Manager only).\n\n");
- exit(1);
+ int len = strlen(name) + strlen(val) + 2;
+ char *str = (char *)malloc(len);
+ if(str == NULL) {
+ merror("%s: malloc failed", ARGV0);
+ exit(errno);
+ }
+ snprintf(str, len, "%s=%s", name, val);
+ putenv(str);
+ return 0;
}
+#endif
+static void helpmsg()
+{
+ print_header();
+ print_out(" %s: -[Vhlj] [-a <ip> -n <name>] [-d sec] [-e id] [-r id] [-i id] [-f file]", ARGV0);
+ print_out(" -V Version and license message");
+ print_out(" -h This help message");
+ print_out(" -j Use JSON output");
+ print_out(" -l List available agents.");
+ print_out(" -a <ip> Add new agent");
+
+ print_out(" -e <id> Extracts key for an agent (Manager only)");
+ print_out(" -r <id> Remove an agent (Manager only)");
+ print_out(" -i <id> Import authentication key (Agent only)");
+ print_out(" -n <name> Name for new agent");
+ print_out(" -F <sec> Remove agents with duplicated IP if disconnected since <sec> seconds");
+ print_out(" -f <file> Bulk generate client keys from file (Manager only)");
+ print_out(" <file> contains lines in IP,NAME format");
+ print_out(" <file> should also exist within /var/ossec due to manage_agents chrooting");
+ exit(1);
+}
-/* print banner */
-void print_banner()
+static void print_banner()
{
printf("\n");
- printf(BANNER, __name, __version);
+ printf(BANNER, __ossec_name, __version);
- #ifdef CLIENT
+#ifdef CLIENT
printf(BANNER_CLIENT);
- #else
+#else
printf(BANNER_OPT);
- #endif
+#endif
return;
}
-
+#ifndef WIN32
/* Clean shutdown on kill */
-void manage_shutdown()
+static void manage_shutdown(__attribute__((unused)) int sig)
{
/* Checking if restart message is necessary */
- if(restart_necessary)
- {
+ if (restart_necessary) {
printf(MUST_RESTART);
- }
- else
- {
+ } else {
printf("\n");
}
printf(EXIT);
exit(0);
}
+#endif
-
-/** main **/
int main(int argc, char **argv)
{
char *user_msg;
-
- int c = 0, cmdlist = 0;
- char *cmdexport = NULL;
- char *cmdimport = NULL;
- char *cmdbulk = NULL;
-
- #ifndef WIN32
- char *dir = DEFAULTDIR;
- char *group = GROUPGLOBAL;
- int gid;
- #endif
-
-
- /* Setting the name */
+ int c = 0, cmdlist = 0, json_output = 0;
+ int force_antiquity;
+ char *end;
+ const char *cmdexport = NULL;
+ const char *cmdimport = NULL;
+ const char *cmdbulk = NULL;
+#ifndef WIN32
+ const char *dir = DEFAULTDIR;
+ const char *group = GROUPGLOBAL;
+ gid_t gid;
+#else
+ FILE *fp;
+ TCHAR path[2048];
+ DWORD last_error;
+ int ret;
+#endif
+
+ extern int willchroot;
+ willchroot = 1;
+
+ /* Set the name */
OS_SetName(ARGV0);
-
- while((c = getopt(argc, argv, "Vhle:i:f:")) != -1){
- switch(c){
- case 'V':
- print_version();
- break;
+ while ((c = getopt(argc, argv, "Vhle:r:i:f:ja:n:F:")) != -1) {
+ switch (c) {
+ case 'V':
+ print_version();
+ break;
case 'h':
helpmsg();
break;
- case 'd':
- nowDebug();
- break;
case 'e':
- #ifdef CLIENT
- ErrorExit("%s: You can't export keys on an agent", ARGV0);
- #endif
- if(!optarg)
- ErrorExit("%s: -e needs an argument",ARGV0);
+#ifdef CLIENT
+ ErrorExit("%s: Key export only available on a master.", ARGV0);
+#endif
+ if (!optarg) {
+ ErrorExit("%s: -e needs an argument.", ARGV0);
+ }
cmdexport = optarg;
break;
+ case 'r':
+#ifdef CLIENT
+ ErrorExit("%s: Key removal only available on a master.", ARGV0);
+#endif
+ if (!optarg) {
+ ErrorExit("%s: -r needs an argument.", ARGV0);
+ }
+
+ /* Use environment variables already available to remove_agent() */
+ setenv("OSSEC_ACTION", "r", 1);
+ setenv("OSSEC_AGENT_ID", optarg, 1);
+ setenv("OSSEC_ACTION_CONFIRMED", "y", 1);
+ break;
case 'i':
- #ifndef CLIENT
- ErrorExit("%s: You can't import keys on the manager.", ARGV0);
- #endif
- if(!optarg)
- ErrorExit("%s: -i needs an argument",ARGV0);
+#ifndef CLIENT
+ ErrorExit("%s: Key import only available on an agent.", ARGV0);
+#endif
+ if (!optarg) {
+ ErrorExit("%s: -i needs an argument.", ARGV0);
+ }
cmdimport = optarg;
break;
case 'f':
- #ifdef CLIENT
- ErrorExit("%s: You can't bulk generate keys on an agent.", ARGV0);
- #endif
- if(!optarg)
- ErrorExit("%s: -f needs an argument",ARGV0);
+#ifdef CLIENT
+ ErrorExit("%s: Bulk generate keys only available on a master.", ARGV0);
+#endif
+ if (!optarg) {
+ ErrorExit("%s: -f needs an argument.", ARGV0);
+ }
cmdbulk = optarg;
+ willchroot = 0;
printf("Bulk load file: %s\n", cmdbulk);
break;
case 'l':
cmdlist = 1;
break;
+ case 'j':
+ json_output = 1;
+ break;
+ case 'a':
+#ifdef CLIENT
+ ErrorExit("%s: Agent adding only available on a master.", ARGV0);
+#endif
+ if (!optarg)
+ ErrorExit("%s: -a needs an argument.", ARGV0);
+ setenv("OSSEC_ACTION", "a", 1);
+ setenv("OSSEC_ACTION_CONFIRMED", "y", 1);
+ setenv("OSSEC_AGENT_IP", optarg, 1);
+ setenv("OSSEC_AGENT_ID", "0", 1);
+ break;
+ case 'n':
+ if (!optarg)
+ ErrorExit("%s: -n needs an argument.", ARGV0);
+ setenv("OSSEC_AGENT_NAME", optarg, 1);
+ break;
+ case 'F':
+ if (!optarg)
+ ErrorExit("%s: -d needs an argument.", ARGV0);
+
+ force_antiquity = strtol(optarg, &end, 10);
+
+ if (optarg == end || force_antiquity < 0)
+ ErrorExit("%s: Invalid number for -d", ARGV0);
+
+ setenv("OSSEC_REMOVE_DUPLICATED", optarg, 1);
+ break;
default:
helpmsg();
break;
}
-
}
-
-
- /* Getting currently time */
+ /* Get current time */
time1 = time(0);
restart_necessary = 0;
+ /* Before chroot */
+ srandom_init();
- #ifndef WIN32
- /* Getting the group name */
+#ifndef WIN32
+ /* Get the group name */
gid = Privsep_GetGroup(group);
- if(gid < 0)
- {
- ErrorExit(USER_ERROR, ARGV0, "", group);
+ if (gid == (gid_t) - 1) {
+ ErrorExit(USER_ERROR, ARGV0, "", group);
}
+ /* Set the group */
+ if (Privsep_SetGroup(gid) < 0) {
+ ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
+ }
+
+ /* Inside chroot now */
+ if(willchroot > 0) {
+
+ /* Chroot to the default directory */
+ if (Privsep_Chroot(dir) < 0) {
+ ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
+ }
- /* Setting the group */
- if(Privsep_SetGroup(gid) < 0)
- {
- ErrorExit(SETGID_ERROR, ARGV0, group);
+ nowChroot();
}
+ /* Start signal handler */
+ StartSIG2(ARGV0, manage_shutdown);
+#else
+ /* Get full path to the directory this executable lives in */
+ ret = GetModuleFileName(NULL, path, sizeof(path));
- /* Chrooting to the default directory */
- if(Privsep_Chroot(dir) < 0)
- {
- ErrorExit(CHROOT_ERROR, ARGV0, dir);
+ /* Check for errors */
+ if (!ret) {
+ ErrorExit(GMF_ERROR);
}
+ /* Get last error */
+ last_error = GetLastError();
- /* Inside chroot now */
- nowChroot();
+ /* Look for errors */
+ if (last_error != ERROR_SUCCESS) {
+ if (last_error == ERROR_INSUFFICIENT_BUFFER) {
+ ErrorExit(GMF_BUFF_ERROR, ret, sizeof(path));
+ } else {
+ ErrorExit(GMF_UNKN_ERROR, last_error);
+ }
+ }
+ /* Remove file name from path */
+ PathRemoveFileSpec(path);
- /* Starting signal handler */
- StartSIG2(ARGV0, manage_shutdown);
- #endif
+ /* Move to correct directory */
+ if (chdir(path)) {
+ ErrorExit(CHDIR_ERROR, ARGV0, path, errno, strerror(errno));
+ }
+ /* Check permissions */
+ fp = fopen(OSSECCONF, "r");
+ if (fp) {
+ fclose(fp);
+ } else {
+ ErrorExit(CONF_ERROR, OSSECCONF);
+ }
+#endif
- if(cmdlist == 1)
- {
+ if (cmdlist == 1) {
list_agents(cmdlist);
exit(0);
- }
- else if(cmdimport)
- {
+ } else if (cmdimport) {
k_import(cmdimport);
exit(0);
- }
- else if(cmdexport)
- {
- k_extract(cmdexport);
+ } else if (cmdexport) {
+ k_extract(cmdexport, json_output);
exit(0);
- }
- else if(cmdbulk)
- {
+ } else if (cmdbulk) {
k_bulkload(cmdbulk);
exit(0);
}
-
-
/* Little shell */
- while(1)
- {
+ while (1) {
int leave_s = 0;
- print_banner();
+
+ if (!json_output)
+ print_banner();
+
/* Get ACTION from the environment. If ACTION is specified,
* we must set leave_s = 1 to ensure that the loop will end */
user_msg = getenv("OSSEC_ACTION");
if (user_msg == NULL) {
- user_msg = read_from_user();
- }
- else{
- leave_s = 1;
+ user_msg = read_from_user();
+ } else {
+ leave_s = 1;
}
/* All the allowed actions */
- switch(user_msg[0])
- {
+ switch (user_msg[0]) {
case 'A':
case 'a':
- add_agent();
+#ifdef CLIENT
+ printf("\n ** Agent adding only available on a master ** \n\n");
+ break;
+#endif
+ add_agent(json_output);
break;
case 'e':
case 'E':
- k_extract(NULL);
+#ifdef CLIENT
+ printf("\n ** Key export only available on a master ** \n\n");
+ break;
+#endif
+ k_extract(NULL, json_output);
break;
case 'i':
case 'I':
+#ifndef CLIENT
+ printf("\n ** Key import only available on an agent ** \n\n");
+ break;
+#else //CLIENT
k_import(NULL);
break;
+#endif
case 'l':
case 'L':
list_agents(0);
break;
case 'r':
case 'R':
- remove_agent();
+#ifdef CLIENT
+ printf("\n ** Key removal only available on a master ** \n\n");
+ break;
+#endif
+ remove_agent(json_output);
break;
case 'q':
case 'Q':
leave_s = 1;
break;
- case 'V':
- print_version();
- break;
+ case 'V':
+ print_version();
+ break;
default:
printf("\n ** Invalid Action ** \n\n");
break;
}
- if(leave_s)
- {
+ if (leave_s) {
break;
}
continue;
-
}
- /* Checking if restart message is necessary */
- if(restart_necessary)
- {
- printf(MUST_RESTART);
- }
- else
- {
- printf("\n");
+ if (!json_output) {
+ if (restart_necessary) {
+ printf(MUST_RESTART);
+ } else {
+ printf("\n");
+ }
+
+ printf(EXIT);
}
printf(EXIT);
- return(0);
+ return (0);
}
-
-
-/* EOF */