diff --git a/src/common.h b/src/common.h index e9914483..c15e7406 100644 --- a/src/common.h +++ b/src/common.h @@ -69,7 +69,8 @@ enum { GETOPT_VAL_PASSWORD, GETOPT_VAL_KEY, GETOPT_VAL_MANAGER_ADDRESS, - GETOPT_VAL_EXECUTABLE + GETOPT_VAL_EXECUTABLE, + GETOPT_VAL_HOMEDIR, }; #endif // _COMMON_H diff --git a/src/jconf.c b/src/jconf.c index 84e80f18..5bc8a6e8 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -328,6 +328,8 @@ read_jconf(const char *file) value, json_boolean, "invalid config file: option 'no_delay' must be a boolean"); conf.no_delay = value->u.boolean; + } else if (strcmp(name, "homedir") == 0) { + conf.homedir = to_string(value); } } } else { diff --git a/src/jconf.h b/src/jconf.h index 3c33e8c2..80d9dcc8 100644 --- a/src/jconf.h +++ b/src/jconf.h @@ -85,6 +85,7 @@ typedef struct { int mptcp; int ipv6_first; int no_delay; + char *homedir; } jconf_t; jconf_t *read_jconf(const char *file); diff --git a/src/manager.c b/src/manager.c index c60004e1..0caf9d9b 100644 --- a/src/manager.c +++ b/src/manager.c @@ -212,6 +212,11 @@ construct_command_line(struct manager_ctx *manager, struct server *server) int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " -d \"%s\"", manager->nameservers); } + if (manager->homedir) + { + int len = strlen(cmd); + snprintf(cmd + len, BUF_SIZE - len, " -D \"%s\"", manager->homedir); + } for (i = 0; i < manager->host_num; i++) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " -s %s", manager->hosts[i]); @@ -856,6 +861,7 @@ main(int argc, char **argv) char *manager_address = NULL; char *plugin = NULL; char *plugin_opts = NULL; + char *homedir = NULL; int fast_open = 0; int no_delay = 0; @@ -888,6 +894,7 @@ main(int argc, char **argv) { "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN }, { "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS }, { "password", required_argument, NULL, GETOPT_VAL_PASSWORD }, + { "homedir", required_argument, NULL, GETOPT_VAL_HOMEDIR }, { "help", no_argument, NULL, GETOPT_VAL_HELP }, { NULL, 0, NULL, 0 } }; @@ -896,7 +903,7 @@ main(int argc, char **argv) USE_TTY(); - while ((c = getopt_long(argc, argv, "f:s:l:k:t:m:c:i:d:a:n:6huUvA", + while ((c = getopt_long(argc, argv, "f:s:l:k:t:m:c:i:d:a:n:D:6huUvA", long_options, NULL)) != -1) switch (c) { case GETOPT_VAL_REUSE_PORT: @@ -966,6 +973,10 @@ main(int argc, char **argv) case '6': ipv6first = 1; break; + case GETOPT_VAL_HOMEDIR: + case 'D': + homedir = optarg; + break; case 'v': verbose = 1; break; @@ -1039,6 +1050,10 @@ main(int argc, char **argv) if (ipv6first == 0) { ipv6first = conf->ipv6_first; } + if (homedir == NULL) + { + homedir = conf->homedir; + } #ifdef HAVE_SETRLIMIT if (nofile == 0) { nofile = conf->nofile; @@ -1119,6 +1134,7 @@ main(int argc, char **argv) manager.plugin = plugin; manager.plugin_opts = plugin_opts; manager.ipv6first = ipv6first; + manager.homedir = homedir; #ifdef HAVE_SETRLIMIT manager.nofile = nofile; #endif @@ -1126,17 +1142,26 @@ main(int argc, char **argv) // initialize ev loop struct ev_loop *loop = EV_DEFAULT; +#ifndef __MINGW32__ + // setuid + if (user != NULL && !run_as(user)) { + FATAL("failed to switch user"); + } + if (geteuid() == 0) { LOGI("running from root user"); } +#endif struct passwd *pw = getpwuid(getuid()); - const char *homedir = pw->pw_dir; - if (homedir == NULL || strlen(homedir) == 0) - { - // if home dir not defined, fall back to /tmp - homedir = "/tmp"; + if (homedir == NULL || strlen(homedir) == 0) { + homedir = pw->pw_dir; + // If home dir is still not defined or set to nologin/nonexistent, fall back to /tmp + if (strstr(homedir, "nologin") || strstr(homedir, "nonexistent") || homedir == NULL || strlen(homedir) == 0) { + homedir = "/tmp"; + } + LOGI("File path changed to %s", homedir); } working_dir_size = strlen(homedir) + 15; working_dir = ss_malloc(working_dir_size); diff --git a/src/manager.h b/src/manager.h index 2c7c3fcc..f07144fb 100644 --- a/src/manager.h +++ b/src/manager.h @@ -59,6 +59,7 @@ struct manager_ctx { char *nameservers; int mtu; int ipv6first; + char *homedir; #ifdef HAVE_SETRLIMIT int nofile; #endif @@ -73,6 +74,7 @@ struct server { char *method; char *plugin; char *plugin_opts; + char *homedir; uint64_t traffic; };