From 7285f2a1bc6b1f91f1a198a83c087e5b08721923 Mon Sep 17 00:00:00 2001 From: switch_st Date: Fri, 24 Jul 2020 12:36:15 +0800 Subject: [PATCH] add set uid/gid command option to supernode --- include/n2n.h | 4 ++++ src/sn.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- src/sn_utils.c | 2 +- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/include/n2n.h b/include/n2n.h index f536f2e..3e554db 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -367,6 +367,10 @@ typedef struct n2n_sn uint16_t mport; /* Management UDP port to bind to. */ int sock; /* Main socket for UDP traffic with edges. */ int mgmt_sock; /* management socket. */ +#ifndef WIN32 + uid_t userid; + gid_t groupid; +#endif int lock_communities; /* If true, only loaded communities can be used. */ struct sn_community *communities; } n2n_sn_t; diff --git a/src/sn.c b/src/sn.c index 08700ae..4087152 100644 --- a/src/sn.c +++ b/src/sn.c @@ -103,6 +103,9 @@ static void help() { #if defined(N2N_HAVE_DAEMON) printf("[-f] "); #endif +#ifndef WIN32 + printf("[-u -g ] "); +#endif /* ifndef WIN32 */ printf("[-t ] "); printf("[-v] "); printf("\n\n"); @@ -112,6 +115,10 @@ static void help() { #if defined(N2N_HAVE_DAEMON) printf("-f \tRun in foreground.\n"); #endif /* #if defined(N2N_HAVE_DAEMON) */ +#ifndef WIN32 + printf("-u \tUser ID (numeric) to use when privileges are dropped.\n"); + printf("-g \tGroup ID (numeric) to use when privileges are dropped.\n"); +#endif /* ifndef WIN32 */ printf("-t \tManagement UDP Port (for multiple supernodes on a machine).\n"); printf("-v \tIncrease verbosity. Can be used multiple times.\n"); printf("-h \tThis help message.\n"); @@ -135,6 +142,16 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) { sss->mport = atoi(_optarg); break; +#ifndef WIN32 + case 'u': /* unprivileged uid */ + sss->userid = atoi(_optarg); + break; + + case 'g': /* unprivileged uid */ + sss->groupid = atoi(_optarg); + break; +#endif + case 'c': /* community file */ load_allowed_sn_community(sss, _optarg); break; @@ -168,7 +185,7 @@ static const struct option long_options[] = { { "mgmt-port", required_argument, NULL, 't' }, { "help" , no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } + { NULL, 0, NULL, 0 } }; /* *************************************************** */ @@ -177,7 +194,7 @@ static const struct option long_options[] = { static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { u_char c; - while((c = getopt_long(argc, argv, "fl:t:c:vh", + while((c = getopt_long(argc, argv, "fl:u:g:t:c:vh", long_options, NULL)) != '?') { if(c == 255) break; setOption(c, optarg, sss); @@ -335,6 +352,9 @@ static void term_handler(int sig) /** Main program entry point from kernel. */ int main(int argc, char * const argv[]) { int rc; +#ifndef WIN32 + struct passwd *pw = NULL; +#endif sn_init(&sss_node); @@ -366,11 +386,6 @@ int main(int argc, char * const argv[]) { } #endif /* #if defined(N2N_HAVE_DAEMON) */ -#ifndef WIN32 - if((getuid() == 0) || (getgid() == 0)) - traceEvent(TRACE_WARNING, "Running as root is discouraged"); -#endif - traceEvent(TRACE_DEBUG, "traceLevel is %d", getTraceLevel()); sss_node.sock = open_socket(sss_node.lport, 1 /*bind ANY*/); @@ -388,6 +403,27 @@ int main(int argc, char * const argv[]) { } else traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", sss_node.mport); +#ifndef WIN32 + if (((pw = getpwnam ("n2n")) != NULL) || ((pw = getpwnam ("nobody")) != NULL)) { + sss_node.userid = sss_node.userid == 0 ? pw->pw_uid : 0; + sss_node.groupid = sss_node.groupid == 0 ? pw->pw_gid : 0; + } + if((sss_node.userid != 0) || (sss_node.groupid != 0)) { + traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d", + (signed int)sss_node.userid, (signed int)sss_node.groupid); + + /* Finished with the need for root privileges. Drop to unprivileged user. */ + if((setgid(sss_node.groupid) != 0) + || (setuid(sss_node.userid) != 0)) { + traceEvent(TRACE_ERROR, "Unable to drop privileges [%u/%s]", errno, strerror(errno)); + exit(1); + } + } + + if((getuid() == 0) || (getgid() == 0)) + traceEvent(TRACE_WARNING, "Running as root is discouraged, check out the -u/-g options"); +#endif + traceEvent(TRACE_NORMAL, "supernode started"); #ifdef __linux__ diff --git a/src/sn_utils.c b/src/sn_utils.c index 352ccd7..e607839 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -782,7 +782,7 @@ static int process_udp(n2n_sn_t * sss, break; } case MSG_TYPE_REGISTER_ACK: - traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode"); + traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) Should not be via supernode"); break; case MSG_TYPE_REGISTER_SUPER: {