From f268b278c0a6f8360fb044743c38a05e36c40c50 Mon Sep 17 00:00:00 2001 From: Simon Shi Date: Fri, 4 Jan 2019 20:25:10 +0800 Subject: [PATCH 1/3] Test homedir for ss-manager Fix for user args --- src/common.h | 3 ++- src/jconf.c | 2 ++ src/jconf.h | 1 + src/manager.c | 37 +++++++++++++++++++++++++++++++------ src/manager.h | 2 ++ 5 files changed, 38 insertions(+), 7 deletions(-) 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; }; From e5d8476afeb2e8dc4838f0707aee6ae9d04fe58e Mon Sep 17 00:00:00 2001 From: Simon Shi Date: Fri, 4 Jan 2019 23:28:52 +0800 Subject: [PATCH 2/3] Update docs --- README.md | 27 +++++++++++++++------------ doc/ss-manager.asciidoc | 10 +++++++--- src/manager.c | 2 +- src/utils.c | 2 ++ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index f4d1a53a..cb089a27 100644 --- a/README.md +++ b/README.md @@ -383,7 +383,7 @@ you may refer to the man pages of the applications, respectively. -k Password of your remote server. - -m Encrypt method: rc4-md5, + -m Encrypt method: rc4-md5, aes-128-gcm, aes-192-gcm, aes-256-gcm, aes-128-cfb, aes-192-cfb, aes-256-cfb, aes-128-ctr, aes-192-ctr, aes-256-ctr, @@ -395,13 +395,13 @@ you may refer to the man pages of the applications, respectively. The default cipher is chacha20-ietf-poly1305. [-a ] Run as another user. - + [-f ] The file path to store pid. [-t ] Socket timeout in seconds. [-c ] The path to config file. - + [-n ] Max number of open files. [-i ] Network interface to bind. @@ -423,32 +423,35 @@ you may refer to the man pages of the applications, respectively. [-d ] Name servers for internal DNS resolver. (only available in server mode) - + [--reuse-port] Enable port reuse. - + [--fast-open] Enable TCP fast open. with Linux kernel > 3.7.0. (only available in local and server mode) - + [--acl ] Path to ACL (Access Control List). (only available in local and server mode) - + [--manager-address ] UNIX domain socket address. (only available in server and manager mode) [--mtu ] MTU of your network interface. - + [--mptcp] Enable Multipath TCP on MPTCP Kernel. - + [--no-delay] Enable TCP_NODELAY. [--executable ] Path to the executable of ss-server. (only available in manager mode) - + + [-D ] Path to the working directory of ss-manager. + (only available in manager mode) + [--key ] Key of your remote server. - + [--plugin ] Enable SIP003 plugin. (Experimental) - + [--plugin-opts ] Set SIP003 plugin options. (Experimental) [-v] Verbose mode. diff --git a/doc/ss-manager.asciidoc b/doc/ss-manager.asciidoc index 195ca8b2..189dfa6b 100644 --- a/doc/ss-manager.asciidoc +++ b/doc/ss-manager.asciidoc @@ -12,7 +12,7 @@ SYNOPSIS [-s ] [-p ] [-l ] [-k ] [-m ] [-f ] [-t ] [-c ] [-i ] - [-b ] [-a ] + [-b ] [-a ] [-D ] [--manager-address ] [--executable ] [--fast-open] [--reuse-port] @@ -116,6 +116,11 @@ Specify the executable path of ss-server. + Only available in manager mode. +--executable :: +Specify the working directory of ss-manager. ++ +Only available in manager mode. + --plugin :: Enable SIP003 plugin. (Experimental) @@ -148,7 +153,7 @@ The format of the traffic statistics: :::: stat: {"8001":11370} There is no way to reset the traffic statistics, unless you remove the port and add it again - + EXAMPLE ------- To use `ss-manager`(1), First start it and specify necessary information. @@ -178,4 +183,3 @@ SEE ALSO `shadowsocks-libev`(8), `iptables`(8), /etc/shadowsocks-libev/config.json - diff --git a/src/manager.c b/src/manager.c index 0caf9d9b..757b7c4c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -1161,7 +1161,7 @@ main(int argc, char **argv) if (strstr(homedir, "nologin") || strstr(homedir, "nonexistent") || homedir == NULL || strlen(homedir) == 0) { homedir = "/tmp"; } - LOGI("File path changed to %s", homedir); + LOGI("working directory points to %s", homedir); } working_dir_size = strlen(homedir) + 15; working_dir = ss_malloc(working_dir_size); diff --git a/src/utils.c b/src/utils.c index 16d00861..e2214e96 100644 --- a/src/utils.c +++ b/src/utils.c @@ -388,6 +388,8 @@ usage() #ifdef MODULE_MANAGER printf( " [--executable ] Path to the executable of ss-server.\n"); + printf( + " [-D ] Path to the working directory of ss-manager.\n"); #endif printf( " [--mtu ] MTU of your network interface.\n"); From 0c2bda940cd97b4ce580fc13ac3ae32c5f3299a8 Mon Sep 17 00:00:00 2001 From: Simon Shi Date: Sat, 5 Jan 2019 09:34:52 +0800 Subject: [PATCH 3/3] Rename variable --- src/common.h | 2 +- src/jconf.c | 4 ++-- src/jconf.h | 2 +- src/manager.c | 39 ++++++++++++++++++++++----------------- src/manager.h | 3 +-- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/common.h b/src/common.h index c15e7406..a36b134d 100644 --- a/src/common.h +++ b/src/common.h @@ -70,7 +70,7 @@ enum { GETOPT_VAL_KEY, GETOPT_VAL_MANAGER_ADDRESS, GETOPT_VAL_EXECUTABLE, - GETOPT_VAL_HOMEDIR, + GETOPT_VAL_WORKDIR, }; #endif // _COMMON_H diff --git a/src/jconf.c b/src/jconf.c index 5bc8a6e8..5509be5b 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -328,8 +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 if (strcmp(name, "workdir") == 0) { + conf.workdir = to_string(value); } } } else { diff --git a/src/jconf.h b/src/jconf.h index 80d9dcc8..59385719 100644 --- a/src/jconf.h +++ b/src/jconf.h @@ -85,7 +85,7 @@ typedef struct { int mptcp; int ipv6_first; int no_delay; - char *homedir; + char *workdir; } jconf_t; jconf_t *read_jconf(const char *file); diff --git a/src/manager.c b/src/manager.c index 757b7c4c..3ac9e416 100644 --- a/src/manager.c +++ b/src/manager.c @@ -212,10 +212,10 @@ 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) + if (manager->workdir) { int len = strlen(cmd); - snprintf(cmd + len, BUF_SIZE - len, " -D \"%s\"", manager->homedir); + snprintf(cmd + len, BUF_SIZE - len, " -D \"%s\"", manager->workdir); } for (i = 0; i < manager->host_num; i++) { int len = strlen(cmd); @@ -861,7 +861,7 @@ main(int argc, char **argv) char *manager_address = NULL; char *plugin = NULL; char *plugin_opts = NULL; - char *homedir = NULL; + char *workdir = NULL; int fast_open = 0; int no_delay = 0; @@ -894,7 +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 }, + { "workdir", required_argument, NULL, GETOPT_VAL_WORKDIR }, { "help", no_argument, NULL, GETOPT_VAL_HELP }, { NULL, 0, NULL, 0 } }; @@ -973,9 +973,9 @@ main(int argc, char **argv) case '6': ipv6first = 1; break; - case GETOPT_VAL_HOMEDIR: + case GETOPT_VAL_WORKDIR: case 'D': - homedir = optarg; + workdir = optarg; break; case 'v': verbose = 1; @@ -1050,9 +1050,9 @@ main(int argc, char **argv) if (ipv6first == 0) { ipv6first = conf->ipv6_first; } - if (homedir == NULL) + if (workdir == NULL) { - homedir = conf->homedir; + workdir = conf->workdir; } #ifdef HAVE_SETRLIMIT if (nofile == 0) { @@ -1134,7 +1134,7 @@ main(int argc, char **argv) manager.plugin = plugin; manager.plugin_opts = plugin_opts; manager.ipv6first = ipv6first; - manager.homedir = homedir; + manager.workdir = workdir; #ifdef HAVE_SETRLIMIT manager.nofile = nofile; #endif @@ -1155,17 +1155,22 @@ main(int argc, char **argv) struct passwd *pw = getpwuid(getuid()); - if (homedir == NULL || strlen(homedir) == 0) { - homedir = pw->pw_dir; + if (workdir == NULL || strlen(workdir) == 0) { + workdir = 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"; + if (strstr(workdir, "nologin") || strstr(workdir, "nonexistent") || workdir == NULL || strlen(workdir) == 0) { + workdir = "/tmp"; } - LOGI("working directory points to %s", homedir); + + working_dir_size = strlen(workdir) + 15; + working_dir = ss_malloc(working_dir_size); + snprintf(working_dir, working_dir_size, "%s/.shadowsocks", workdir); + } else { + working_dir_size = strlen(workdir) + 2; + working_dir = ss_malloc(working_dir_size); + snprintf(working_dir, working_dir_size, "%s", workdir); } - working_dir_size = strlen(homedir) + 15; - working_dir = ss_malloc(working_dir_size); - snprintf(working_dir, working_dir_size, "%s/.shadowsocks", homedir); + LOGI("working directory points to %s", working_dir); int err = mkdir(working_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (err != 0 && errno != EEXIST) { diff --git a/src/manager.h b/src/manager.h index f07144fb..6af71f06 100644 --- a/src/manager.h +++ b/src/manager.h @@ -59,7 +59,7 @@ struct manager_ctx { char *nameservers; int mtu; int ipv6first; - char *homedir; + char *workdir; #ifdef HAVE_SETRLIMIT int nofile; #endif @@ -74,7 +74,6 @@ struct server { char *method; char *plugin; char *plugin_opts; - char *homedir; uint64_t traffic; };