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:
M | README | | | 8 | ++++++++ |
M | main.c | | | 55 | ++++++++++++++++++++++++++++++++++++++++--------------- |
M | tskrtt.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.
.