aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Bühler <stbuehler@web.de>2009-03-26 15:45:10 +0000
committerStefan Bühler <stbuehler@web.de>2009-03-26 15:45:10 +0000
commitfc867f2d86ebd1858e1401cc60d59877918a184f (patch)
tree8946a0a0d7555b38274bf11978f3c14236d0f51a
parentca2bcf265a9303b82b9e740bffd219d9a59a7c5a (diff)
downloadspawn-fcgi-fc867f2d86ebd1858e1401cc60d59877918a184f.tar.gz
spawn-fcgi-fc867f2d86ebd1858e1401cc60d59877918a184f.zip
Added options to chown/chmod the socket and to create the socket before chroot() (fixes #1906)
git-svn-id: svn://svn.lighttpd.net/spawn-fcgi/trunk@30 4a9f3682-ca7b-49a8-9a55-ba4640e46f83
-rw-r--r--NEWS1
-rw-r--r--src/spawn-fcgi.c75
2 files changed, 64 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index ec1f284..28fdf5b 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ NEWS
- 1.6.1 -
* Add build date to show-version
+ * Added options to chown/chmod the socket and to create the socket before chroot() (fixes #1906)
- 1.6.0 - 2009-02-28
diff --git a/src/spawn-fcgi.c b/src/spawn-fcgi.c
index f8cc86a..56aa617 100644
--- a/src/spawn-fcgi.c
+++ b/src/spawn-fcgi.c
@@ -59,10 +59,8 @@
typedef int socklen_t;
#endif
-static int fcgi_spawn_connection(char *appPath, char **appArgv, char *addr, unsigned short port, const char *unixsocket, int fork_count, int child_count, int pid_fd, int nofork) {
- int fcgi_fd;
- int socket_type, status, rc = 0;
- struct timeval tv = { 0, 100 * 1000 };
+static int bind_socket(const char *addr, unsigned short port, const char *unixsocket, uid_t uid, gid_t gid, int mode) {
+ int fcgi_fd, socket_type, val;
struct sockaddr_un fcgi_addr_un;
struct sockaddr_in fcgi_addr_in;
@@ -70,9 +68,6 @@ static int fcgi_spawn_connection(char *appPath, char **appArgv, char *addr, unsi
socklen_t servlen;
- pid_t child;
- int val;
-
if (unixsocket) {
memset(&fcgi_addr_un, 0, sizeof(fcgi_addr_un));
@@ -146,11 +141,40 @@ static int fcgi_spawn_connection(char *appPath, char **appArgv, char *addr, unsi
return -1;
}
+ if (unixsocket) {
+ if (0 != uid || 0 != gid) {
+ if (0 == uid) uid = -1;
+ if (0 == gid) gid = -1;
+ if (-1 == chown(unixsocket, uid, gid)) {
+ fprintf(stderr, "spawn-fcgi: couldn't chown socket: %s\n", strerror(errno));
+ close(fcgi_fd);
+ unlink(unixsocket);
+ return -1;
+ }
+
+ if (-1 == chmod(unixsocket, mode)) {
+ fprintf(stderr, "spawn-fcgi: couldn't chmod socket: %s\n", strerror(errno));
+ close(fcgi_fd);
+ unlink(unixsocket);
+ return -1;
+ }
+ }
+ }
+
if (-1 == listen(fcgi_fd, 1024)) {
fprintf(stderr, "spawn-fcgi: listen failed: %s\n", strerror(errno));
return -1;
}
+ return fcgi_fd;
+}
+
+static int fcgi_spawn_connection(char *appPath, char **appArgv, int fcgi_fd, int fork_count, int child_count, int pid_fd, int nofork) {
+ int status, rc = 0;
+ struct timeval tv = { 0, 100 * 1000 };
+
+ pid_t child;
+
while (fork_count-- > 0) {
if (!nofork) {
@@ -351,6 +375,7 @@ static void show_help () {
" -a <addr> bind to ip address\n" \
" -p <port> bind to tcp-port\n" \
" -s <path> bind to unix-domain socket\n" \
+" -M <mode> change unix-domain socket mode\n" \
" -C <childs> (PHP only) numbers of childs to spawn (default: not setting\n" \
" the PHP_FCGI_CHILDREN env var - php defaults to 0)\n" \
" -F <childs> numbers of childs to fork (default 1)\n" \
@@ -360,8 +385,11 @@ static void show_help () {
" -?, -h show this help\n" \
"(root only)\n" \
" -c <dir> chroot to directory\n" \
+" -S create socket before chroot()ing (default is to create the socket in the chroot)\n" \
" -u <user> change to user-id\n" \
" -g <group> change to group-id (default: primary group of user if -u is given)\n" \
+" -U <user> change unix-domain socket owner to user-id\n" \
+" -G <group> change unix-domain socket group to group-id\n" \
;
write(1, b, strlen(b));
}
@@ -370,15 +398,19 @@ static void show_help () {
int main(int argc, char **argv) {
char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
*groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
+ *sockusername = NULL, *sockgroupname = NULL,
*addr = NULL;
char **fcgi_app_argv = { NULL };
unsigned short port = 0;
+ int sockmode = -1;
int child_count = -1;
int fork_count = 1;
int i_am_root, o;
int pid_fd = -1;
int nofork = 0;
+ int sockbeforechroot = 0;
struct sockaddr_un un;
+ int fcgi_fd = -1;
if (argc < 2) { /* no arguments given */
show_help();
@@ -387,7 +419,7 @@ int main(int argc, char **argv) {
i_am_root = (getuid() == 0);
- while (-1 != (o = getopt(argc, argv, "c:f:g:?hna:p:u:vC:F:s:P:"))) {
+ while (-1 != (o = getopt(argc, argv, "c:f:g:?hna:p:u:vC:F:s:P:U:G:M:S"))) {
switch(o) {
case 'f': fcgi_app = optarg; break;
case 'a': addr = optarg;/* ip addr */ break;
@@ -398,6 +430,10 @@ int main(int argc, char **argv) {
case 'c': if (i_am_root) { changeroot = optarg; }/* chroot() */ break;
case 'u': if (i_am_root) { username = optarg; } /* set user */ break;
case 'g': if (i_am_root) { groupname = optarg; } /* set group */ break;
+ case 'U': if (i_am_root) { sockusername = optarg; } /* set socket user */ break;
+ case 'G': if (i_am_root) { sockgroupname = optarg; } /* set socket group */ break;
+ case 'S': if (i_am_root) { sockbeforechroot = 1; } /* open socket before chroot() */ break;
+ case 'M': sockmode = strtol(optarg, NULL, 0); /* set socket mode */ break;
case 'n': nofork = 1; break;
case 'P': pid_file = optarg; /* PID file */ break;
case 'v': show_version(); return 0;
@@ -419,7 +455,7 @@ int main(int argc, char **argv) {
}
if (0 == port && NULL == unixsocket) {
- fprintf(stderr, "spawn-fcgi: no socket given (use either -p or -a)\n");
+ fprintf(stderr, "spawn-fcgi: no socket given (use either -p or -s)\n");
return -1;
} else if (0 != port && NULL != unixsocket) {
fprintf(stderr, "spawn-fcgi: either a unix domain socket or a tcp-port, but not both\n");
@@ -473,13 +509,22 @@ int main(int argc, char **argv) {
}
if (i_am_root) {
- uid_t uid;
- gid_t gid;
+ uid_t uid, sockuid;
+ gid_t gid, sockgid;
const char* real_username;
if (-1 == find_user_group(username, groupname, &uid, &gid, &real_username))
return -1;
+ if (-1 == find_user_group(sockusername, sockgroupname, &sockuid, &sockgid, NULL))
+ return -1;
+
+ if (0 == sockuid) sockuid = uid;
+ if (0 == sockgid) sockgid = gid;
+
+ if (sockbeforechroot && -1 == (fcgi_fd = bind_socket(addr, port, unixsocket, sockuid, sockgid, sockmode)))
+ return -1;
+
/* Change group before chroot, when we have access
* to /etc/group
*/
@@ -502,11 +547,17 @@ int main(int argc, char **argv) {
}
}
+ if (!sockbeforechroot && -1 == (fcgi_fd = bind_socket(addr, port, unixsocket, sockuid, sockgid, sockmode)))
+ return -1;
+
/* drop root privs */
if (uid != 0) {
setuid(uid);
}
+ } else {
+ if (-1 == (fcgi_fd = bind_socket(addr, port, unixsocket, 0, 0, sockmode)))
+ return -1;
}
- return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, addr, port, unixsocket, fork_count, child_count, pid_fd, nofork);
+ return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, fcgi_fd, fork_count, child_count, pid_fd, nofork);
}