Optimize new path fallthrough feature to only serve dynamic content. - geomyidae - A small C-based gopherd.
git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/
Log
Files
Refs
Tags
README
LICENSE
---
commit 27c94c92d5fdf7294ee1905c381d0ce2f4ccebca
parent fdd8c5b2210b2c3719bce020dfec54bbe36adb49
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sun,  3 Apr 2022 09:55:45 +0200

Optimize new path fallthrough feature to only serve dynamic content.

Diffstat:
  M main.c                              |      29 +++++++++++++++++++++++++++--

1 file changed, 27 insertions(+), 2 deletions(-)
---
diff --git a/main.c b/main.c
@@ -139,10 +139,14 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
         struct stat dir;
         char recvc[1025], recvb[1025], path[1025], args[1025], argsc[1025],
                 *sear, *c, *sep, *pathp, *recvbp;
-        int len = 0, fd, i, maxrecv;
+        int len = 0, fd, i, maxrecv, pathfallthrough = 0;
         filetype *type;
 
         if (!istls) {
+                /*
+                 * If sticky bit is set on base dir and encryption is not
+                 * used, do not serve.
+                 */
                 if (stat(base, &dir) == -1)
                         return;
                 if (dir.st_mode & S_ISVTX) {
@@ -284,12 +288,16 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
                                         );
                                 }
                                 /* path fallthrough */
+                                pathfallthrough = 1;
                                 break;
                         }
                 }
         }
 
         if (stat(path, &dir) != -1) {
+                /*
+                 * If sticky bit is set, only serve if this is encrypted.
+                 */
                 if ((dir.st_mode & S_ISVTX) && !istls) {
                         dprintf(sock, tlserr, recvc);
                         if (loglvl & ERRORS) {
@@ -340,6 +348,19 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
                 if (c == NULL)
                         c = path;
                 type = gettype(c);
+
+                /*
+                 * If we had to traverse the path to find some, only
+                 * allow index.dcgi and index.cgi as handlers.
+                 */
+                if (pathfallthrough &&
+                                !(type->f == handledcgi || type->f == handlecgi)) {
+                        dprintf(sock, notfounderr, recvc);
+                        if (loglvl & ERRORS)
+                                logentry(clienth, clientp, recvc, "not found");
+                        return;
+                }
+
                 if (nocgi && (type->f == handledcgi || type->f == handlecgi)) {
                         dprintf(sock, nocgierr, recvc);
                         if (loglvl & ERRORS)
@@ -349,7 +370,11 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
                                 clienth, istls);
                 }
         } else {
-                if (S_ISDIR(dir.st_mode)) {
+                /*
+                 * If we had to traverse the path, do not allow directory
+                 * listings, only dynamic content.
+                 */
+                if (!pathfallthrough && S_ISDIR(dir.st_mode)) {
                         handledir(sock, path, port, base, args, sear, ohost,
                                 clienth, istls);
                         if (loglvl & DIRS) {