diff --git a/examples/shrpx.cc b/examples/shrpx.cc index 5cb8b05..e1088c5 100644 --- a/examples/shrpx.cc +++ b/examples/shrpx.cc @@ -33,10 +33,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -233,6 +235,19 @@ int event_loop() } } // namespace +namespace { +void save_pid() +{ + std::ofstream out(get_config()->pid_file, std::ios::binary); + out << getpid() << "\n"; + out.close(); + if(!out) { + LOG(ERROR) << "Could not save PID to file " << get_config()->pid_file; + exit(EXIT_FAILURE); + } +} +} // namespace + namespace { void fill_default_config() { @@ -387,6 +402,9 @@ void print_help(std::ostream& out) << " frontend connection to 2**.\n" << " Default: " << get_config()->spdy_upstream_window_bits << "\n" + << " --pid-file= Set path to save PID of this program.\n" + << " --user= Run this program as USER. This option is\n" + << " intended to be used to drop root privileges.\n" << " -h, --help Print this help.\n" << std::endl; } @@ -422,6 +440,8 @@ int main(int argc, char **argv) {"accesslog", no_argument, &flag, 7 }, {"backend-keep-alive-timeout", required_argument, &flag, 8 }, {"frontend-spdy-window-bits", required_argument, &flag, 9 }, + {"pid-file", required_argument, &flag, 10 }, + {"user", required_argument, &flag, 11 }, {"help", no_argument, 0, 'h' }, {0, 0, 0, 0 } }; @@ -531,6 +551,20 @@ int main(int argc, char **argv) } break; } + case 10: + mod_config()->pid_file = optarg; + break; + case 11: { + passwd *pwd = getpwnam(optarg); + if(pwd == 0) { + std::cerr << "--user: failed to get uid from " << optarg + << ": " << strerror(errno) << std::endl; + exit(EXIT_FAILURE); + } + mod_config()->uid = pwd->pw_uid; + mod_config()->gid = pwd->pw_gid; + break; + } default: break; } @@ -576,6 +610,23 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } } + if(get_config()->pid_file) { + save_pid(); + } + if(getuid() == 0 && get_config()->uid != 0) { + if(setgid(get_config()->gid) != 0) { + std::cerr << "Could not change gid: " << strerror(errno) << std::endl; + exit(EXIT_FAILURE); + } + if(setuid(get_config()->uid) != 0) { + std::cerr << "Could not change uid: " << strerror(errno) << std::endl; + exit(EXIT_FAILURE); + } + if(setuid(0) != -1) { + std::cerr << "FATAL: Still have root privileges?" << std::endl; + exit(EXIT_FAILURE); + } + } struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); diff --git a/examples/shrpx_config.cc b/examples/shrpx_config.cc index 562d5b6..a6ddafd 100644 --- a/examples/shrpx_config.cc +++ b/examples/shrpx_config.cc @@ -44,7 +44,10 @@ Config::Config() spdy_proxy(false), add_x_forwarded_for(false), accesslog(false), - spdy_upstream_window_bits(0) + spdy_upstream_window_bits(0), + pid_file(0), + uid(0), + gid(0) {} namespace { diff --git a/examples/shrpx_config.h b/examples/shrpx_config.h index fc33fe0..103590f 100644 --- a/examples/shrpx_config.h +++ b/examples/shrpx_config.h @@ -70,6 +70,9 @@ struct Config { bool add_x_forwarded_for; bool accesslog; size_t spdy_upstream_window_bits; + const char* pid_file; + uid_t uid; + gid_t gid; Config(); };