mirror of https://github.com/adamdruppe/arsd.git
improve privilege dropping in cgi
This commit is contained in:
parent
ac64e36c36
commit
641d823ddd
73
cgi.d
73
cgi.d
|
@ -476,6 +476,7 @@ import std.base64;
|
||||||
static import std.algorithm;
|
static import std.algorithm;
|
||||||
import std.datetime;
|
import std.datetime;
|
||||||
import std.range;
|
import std.range;
|
||||||
|
import std.typecons : Nullable;
|
||||||
|
|
||||||
import std.process;
|
import std.process;
|
||||||
|
|
||||||
|
@ -3510,11 +3511,11 @@ struct RequestServer {
|
||||||
foundHost = false;
|
foundHost = false;
|
||||||
}
|
}
|
||||||
if(foundUid) {
|
if(foundUid) {
|
||||||
privDropUserId = to!int(arg);
|
privilegesDropToUid = to!int(arg);
|
||||||
foundUid = false;
|
foundUid = false;
|
||||||
}
|
}
|
||||||
if(foundGid) {
|
if(foundGid) {
|
||||||
privDropGroupId = to!int(arg);
|
privilegesDropToGid = to!int(arg);
|
||||||
foundGid = false;
|
foundGid = false;
|
||||||
}
|
}
|
||||||
if(arg == "--listening-host" || arg == "-h" || arg == "/listening-host")
|
if(arg == "--listening-host" || arg == "-h" || arg == "/listening-host")
|
||||||
|
@ -3528,7 +3529,30 @@ struct RequestServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: the privDropUserId/group id need to be set in here instead of global
|
///
|
||||||
|
Nullable!uid_t privilegesDropToUid;
|
||||||
|
///
|
||||||
|
Nullable!gid_t privilegesDropToGid;
|
||||||
|
|
||||||
|
private void dropPrivileges() {
|
||||||
|
version(Posix) {
|
||||||
|
import core.sys.posix.unistd;
|
||||||
|
|
||||||
|
if (!privilegesDropToGid.isNull && setgid(privilegesDropToGid.get) != 0)
|
||||||
|
throw new Exception("Dropping privileges via setgid() failed.");
|
||||||
|
|
||||||
|
if (!privilegesDropToUid.isNull && setuid(privilegesDropToUid.get) != 0)
|
||||||
|
throw new Exception("Dropping privileges via setuid() failed.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// FIXME: Windows?
|
||||||
|
//pragma(msg, "Dropping privileges is not implemented for this platform");
|
||||||
|
}
|
||||||
|
|
||||||
|
// done, set null
|
||||||
|
privilegesDropToGid.nullify();
|
||||||
|
privilegesDropToUid.nullify();
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Serves a single HTTP request on this thread, with an embedded server, then stops. Designed for cases like embedded oauth responders
|
Serves a single HTTP request on this thread, with an embedded server, then stops. Designed for cases like embedded oauth responders
|
||||||
|
@ -3557,7 +3581,7 @@ struct RequestServer {
|
||||||
|
|
||||||
bool tcp;
|
bool tcp;
|
||||||
void delegate() cleanup;
|
void delegate() cleanup;
|
||||||
auto socket = startListening(listeningHost, listeningPort, tcp, cleanup, 1);
|
auto socket = startListening(listeningHost, listeningPort, tcp, cleanup, 1, &dropPrivileges);
|
||||||
auto connection = socket.accept();
|
auto connection = socket.accept();
|
||||||
doThreadHttpConnectionGuts!(CustomCgi, fun, true)(connection);
|
doThreadHttpConnectionGuts!(CustomCgi, fun, true)(connection);
|
||||||
|
|
||||||
|
@ -3680,28 +3704,6 @@ else
|
||||||
|
|
||||||
private __gshared bool globalStopFlag = false;
|
private __gshared bool globalStopFlag = false;
|
||||||
|
|
||||||
private int privDropUserId;
|
|
||||||
private int privDropGroupId;
|
|
||||||
|
|
||||||
// Added Jan 11, 2021
|
|
||||||
private void dropPrivs() {
|
|
||||||
version(Posix) {
|
|
||||||
import core.sys.posix.unistd;
|
|
||||||
|
|
||||||
auto userId = privDropUserId;
|
|
||||||
auto groupId = privDropGroupId;
|
|
||||||
|
|
||||||
if((userId != 0 || groupId != 0) && getuid() == 0) {
|
|
||||||
if(groupId)
|
|
||||||
setgid(groupId);
|
|
||||||
if(userId)
|
|
||||||
setuid(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// FIXME: Windows?
|
|
||||||
}
|
|
||||||
|
|
||||||
version(embedded_httpd_processes)
|
version(embedded_httpd_processes)
|
||||||
void serveEmbeddedHttpdProcesses(alias fun, CustomCgi = Cgi)(RequestServer params) {
|
void serveEmbeddedHttpdProcesses(alias fun, CustomCgi = Cgi)(RequestServer params) {
|
||||||
import core.sys.posix.unistd;
|
import core.sys.posix.unistd;
|
||||||
|
@ -3745,7 +3747,7 @@ void serveEmbeddedHttpdProcesses(alias fun, CustomCgi = Cgi)(RequestServer param
|
||||||
close(sock);
|
close(sock);
|
||||||
throw new Exception("listen");
|
throw new Exception("listen");
|
||||||
}
|
}
|
||||||
dropPrivs();
|
params.dropPrivileges();
|
||||||
}
|
}
|
||||||
|
|
||||||
version(embedded_httpd_processes_accept_after_fork) {} else {
|
version(embedded_httpd_processes_accept_after_fork) {} else {
|
||||||
|
@ -5153,9 +5155,13 @@ import core.atomic;
|
||||||
/**
|
/**
|
||||||
To use this thing:
|
To use this thing:
|
||||||
|
|
||||||
|
---
|
||||||
void handler(Socket s) { do something... }
|
void handler(Socket s) { do something... }
|
||||||
auto manager = new ListeningConnectionManager("127.0.0.1", 80, &handler);
|
auto manager = new ListeningConnectionManager("127.0.0.1", 80, &handler, &delegateThatDropsPrivileges);
|
||||||
manager.listen();
|
manager.listen();
|
||||||
|
---
|
||||||
|
|
||||||
|
The 4th parameter is optional.
|
||||||
|
|
||||||
I suggest you use BufferedInputRange(connection) to handle the input. As a packet
|
I suggest you use BufferedInputRange(connection) to handle the input. As a packet
|
||||||
comes in, you will get control. You can just continue; though to fetch more.
|
comes in, you will get control. You can just continue; though to fetch more.
|
||||||
|
@ -5355,15 +5361,15 @@ class ListeningConnectionManager {
|
||||||
private void dg_handler(Socket s) {
|
private void dg_handler(Socket s) {
|
||||||
fhandler(s);
|
fhandler(s);
|
||||||
}
|
}
|
||||||
this(string host, ushort port, void function(Socket) handler) {
|
this(string host, ushort port, void function(Socket) handler, void delegate() dropPrivs = null) {
|
||||||
fhandler = handler;
|
fhandler = handler;
|
||||||
this(host, port, &dg_handler);
|
this(host, port, &dg_handler, dropPrivs);
|
||||||
}
|
}
|
||||||
|
|
||||||
this(string host, ushort port, void delegate(Socket) handler) {
|
this(string host, ushort port, void delegate(Socket) handler, void delegate() dropPrivs = null) {
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
|
|
||||||
listener = startListening(host, port, tcp, cleanup, 128);
|
listener = startListening(host, port, tcp, cleanup, 128, dropPrivs);
|
||||||
|
|
||||||
version(cgi_use_fiber) version(cgi_use_fork)
|
version(cgi_use_fiber) version(cgi_use_fork)
|
||||||
listener.blocking = false;
|
listener.blocking = false;
|
||||||
|
@ -5376,7 +5382,7 @@ class ListeningConnectionManager {
|
||||||
void delegate(Socket) handler;
|
void delegate(Socket) handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket startListening(string host, ushort port, ref bool tcp, ref void delegate() cleanup, int backQueue) {
|
Socket startListening(string host, ushort port, ref bool tcp, ref void delegate() cleanup, int backQueue, void delegate() dropPrivs) {
|
||||||
Socket listener;
|
Socket listener;
|
||||||
if(host.startsWith("unix:")) {
|
if(host.startsWith("unix:")) {
|
||||||
version(Posix) {
|
version(Posix) {
|
||||||
|
@ -5424,6 +5430,7 @@ Socket startListening(string host, ushort port, ref bool tcp, ref void delegate(
|
||||||
|
|
||||||
listener.listen(backQueue);
|
listener.listen(backQueue);
|
||||||
|
|
||||||
|
if (dropPrivs !is null) // can be null, backwards compatibility
|
||||||
dropPrivs();
|
dropPrivs();
|
||||||
|
|
||||||
return listener;
|
return listener;
|
||||||
|
|
Loading…
Reference in New Issue