Introduction
Introduction Statistics Contact Development Disclaimer Help
First rework of path handling. - geomyidae - a small C-based gopherd (mirror)
git clone git://git.codemadness.org/geomyidae
Log
Files
Refs
README
LICENSE
---
commit b12a77acd24fc170b1ad047986ffaf13592fb326
parent f66a8a67b9471909016d6f24ce93f39584130a67
Author: Christoph Lohmann <[email protected]>
Date: Thu, 20 Jul 2023 06:30:24 +0200
First rework of path handling.
* Renaming the gph functions.
* Beware, still full of debug functions.
Diffstat:
M handlr.c | 112 +++++++++++++++++------------…
M handlr.h | 25 ++++++++++++++++++++-----
M ind.c | 133 ++++++++++++++++-------------…
M ind.h | 41 ++++++++++++++++-------------…
M index.gph | 4 +++-
M main.c | 144 ++++++++++++++++++++++-------…
6 files changed, 277 insertions(+), 182 deletions(-)
---
diff --git a/handlr.c b/handlr.c
@@ -17,6 +17,7 @@
#include <dirent.h>
#include <sys/wait.h>
#include <errno.h>
+#include <libgen.h>
#include "ind.h"
#include "arg.h"
@@ -25,7 +26,7 @@ void
handledir(int sock, char *path, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost, int istls)
{
- char *pa, *file, *e, *par, *b;
+ char *pa, *file, *e, *par;
struct dirent **dirent;
int ndir, i, ret = 0;
struct stat st;
@@ -35,22 +36,25 @@ handledir(int sock, char *path, char *port, char *base, cha…
USED(sear);
USED(bhost);
- pa = xstrdup(path);
- e = pa + strlen(pa) - 1;
- if (e > pa && e[0] == '/')
- *e = '\0';
+ printf("handledir:\n");
+ printf("sock = %d; path = %s; port = %s; base = %s; args = %s;\n",
+ sock, path, port, base, args);
+ printf("sear = %s; ohost = %s; chost = %s; bhost = %s; istls = %d;\n",
+ sear, ohost, chost, bhost, istls);
- par = xstrdup(pa);
+ pa = xstrdup(path);
- b = strrchr(makebasepath(par, base), '/');
- if (b != NULL) {
- *b = '\0';
+ /* Is there any directory below the request? */
+ if (strlen(pa+strlen(base)) > 1) {
+ par = xstrdup(pa+strlen(base));
+ e = strrchr(par, '/');
+ *e = '\0';
dprintf(sock, "1..\t%s\t%s\t%s\r\n",
- makebasepath(par, base), ohost, port);
+ par, ohost, port);
+ free(par);
}
- free(par);
- ndir = scandir(pa[0] ? pa : ".", &dirent, 0, alphasort);
+ ndir = scandir(pa, &dirent, 0, alphasort);
if (ndir < 0) {
perror("scandir");
free(pa);
@@ -61,19 +65,21 @@ handledir(int sock, char *path, char *port, char *base, cha…
continue;
type = gettype(dirent[i]->d_name);
- file = smprintf("%s%s%s", pa,
- pa[0] == '/' && pa[1] == '\0' ? "" : "…
+
+ file = smprintf("%s%s%s",
+ pa,
+ pa[strlen(pa)-1] == '/'? "" : "/",
dirent[i]->d_name);
+ printf("handledir: smprintf file = %s\n", file);
if (stat(file, &st) >= 0 && S_ISDIR(st.st_mode))
type = gettype("index.gph");
- e = makebasepath(file, base);
ret = dprintf(sock,
"%c%-50.50s %10s %16s\t%s\t%s\t%s\r\n",
*type->type,
dirent[i]->d_name,
humansize(st.st_size),
humantime(&(st.st_mtime)),
- e, ohost, port);
+ file + strlen(base), ohost, port);
free(file);
}
for (i = 0; i < ndir; i++)
@@ -89,24 +95,30 @@ void
handlegph(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost, int istls)
{
- Indexs *act;
+ gphindex *act;
int i, ret = 0;
USED(args);
USED(sear);
USED(bhost);
- act = scanfile(file);
+ printf("handlegph:\n");
+ printf("sock = %d; file = %s; port = %s; base = %s; args = %s;\n",
+ sock, file, port, base, args);
+ printf("sear = %s; ohost = %s; chost = %s; bhost = %s; istls = %d;\n",
+ sear, ohost, chost, bhost, istls);
+
+ act = gph_scanfile(file);
if (act != NULL) {
for (i = 0; i < act->num && ret >= 0; i++)
- ret = printelem(sock, act->n[i], file, base, ohost, po…
+ ret = gph_printelem(sock, act->n[i], file, base, ohost…
dprintf(sock, ".\r\n");
for (i = 0; i < act->num; i++) {
- freeelem(act->n[i]);
+ gph_freeelem(act->n[i]);
act->n[i] = NULL;
}
- freeindex(act);
+ gph_freeindex(act);
}
}
@@ -135,21 +147,22 @@ void
handlecgi(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost, int istls)
{
- char *p, *path;
+ char *script, *path;
USED(base);
USED(port);
- path = xstrdup(file);
- p = strrchr(path, '/');
- if (p != NULL)
- p[1] = '\0';
- else {
- free(path);
- path = NULL;
- }
+ printf("handlecgi:\n");
+ printf("sock = %d; file = %s; port = %s; base = %s; args = %s;\n",
+ sock, file, port, base, args);
+ printf("sear = %s; ohost = %s; chost = %s; bhost = %s; istls = %d;\n",
+ sear, ohost, chost, bhost, istls);
- p = makebasepath(file, base);
+ path = xstrdup(file);
+ path = dirname(path);
+ script = path + strlen(path) + 1;
+ printf("path = %s\n", path);
+ printf("script = %s\n", script);
if (sear == NULL)
sear = "";
@@ -166,10 +179,10 @@ handlecgi(int sock, char *file, char *port, char *base, c…
break;
}
- setcgienviron(p, file, port, base, args, sear, ohost, chost,
+ setcgienviron(script, file, port, base, args, sear, ohost, cho…
bhost, istls);
- if (execl(file, p, sear, args, ohost, port,
+ if (execl(file, script, sear, args, ohost, port,
(char *)NULL) == -1) {
perror("execl");
_exit(1);
@@ -189,25 +202,24 @@ handledcgi(int sock, char *file, char *port, char *base, …
char *sear, char *ohost, char *chost, char *bhost, int istls)
{
FILE *fp;
- char *p, *path, *ln = NULL;
+ char *script, *path, *ln = NULL;
size_t linesiz = 0;
ssize_t n;
int outsocks[2], ret = 0;
- Elems *el;
+ gphelem *el;
+
+ printf("handledcgi:\n");
+ printf("sock = %d; file = %s; port = %s; base = %s; args = %s;\n",
+ sock, file, port, base, args);
+ printf("sear = %s; ohost = %s; chost = %s; bhost = %s; istls = %d;\n",
+ sear, ohost, chost, bhost, istls);
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, outsocks) < 0)
return;
path = xstrdup(file);
- p = strrchr(path, '/');
- if (p != NULL)
- p[1] = '\0';
- else {
- free(path);
- path = NULL;
- }
-
- p = makebasepath(file, base);
+ path = dirname(path);
+ script = path + strlen(path) + 1;
if (sear == NULL)
sear = "";
@@ -225,10 +237,10 @@ handledcgi(int sock, char *file, char *port, char *base, …
break;
}
- setcgienviron(p, file, port, base, args, sear, ohost, chost,
+ setcgienviron(script, file, port, base, args, sear, ohost, cho…
bhost, istls);
- if (execl(file, p, sear, args, ohost, port,
+ if (execl(file, script, sear, args, ohost, port,
(char *)NULL) == -1) {
perror("execl");
_exit(1);
@@ -251,21 +263,21 @@ handledcgi(int sock, char *file, char *port, char *base, …
if (ln[n - 1] == '\n')
ln[--n] = '\0';
- el = getadv(ln);
+ el = gph_getadv(ln);
if (el == NULL)
continue;
- ret = printelem(sock, el, file, base, ohost, port);
- freeelem(el);
+ ret = gph_printelem(sock, el, file, base, ohost, port);
+ gph_freeelem(el);
}
if (ferror(fp))
perror("getline");
dprintf(sock, ".\r\n");
free(ln);
- free(path);
fclose(fp);
wait(NULL);
+ free(path);
break;
}
}
diff --git a/handlr.h b/handlr.h
@@ -9,16 +9,31 @@
/*
* Handler API definition
*
- * path .... absolute path to the script
+ * Sample: /get/some/script/with/dirs////?key=value\tsearch what?\r\n
+ * * in /get/some/script is a file "index.dcgi"
+ * * request to bitreich.org on port 70 using TLS
+ * * base is in /var/gopher
+ * * client from 85.65.4.2
+ *
+ * path/file absolute path to the script/directory, always starts with '/'
+ * Sample: /var/gopher/get/some/script/index.dcgi
* port .... port which the script should use when defining menu items
* (See -o and -p in geomyidae(8))
- * base .... base path of geomyidae ("" in case of chroot)
- * args .... query string parsed after »script?query«
- * sear .... search part of request (»selector\tsearch\r\n«)
- * ohost ... host of geomiydae (See -h in geomyidae(8))
+ * Sample: 70
+ * base .... base path of geomyidae, never ends in '/', so chroot is ''
+ * Sample: /var/gopher
+ * args .... Gives all variable input from the selector in some way.
+ * Sample: /with/dirs////?key=value
+ * sear .... search part of request
+ * Sample: search what?
+ * ohost ... host of geomyidae (See -h in geomyidae(8))
+ * Sample: bitreich.org
* chost ... IP of the client sending a request
+ * Sample: 85.65.4.2
* bhost ... server IP the server received the connection to
+ * Sample: 78.46.175.99
* istls ... set to 1, if TLS was used for thr request
+ * Sample: 1
*/
void handledir(int sock, char *path, char *port, char *base, char *args,
diff --git a/ind.c b/ind.c
@@ -24,6 +24,7 @@
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <limits.h>
+#include <errno.h>
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
@@ -258,7 +259,7 @@ gettype(char *filename)
}
void
-freeelem(Elems *e)
+gph_freeelem(gphelem *e)
{
if (e != NULL) {
if (e->e != NULL) {
@@ -273,12 +274,12 @@ freeelem(Elems *e)
}
void
-freeindex(Indexs *i)
+gph_freeindex(gphindex *i)
{
if (i != NULL) {
if (i->n != NULL) {
for (;i->num > 0; i->num--)
- freeelem(i->n[i->num - 1]);
+ gph_freeelem(i->n[i->num - 1]);
free(i->n);
}
free(i);
@@ -288,7 +289,7 @@ freeindex(Indexs *i)
}
void
-addelem(Elems *e, char *s)
+gph_addelem(gphelem *e, char *s)
{
e->num++;
e->e = xrealloc(e->e, sizeof(char *) * e->num);
@@ -297,23 +298,23 @@ addelem(Elems *e, char *s)
return;
}
-Elems *
-getadv(char *str)
+gphelem *
+gph_getadv(char *str)
{
char *b, *e, *o, *bo;
- Elems *ret;
+ gphelem *ret;
- ret = xcalloc(1, sizeof(Elems));
+ ret = xcalloc(1, sizeof(gphelem));
if (strchr(str, '\t')) {
- addelem(ret, "i");
- addelem(ret, "Happy helping ☃ here: You tried to "
+ gph_addelem(ret, "i");
+ gph_addelem(ret, "Happy helping ☃ here: You tried to "
"output a spurious TAB character. This will "
"break gopher. Please review your scripts. "
"Have a nice day!");
- addelem(ret, "Err");
- addelem(ret, "server");
- addelem(ret, "port");
+ gph_addelem(ret, "Err");
+ gph_addelem(ret, "server");
+ gph_addelem(ret, "port");
return ret;
}
@@ -331,7 +332,7 @@ getadv(char *str)
}
*e = '\0';
e++;
- addelem(ret, b);
+ gph_addelem(ret, b);
b = e;
bo = b;
}
@@ -339,7 +340,7 @@ getadv(char *str)
e = strchr(b, ']');
if (e != NULL) {
*e = '\0';
- addelem(ret, b);
+ gph_addelem(ret, b);
}
free(o);
@@ -349,55 +350,55 @@ getadv(char *str)
}
/* Invalid entry: Give back the whole line. */
- freeelem(ret);
- ret = xcalloc(1, sizeof(Elems));
+ gph_freeelem(ret);
+ ret = xcalloc(1, sizeof(gphelem));
}
- addelem(ret, "i");
+ gph_addelem(ret, "i");
/* Jump over escape sequence. */
if (str[0] == '[' && str[1] == '|')
str += 2;
- addelem(ret, str);
- addelem(ret, "Err");
- addelem(ret, "server");
- addelem(ret, "port");
+ gph_addelem(ret, str);
+ gph_addelem(ret, "Err");
+ gph_addelem(ret, "server");
+ gph_addelem(ret, "port");
return ret;
}
void
-addindexs(Indexs *idx, Elems *el)
+gph_addindex(gphindex *idx, gphelem *el)
{
idx->num++;
- idx->n = xrealloc(idx->n, sizeof(Elems) * idx->num);
+ idx->n = xrealloc(idx->n, sizeof(gphelem *) * idx->num);
idx->n[idx->num - 1] = el;
return;
}
-Indexs *
-scanfile(char *fname)
+gphindex *
+gph_scanfile(char *fname)
{
char *ln = NULL;
size_t linesiz = 0;
ssize_t n;
FILE *fp;
- Indexs *ret;
- Elems *el;
+ gphindex *ret;
+ gphelem *el;
if (!(fp = fopen(fname, "r")))
return NULL;
- ret = xcalloc(1, sizeof(Indexs));
+ ret = xcalloc(1, sizeof(gphindex));
while ((n = getline(&ln, &linesiz, fp)) > 0) {
if (ln[n - 1] == '\n')
ln[--n] = '\0';
- el = getadv(ln);
+ el = gph_getadv(ln);
if (el == NULL)
continue;
- addindexs(ret, el);
+ gph_addindex(ret, el);
}
if (ferror(fp))
perror("getline");
@@ -413,9 +414,9 @@ scanfile(char *fname)
}
int
-printelem(int fd, Elems *el, char *file, char *base, char *addr, char *port)
+gph_printelem(int fd, gphelem *el, char *file, char *base, char *addr, char *p…
{
- char *path, *p, *argbase, buf[PATH_MAX+1], *argp, *realbase;
+ char *path, *p, *argbase, buf[PATH_MAX+1], *argp, *realbase, *rpath;
int len, blen;
if (!strcmp(el->e[3], "server")) {
@@ -432,10 +433,6 @@ printelem(int fd, Elems *el, char *file, char *base, char …
* some URL and ignore various types that have different semantics,
* do not point to some file or directory.
*/
- /*
- * FUTURE: If ever special requests with no beginning '/' are used in
- * geomyidae, this is the place to control this.
- */
if ((el->e[2][0] != '\0'
&& el->e[2][0] != '/' /* Absolute Request. */
&& el->e[0][0] != 'i' /* Informational item. */
@@ -446,45 +443,50 @@ printelem(int fd, Elems *el, char *file, char *base, char…
&& el->e[0][0] != 'T') && /* tn3270 */
!(el->e[0][0] == 'h' && !strncmp(el->e[2], "URL:", 4))) {
path = file + strlen(base);
- if ((p = strrchr(path, '/')))
- len = p - path;
- else
+
+ /* Strip off original gph file name. */
+ if ((p = strrchr(path, '/'))) {
+ len = strlen(path) - strlen(basename(path));
+ } else {
len = strlen(path);
+ }
/* Strip off arguments for realpath. */
argbase = strchr(el->e[2], '?');
- if (argbase != NULL)
+ if (argbase != NULL) {
blen = argbase - el->e[2];
- else
+ } else {
blen = strlen(el->e[2]);
+ }
- snprintf(buf, sizeof(buf), "%s%.*s/%.*s", base, len,
+ /*
+ * Print everything together. Realpath will resolve it.
+ */
+ snprintf(buf, sizeof(buf), "%s%.*s%.*s", base, len,
path, blen, el->e[2]);
- if ((path = realpath(buf, NULL)) &&
- (realbase = realpath(base, NULL)) &&
- !strncmp(realbase, path, strlen(realbase))) {
- p = path + strlen(realbase);
+ if ((rpath = realpath(buf, NULL)) &&
+ (realbase = realpath(*base? base : "/", NULL))…
+ !strncmp(realbase, rpath, strlen(realbase))) {
+ p = rpath + (*base? strlen(realbase) : 0);
/*
- * Do not forget to readd arguments which were
+ * Do not forget to re-add arguments which were
* stripped off.
*/
- if (argbase != NULL)
- argp = smprintf("%s%s", p[0]? p : "/", argbase…
- else
- argp = xstrdup(p[0]? p : "/");
+ argp = smprintf("%s%s", *p? p : "/", argbase? argbase …
free(el->e[2]);
el->e[2] = argp;
free(realbase);
}
- free(path);
+ if (rpath != NULL)
+ free(rpath);
}
if (dprintf(fd, "%.1s%s\t%s\t%s\t%s\r\n", el->e[0], el->e[1], el->e[2],
el->e[3], el->e[4]) < 0) {
- perror("printelem: dprintf");
+ perror("printgphelem: dprintf");
return -1;
}
return 0;
@@ -545,19 +547,26 @@ setcgienviron(char *file, char *path, char *port, char *b…
setenv("GATEWAY_INTERFACE", "CGI/1.1", 1);
/* TODO: Separate, if run like rest.dcgi. */
setenv("PATH_INFO", file, 1);
+ printf("PATH_INFO = %s\n", file);
setenv("PATH_TRANSLATED", path, 1);
+ printf("PATH_TRANSLATED = %s\n", path);
setenv("QUERY_STRING", args, 1);
+ printf("QUERY_STRING = %s\n", args);
/* legacy compatibility */
setenv("SELECTOR", args, 1);
+ printf("SELECTOR = %s\n", args);
setenv("REQUEST", args, 1);
+ printf("REQUEST = %s\n", args);
setenv("REMOTE_ADDR", chost, 1);
+ printf("REMOTE_ADDR = %s\n", chost);
/*
* Don't do a reverse lookup on every call. Only do when needed, in
* the script. The RFC allows us to set the IP to the value.
*/
setenv("REMOTE_HOST", chost, 1);
+ printf("REMOTE_HOST = %s\n", chost);
/* Please do not implement identd here. */
unsetenv("REMOTE_IDENT");
unsetenv("REMOTE_USER");
@@ -569,9 +578,12 @@ setcgienviron(char *file, char *path, char *port, char *ba…
*/
setenv("REQUEST_METHOD", "GET", 1);
setenv("SCRIPT_NAME", file, 1);
+ printf("SCRIPT_NAME = %s\n", file);
setenv("SERVER_NAME", ohost, 1);
+ printf("SERVER_PORT = %s\n", port);
setenv("SERVER_PORT", port, 1);
setenv("SERVER_LISTEN_NAME", bhost, 1);
+ printf("SERVER_LISTEN_NAME = %s\n", bhost);
if (istls) {
setenv("SERVER_PROTOCOL", "gophers/1.0", 1);
} else {
@@ -580,8 +592,10 @@ setcgienviron(char *file, char *path, char *port, char *ba…
setenv("SERVER_SOFTWARE", "geomyidae", 1);
setenv("X_GOPHER_SEARCH", sear, 1);
+ printf("X_GOPHER_SEARCH = %s\n", sear);
/* legacy compatibility */
setenv("SEARCHREQUEST", sear, 1);
+ printf("SEARCHREQUEST = %s\n", sear);
if (istls) {
setenv("GOPHERS", "on", 1);
@@ -626,14 +640,3 @@ humantime(const time_t *clock)
return buf;
}
-char *
-makebasepath(char *path, char *base)
-{
- if (!(base[0] == '/' && base[1] == '\0') &&
- strlen(path) > strlen(base)) {
- return path + strlen(base);
- } else {
- return path;
- }
-}
-
diff --git a/ind.h b/ind.h
@@ -10,18 +10,6 @@
extern int glfd;
-typedef struct Elems Elems;
-struct Elems {
- char **e;
- int num;
-};
-
-typedef struct Indexs Indexs;
-struct Indexs {
- Elems **n;
- int num;
-};
-
typedef struct filetype filetype;
struct filetype {
char *end;
@@ -31,20 +19,34 @@ struct filetype {
};
filetype *gettype(char *filename);
+
+typedef struct gphelem gphelem;
+struct gphelem {
+ char **e;
+ int num;
+};
+
+typedef struct gphindex gphindex;
+struct gphindex {
+ gphelem **n;
+ int num;
+};
+
+gphindex *gph_scanfile(char *fname);
+gphelem *gph_getadv(char *str);
+int gph_printelem(int fd, gphelem *el, char *file, char *base, char *addr, cha…
+void gph_addindex(gphindex *idx, gphelem *el);
+void gph_addelem(gphelem *e, char *s);
+void gph_freeindex(gphindex *i);
+void gph_freeelem(gphelem *e);
+
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
void *xrealloc(void *, size_t);
char *xstrdup(const char *str);
int xsendfile(int, int);
-Indexs *scanfile(char *fname);
-Elems *getadv(char *str);
int pendingbytes(int sock);
void waitforpendingbytes(int sock);
-int printelem(int fd, Elems *el, char *file, char *base, char *addr, char *por…
-void addindexs(Indexs *idx, Elems *el);
-void addelem(Elems *e, char *s);
-void freeindex(Indexs *i);
-void freeelem(Elems *e);
char *smprintf(char *fmt, ...);
char *reverselookup(char *host);
void setcgienviron(char *file, char *path, char *port, char *base,
@@ -52,7 +54,6 @@ void setcgienviron(char *file, char *path, char *port, char *…
char *bhost, int istls);
char *humansize(off_t n);
char *humantime(const time_t *clock);
-char *makebasepath(char *path, char *base);
#endif
diff --git a/index.gph b/index.gph
@@ -3,9 +3,11 @@ tcomment (old style comment)
[1|R-36|/|server|port]
[0|file - comment|/file.txt|server|port]
[h|http://www.heise.de|URL:http://www.heise.de|server|port]
-[0|some \| escape and [ special characters ] test|error|server|port]
+[0|some \| escape and [ special characters ] test|Err|server|port]
[9|binary data file|/file.dat|server|port]
[9|unclosed entry|/file.dat|server|port
+[9|some relative path with args|./legacy/caps.txt?key=value|server|port]
+[9|some other relative path|legacy/caps.txt|server|port]
[|empty type||server|port]
[|Escape something, [| is skipped.
some invalid line
diff --git a/main.c b/main.c
@@ -59,7 +59,7 @@ int nlistfds = 0;
char *argv0;
char stdbase[] = "/var/gopher";
char *stdport = "70";
-char *indexf[] = {"/index.gph", "/index.cgi", "/index.dcgi", "/index.bob", "/i…
+char *indexf[] = {"index.gph", "index.cgi", "index.dcgi", "index.bob", "index.…
char *nocgierr = "3Sorry, execution of the token '%s' was requested, but this "
"is disabled in the server configuration.\tErr"
"\tlocalhost\t70\r\n";
@@ -83,7 +83,7 @@ char *htredir = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
" </body>\n"
"</html>\n";
char *selinval ="3Happy helping ☃ here: "
- "Sorry, your selector does not start with / or contains '..'. "
+ "Sorry, your selector does contains '..'. "
"That's illegal here.\tErr\tlocalhost\t70\r\n.\r\n\r\n";
int
@@ -142,12 +142,20 @@ handlerequest(int sock, char *req, int rlen, char *base, …
int len = 0, fd, i, maxrecv, pathfallthrough = 0;
filetype *type;
+ printf("handlerequest:\n");
+ printf("sock = %d; req = '%s';\n", sock, req);
+ printf("rlen = %d; base = '%s'; ohost = '%s'; port = %s;\n", rlen,
+ base, ohost, port);
+ printf("clienth = %s; clientp = %s; serverh = %s; serverp = %s;\n",
+ clienth, clientp, serverh, serverp);
+ printf("nocgi = %d; istls = %d;\n", nocgi, istls);
+
if (!istls) {
/*
* If sticky bit is set on base dir and encryption is not
* used, do not serve.
*/
- if (stat(base, &dir) == -1)
+ if (stat(*base? base : "/", &dir) == -1)
return;
if (dir.st_mode & S_ISVTX) {
dprintf(sock, tlserr, recvc);
@@ -176,6 +184,7 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
c = strchr(recvb, '\n');
if (c)
c[0] = '\0';
+
sear = strchr(recvb, '\t');
if (sear != NULL) {
*sear++ = '\0';
@@ -228,29 +237,32 @@ handlerequest(int sock, char *req, int rlen, char *base, …
* selectors.
*/
+ /* Strip off the arguments of req?args style. */
c = strchr(recvb, '?');
if (c != NULL) {
*c++ = '\0';
- snprintf(args, sizeof(args), "%s", c);
+ snprintf(args, sizeof(args), "?%s", c);
}
+ printf("args = %s\n", args);
+ printf("recvb = %s\n", recvb);
- if (recvb[0] == '\0') {
- recvb[0] = '/';
- recvb[1] = '\0';
+ /* Strip '/' at the end of the request. */
+ for (c = recvb + strlen(recvb) - 1; c >= recvb && c[0] == '/'; c--) {
+ /* Prepend to args. */
+ snprintf(args, sizeof(args), "/%s", args);
+ c[0] = '\0';
}
+ printf("args = %s\n", args);
- /*
- * Do not allow requests not beginning with '/' or which contain
- * "..".
- */
- if (recvb[0] != '/' || strstr(recvb, "..")){
+ /* Do not allow requests including "..". */
+ if (strstr(recvb, "..")) {
dprintf(sock, "%s", selinval);
return;
}
- /* append base to request path (always starting with /), if base is a …
- if (snprintf(path, sizeof(path), "%s%s",
- base[0] == '/' && base[1] == '\0' ? "" : base,
+ printf("recvb = %s\n", recvb);
+ if (snprintf(path, sizeof(path), "%s%s%s", base,
+ (*recvb != '/')? "/" : "",
recvb) > sizeof(path)) {
if (loglvl & ERRORS) {
logentry(clienth, clientp, recvc,
@@ -259,6 +271,8 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
dprintf(sock, toolongerr, recvc);
return;
}
+ /* path is now always at least '/' */
+ printf("path = %s\n", path);
fd = -1;
/*
@@ -270,33 +284,54 @@ handlerequest(int sock, char *req, int rlen, char *base, …
* $args = $rest_of_path + "?" + $args
*/
if (stat(path, &dir) == -1) {
+ printf("Not found. Try backtraversal.\n");
memmove(argsc, args, strlen(args));
snprintf(path, sizeof(path), "%s", base);
- recvbp = recvb + 1;
+ recvbp = recvb;
+
+ /*
+ * Walk into the selector until some directory or file
+ * does not exist. Then reconstruct the args, selector
+ * etc.
+ */
while (recvbp != NULL) {
- sep = strsep(&recvbp, "/");
+ /* Traverse multiple / in selector. */
+ for (sep = recvbp; sep != recvbp && sep != recvbp+1;
+ sep = strsep(&recvbp, "/"));
+ printf("traversal directory = %s\n", sep);
+
+ /* Append found directory to path. */
snprintf(path+strlen(path), sizeof(path)-strlen(path),
"/%s", sep);
+ /* path is now always at least '/' */
+ printf("full traversal path = %s\n", path);
+
if (stat(path, &dir) == -1) {
+ /*
+ * Current try was not found. Go back one
+ * step and finish.
+ */
c = strrchr(path, '/');
if (c != NULL) {
*c++ = '\0';
snprintf(args, sizeof(args),
- "/%s%s%s%s%s",
+ "/%s%s%s%s",
c,
(recvbp != NULL)? "/" : "",
(recvbp != NULL)? recvbp : "",
- (argsc[0] != '\0')? "?" : "",
(argsc[0] != '\0')? argsc : ""
);
+ printf("args = %s\n", args);
}
/* path fallthrough */
pathfallthrough = 1;
+ printf("pathfallthrough = 1\n");
break;
}
}
}
+ printf("path = %s\n", path);
if (stat(path, &dir) != -1) {
/*
* If sticky bit is set, only serve if this is encrypted.
@@ -311,9 +346,11 @@ handlerequest(int sock, char *req, int rlen, char *base, c…
}
if (S_ISDIR(dir.st_mode)) {
+ printf("S_ISDIR\n");
for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]);
i++) {
- if (strlen(path) + strlen(indexf[i])
+ len = strlen(path);
+ if (len + strlen(indexf[i]) + (path[len-1] == …
>= sizeof(path)) {
if (loglvl & ERRORS) {
logentry(clienth, clientp,
@@ -322,12 +359,18 @@ handlerequest(int sock, char *req, int rlen, char *base, …
}
return;
}
- strncat(path, indexf[i],
- sizeof(path)-strlen(path)-1);
+ sprintf(path, "%s%s%s",
+ path,
+ (path[len-1] == '/')? "" : "/",
+ indexf[i]);
+ printf("path index = %s\n", path);
fd = open(path, O_RDONLY);
if (fd >= 0)
break;
- path[strlen(path)-strlen(indexf[i])] = '\0';
+
+ /* Not found. Clear path from indexf. */
+ printf("len = %d\n", len);
+ path[len] = '\0';
}
} else {
fd = open(path, O_RDONLY);
@@ -342,10 +385,9 @@ handlerequest(int sock, char *req, int rlen, char *base, c…
}
}
+ /* Some file was opened. Serve it. */
if (fd >= 0) {
close(fd);
- if (loglvl & FILES)
- logentry(clienth, clientp, recvc, "serving");
c = strrchr(path, '/');
if (c == NULL)
@@ -359,8 +401,10 @@ handlerequest(int sock, char *req, int rlen, char *base, c…
if (pathfallthrough &&
!(type->f == handledcgi || type->f == handlecg…
dprintf(sock, notfounderr, recvc);
- if (loglvl & ERRORS)
- logentry(clienth, clientp, recvc, "not found");
+ if (loglvl & ERRORS) {
+ logentry(clienth, clientp, recvc,
+ "handler in path fallthrough not allow…
+ }
return;
}
@@ -369,14 +413,21 @@ handlerequest(int sock, char *req, int rlen, char *base, …
if (loglvl & ERRORS)
logentry(clienth, clientp, recvc, "nocgi error…
} else {
+ if (loglvl & FILES)
+ logentry(clienth, clientp, recvc, "serving");
+
type->f(sock, path, port, base, args, sear, ohost,
clienth, serverh, istls);
}
} else {
- /*
- * If we had to traverse the path, do not allow directory
- * listings, only dynamic content.
- */
+ if (pathfallthrough && S_ISDIR(dir.st_mode)) {
+ if (loglvl & ERRORS) {
+ logentry(clienth, clientp, recvc,
+ "directory listing in traversal not al…
+ }
+ return;
+ }
+
if (!pathfallthrough && S_ISDIR(dir.st_mode)) {
handledir(sock, path, port, base, args, sear, ohost,
clienth, serverh, istls);
@@ -791,7 +842,7 @@ main(int argc, char *argv[])
perror("chdir");
return 1;
}
- base = "/";
+ base = "";
if (chroot(".") < 0) {
perror("chroot");
return 1;
@@ -801,9 +852,9 @@ main(int argc, char *argv[])
return 1;
}
- /* strip / at the end, except if it is "/" */
- for (p = base + strlen(base); p > base + 1 && p[-1] == '/'; --p)
- p[-1] = '\0';
+ /* strip / at the end of base */
+ for (p = base + strlen(base) - 1; p >= base && p[0] == '/'; --p)
+ p[0] = '\0';
if (dropprivileges(gr, us) < 0) {
perror("dropprivileges");
@@ -1063,21 +1114,32 @@ read_selector_again:
close(tlssocks[tlsclientreader? 1 : 0]…
do {
if (tlsclientreader) {
- shuflen = read(tlssock…
+ shuflen = read(tlssock…
+ shufbuf,
+ sizeof(shufbuf…
} else {
- shuflen = tls_read(tls…
+ shuflen = tls_read(tls…
+ shufbuf,
+ sizeof(shufbuf…
}
if (shuflen == -1 && errno == …
continue;
- for (shufpos = 0; shufpos < sh…
+ for (shufpos = 0; shufpos < sh…
+ shufpos += wle…
if (tlsclientreader) {
- wlen = tls_wri…
+ wlen = tls_wri…
+ shufbu…
+ shufle…
if (wlen < 0) {
- fprint…
+ fprint…
+ …
+ …
return…
}
} else {
- wlen = write(t…
+ wlen = write(t…
+ shufbu…
+ shufle…
if (wlen < 0) {
perror…
return…
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.