tskrtt

Simple libev based gopher server
git clone https://git.inz.fi/tskrtt/
Log | Files | Refs | README

commit 887e992156ed63506d42e9cf453335fd4019a4e0
parent 8aeae05926ec600aeb4af09f789080ad63126426
Author: Santtu Lakkala <inz@inz.fi>
Date:   Wed, 26 May 2021 22:51:04 +0300

Implement chroot to root dir

Diffstat:
MREADME | 8++++++++
Mmain.c | 55++++++++++++++++++++++++++++++++++++++++---------------
Mtskrtt.1 | 3+++
3 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/README b/README @@ -14,6 +14,8 @@ Usage: -4 Only listen for IPv4 connections. -6 Only listen for IPv6 connections. + + -c Chroot to root directory. -d Don't fork into background. @@ -72,5 +74,11 @@ Dynamic content: to avoid HTTP headers in the output. +Chroot: + tskrtt can chroot to root dir (if built with support, chroot() is not + part of POSIX. Note that this has immerse effect on d?cgi, whereas + their interpreter / dynamic libraries need to be available inside the + chroot. + Reporting bugs: Bugs can be reported to inz@inz.fi via email. diff --git a/main.c b/main.c @@ -1,3 +1,7 @@ +#ifdef USE_CHROOT +#define _DEFAULT_SOURCE +#define _BSD_SOURCE +#endif #define _POSIX_C_SOURCE 200809L #include <netinet/in.h> @@ -202,6 +206,11 @@ int main (int argc, char *argv[]) const char *logfile = NULL; int lfd = -1; bool dofork = true; +#ifdef USE_CHROOT + bool dochroot = false; +#endif + uid_t uid; + gid_t gid; signal(SIGPIPE, SIG_IGN); @@ -212,6 +221,11 @@ int main (int argc, char *argv[]) case '6': hints.ai_family = AF_INET6; break; +#ifdef USE_CHROOT + case 'c': + dochroot = true; + break; +#endif case 'd': dofork = false; break; @@ -302,31 +316,42 @@ int main (int argc, char *argv[]) listen_watcher.tlsctx = NULL; #endif - if (group) { - struct group *g = getgrnam(group); - if (!g) - croak("No such group"); - if (setgid(g->gr_gid)) - croak("setgid failed"); + if (*gopherroot != '/' && getcwd(gopherrootbuf, sizeof(gopherrootbuf))) { + size_t l = strlen(gopherrootbuf); + int ll = snprintf(gopherrootbuf + l, sizeof(gopherrootbuf) - l, "/%s", gopherroot); + if ((l += ll - 1) < sizeof(gopherrootbuf) - 1 && cleanup_path(gopherrootbuf + 1, NULL, &l)) { + gopherrootbuf[l + 1] = '\0'; + gopherroot = gopherrootbuf; + } } if (user) { struct passwd *u = getpwnam(user); if (!u) croak("No such user"); - if (setuid(u->pw_uid)) - croak("setuid failed"); + uid = u->pw_uid; } - if (*gopherroot != '/' && getcwd(gopherrootbuf, sizeof(gopherrootbuf))) { - size_t l = strlen(gopherrootbuf); - int ll = snprintf(gopherrootbuf + l, sizeof(gopherrootbuf) - l, "/%s", gopherroot); - if ((l += ll - 1) < sizeof(gopherrootbuf) - 1 && cleanup_path(gopherrootbuf + 1, NULL, &l)) { - gopherrootbuf[l + 1] = '\0'; - gopherroot = gopherrootbuf; - } + if (group) { + struct group *g = getgrnam(group); + if (!g) + croak("No such group"); + gid = g->gr_gid; } +#ifdef USE_CHROOT + if (dochroot) { + if (chroot(gopherroot)) + croak("chroot failed"); + gopherroot = strcpy(gopherrootbuf, "/"); + } +#endif + + if (group && setgid(gid)) + croak("setgid failed"); + if (user && setuid(uid)) + croak("setuid failed"); + if (dofork) { if (fork()) { close(lfd); diff --git a/tskrtt.1 b/tskrtt.1 @@ -39,6 +39,9 @@ Only listen for IPv4 connections. .It Fl 6 Only listen for IPv6 connections. . +.It Fl c +Chroot to root directory. +. .It Fl d Don't fork into background. .