Skip to content

Commit f5cfdcf

Browse files
committed
drop_uid / drop_gid support
1 parent 62cd7a4 commit f5cfdcf

File tree

4 files changed

+45
-6
lines changed

4 files changed

+45
-6
lines changed

bin/server.config

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
# Default vhost
1+
# Hosts to respond to (localhost/127.0.0.1 implied)
22
vhost=10.0.10.86,acme.local
33
port=8080
44
diskpath=./htdocs
5+
6+
# Optional - uid/gid to "drop" to with setuid/setgid after bind() so the program doesn't have to run as root
7+
# Default 0 because dropping to root makes no sense
8+
drop_uid=0
9+
drop_gid=0

src/HTTPServer.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,19 @@
2525
* @param vhost_aliases List of hostnames the HTTP server will respond to
2626
* @param port Port the vhost listens on
2727
* @param diskpath Path to the folder the vhost serves up
28+
* @param drop_uid UID to setuid to after bind(). Ignored if 0
29+
* @param drop_gid GID to setgid to after bind(). Ignored if 0
2830
*/
29-
HTTPServer::HTTPServer(std::vector<std::string> vhost_aliases, int port, std::string diskpath) {
31+
HTTPServer::HTTPServer(std::vector<std::string> vhost_aliases, int port, std::string diskpath, int drop_uid, int drop_gid) {
3032
canRun = false;
3133
listenSocket = INVALID_SOCKET;
3234
listenPort = port;
3335
kqfd = -1;
36+
dropUid = drop_uid;
37+
dropGid = drop_gid;
3438

35-
std::cout << "Primary port: " << port << ", disk path: " << diskpath.c_str() << std::endl;
39+
std::cout << "Port: " << port << std::endl;
40+
std::cout << "Disk path: " << diskpath.c_str() << std::endl;
3641

3742
// Create a resource host serving the base path ./htdocs on disk
3843
ResourceHost* resHost = new ResourceHost(diskpath);
@@ -104,6 +109,21 @@ bool HTTPServer::start() {
104109
return false;
105110
}
106111

112+
// Optionally drop uid/gid if specified
113+
if (dropUid != 0 && dropGid != 0) {
114+
if (setgid(dropGid) == -1) {
115+
std::cout << "setgid to " << dropGid << " failed!" << std::endl;
116+
return false;
117+
}
118+
119+
if (setuid(dropUid) == -1) {
120+
std::cout << "setuid to " << dropUid << " failed!" << std::endl;
121+
return false;
122+
}
123+
124+
std::cout << "Successfully dropped uid to " << dropUid << " and gid to " << dropGid << std::endl;
125+
}
126+
107127
// Listen: Put the socket in a listening state, ready to accept connections
108128
// Accept a backlog of the OS Maximum connections in the queue
109129
if (listen(listenSocket, SOMAXCONN) != 0) {

src/HTTPServer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class HTTPServer {
5151
int listenPort;
5252
int listenSocket; // Descriptor for the listening socket
5353
struct sockaddr_in serverAddr; // Structure for the server address
54+
int dropUid; // setuid to this after bind()
55+
int dropGid; // setgid to this after bind()
5456

5557
// Kqueue
5658
struct timespec kqTimeout = {2, 0}; // Block for 2 seconds and 0ns at the most
@@ -86,7 +88,7 @@ class HTTPServer {
8688
bool canRun;
8789

8890
public:
89-
HTTPServer(std::vector<std::string> vhost_aliases, int port, std::string diskpath);
91+
HTTPServer(std::vector<std::string> vhost_aliases, int port, std::string diskpath, int drop_uid=0, int drop_gid=0);
9092
~HTTPServer();
9193

9294
bool start();

src/main.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ int main (int argc, const char * argv[])
4343
std::map<std::string, std::string> config;
4444
std::fstream cfile;
4545
std::string line, key, val;
46-
int epos;
46+
int epos = 0;
47+
int drop_uid = 0, drop_gid = 0;
4748
cfile.open("server.config");
4849
if (!cfile.is_open()) {
4950
std::cout << "Unable to open server.config file in working directory" << std::endl;
@@ -83,6 +84,17 @@ int main (int argc, const char * argv[])
8384
vhost_alias_str.erase(0, pos + delimiter.length());
8485
} while (pos != std::string::npos);
8586

87+
// Check for optional drop_uid, drop_gid. Ensure both are set
88+
if (config.find("drop_uid") != config.end() && config.find("drop_gid") != config.end()) {
89+
drop_uid = atoi(config["drop_uid"].c_str());
90+
drop_gid = atoi(config["drop_gid"].c_str());
91+
92+
if (drop_uid == 0 || drop_gid == 0) {
93+
// Both must be set, otherwise set back to 0 so we dont use
94+
drop_uid = drop_gid = 0;
95+
}
96+
}
97+
8698
// Ignore SIGPIPE "Broken pipe" signals when socket connections are broken.
8799
signal(SIGPIPE, handleSigPipe);
88100

@@ -92,7 +104,7 @@ int main (int argc, const char * argv[])
92104
signal(SIGTERM, &handleTermSig);
93105

94106
// Instance and start the server
95-
svr = new HTTPServer(vhosts, atoi(config["port"].c_str()), config["diskpath"]);
107+
svr = new HTTPServer(vhosts, atoi(config["port"].c_str()), config["diskpath"], drop_uid, drop_gid);
96108
if (!svr->start()) {
97109
svr->stop();
98110
delete svr;

0 commit comments

Comments
 (0)