Introduction
Introduction Statistics Contact Development Disclaimer Help
Fix traversal handling, add selector and traversal to CGI environment. - geomyi…
git clone git://git.codemadness.org/geomyidae
Log
Files
Refs
README
LICENSE
---
commit a291bc8c99309fcbfd1a7688988ba60a2e5bf042
parent b12a77acd24fc170b1ad047986ffaf13592fb326
Author: Christoph Lohmann <[email protected]>
Date: Sat, 22 Jul 2023 15:28:45 +0200
Fix traversal handling, add selector and traversal to CGI environment.
* Add raw selector to CGI scripts.
* Add traversal to CGI scripts.
* Add both to manpages.
Diffstat:
M geomyidae.8 | 9 ++++++---
M handlr.c | 56 ++++++++++++++++-------------…
M handlr.h | 18 +++++++++++-------
M ind.c | 21 +++++----------------
M ind.h | 4 ++--
M main.c | 102 +++++++++++++++--------------…
6 files changed, 102 insertions(+), 108 deletions(-)
---
diff --git a/geomyidae.8 b/geomyidae.8
@@ -352,9 +352,11 @@ executable.[d]cgi $search $arguments $host $port
where
.Bd -literal -offset indent
search = query string (type 7) or "" (type 0)
-arguments = string after "?" in the path, the remaining path or ""
+arguments = string behind "?" in selector or ""
host = server's hostname ("localhost" by default)
port = server's port ("70" by default)
+traversal = remaining path from path traversal
+selector = raw selector
.Ed
.Pp
All terms are tab-separated (per gopher protocol) which can cause some
@@ -377,8 +379,9 @@ GATEWAY_INTERFACE = `CGI/1.1'
PATH_INFO = script which is executed
PATH_TRANSLATED = absolute path with script which is executed
QUERY_STRING = arguments (See above.)
-SELECTOR = arguments (For backwards compatibility.)
-REQUEST = arguments (For backwards compatibility.)
+SELECTOR = raw selector
+REQUEST = raw selector
+TRAVERSAL = traversel (See above.)
REMOTE_ADDR = IP of the client
REMOTE_HOST = REMOTE_ADDR
REQUEST_METHOD = `GET'
diff --git a/handlr.c b/handlr.c
@@ -24,7 +24,8 @@
void
handledir(int sock, char *path, char *port, char *base, char *args,
- char *sear, char *ohost, char *chost, char *bhost, int istls)
+ char *sear, char *ohost, char *chost, char *bhost, int istls,
+ char *sel, char *traverse)
{
char *pa, *file, *e, *par;
struct dirent **dirent;
@@ -35,12 +36,8 @@ handledir(int sock, char *path, char *port, char *base, char…
USED(args);
USED(sear);
USED(bhost);
-
- 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);
+ USED(sel);
+ USED(traverse);
pa = xstrdup(path);
@@ -70,7 +67,6 @@ handledir(int sock, char *path, char *port, char *base, char …
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");
ret = dprintf(sock,
@@ -93,7 +89,8 @@ handledir(int sock, char *path, char *port, char *base, char …
void
handlegph(int sock, char *file, char *port, char *base, char *args,
- char *sear, char *ohost, char *chost, char *bhost, int istls)
+ char *sear, char *ohost, char *chost, char *bhost, int istls,
+ char *sel, char *traverse)
{
gphindex *act;
int i, ret = 0;
@@ -101,12 +98,8 @@ handlegph(int sock, char *file, char *port, char *base, cha…
USED(args);
USED(sear);
USED(bhost);
-
- 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);
+ USED(sel);
+ USED(traverse);
act = gph_scanfile(file);
if (act != NULL) {
@@ -124,7 +117,8 @@ handlegph(int sock, char *file, char *port, char *base, cha…
void
handlebin(int sock, char *file, char *port, char *base, char *args,
- char *sear, char *ohost, char *chost, char *bhost, int istls)
+ char *sear, char *ohost, char *chost, char *bhost, int istls,
+ char *sel, char *traverse)
{
int fd;
@@ -134,6 +128,8 @@ handlebin(int sock, char *file, char *port, char *base, cha…
USED(sear);
USED(ohost);
USED(bhost);
+ USED(sel);
+ USED(traverse);
fd = open(file, O_RDONLY);
if (fd >= 0) {
@@ -145,9 +141,10 @@ handlebin(int sock, char *file, char *port, char *base, ch…
void
handlecgi(int sock, char *file, char *port, char *base, char *args,
- char *sear, char *ohost, char *chost, char *bhost, int istls)
+ char *sear, char *ohost, char *chost, char *bhost, int istls,
+ char *sel, char *traverse)
{
- char *script, *path;
+ char *script, *path, *filec;
USED(base);
USED(port);
@@ -157,9 +154,10 @@ handlecgi(int sock, char *file, char *port, char *base, ch…
sock, file, port, base, args);
printf("sear = %s; ohost = %s; chost = %s; bhost = %s; istls = %d;\n",
sear, ohost, chost, bhost, istls);
+ printf("sel = %s; traverse = %s;\n", sel, traverse);
- path = xstrdup(file);
- path = dirname(path);
+ filec = xstrdup(file);
+ path = dirname(filec);
script = path + strlen(path) + 1;
printf("path = %s\n", path);
printf("script = %s\n", script);
@@ -180,7 +178,7 @@ handlecgi(int sock, char *file, char *port, char *base, cha…
}
setcgienviron(script, file, port, base, args, sear, ohost, cho…
- bhost, istls);
+ bhost, istls, sel, traverse);
if (execl(file, script, sear, args, ohost, port,
(char *)NULL) == -1) {
@@ -192,17 +190,18 @@ handlecgi(int sock, char *file, char *port, char *base, c…
break;
default:
wait(NULL);
- free(path);
+ free(filec);
break;
}
}
void
handledcgi(int sock, char *file, char *port, char *base, char *args,
- char *sear, char *ohost, char *chost, char *bhost, int istls)
+ char *sear, char *ohost, char *chost, char *bhost, int istls,
+ char *sel, char *traverse)
{
FILE *fp;
- char *script, *path, *ln = NULL;
+ char *script, *path, *filec, *ln = NULL;
size_t linesiz = 0;
ssize_t n;
int outsocks[2], ret = 0;
@@ -213,12 +212,13 @@ handledcgi(int sock, char *file, char *port, char *base, …
sock, file, port, base, args);
printf("sear = %s; ohost = %s; chost = %s; bhost = %s; istls = %d;\n",
sear, ohost, chost, bhost, istls);
+ printf("sel = %s; traverse = %s;\n", sel, traverse);
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, outsocks) < 0)
return;
- path = xstrdup(file);
- path = dirname(path);
+ filec = xstrdup(file);
+ path = dirname(filec);
script = path + strlen(path) + 1;
if (sear == NULL)
@@ -238,7 +238,7 @@ handledcgi(int sock, char *file, char *port, char *base, ch…
}
setcgienviron(script, file, port, base, args, sear, ohost, cho…
- bhost, istls);
+ bhost, istls, sel, traverse);
if (execl(file, script, sear, args, ohost, port,
(char *)NULL) == -1) {
@@ -277,7 +277,7 @@ handledcgi(int sock, char *file, char *port, char *base, ch…
free(ln);
fclose(fp);
wait(NULL);
- free(path);
+ free(filec);
break;
}
}
diff --git a/handlr.h b/handlr.h
@@ -23,7 +23,7 @@
* 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
+ * Sample: key=value
* sear .... search part of request
* Sample: search what?
* ohost ... host of geomyidae (See -h in geomyidae(8))
@@ -34,25 +34,29 @@
* Sample: 78.46.175.99
* istls ... set to 1, if TLS was used for thr request
* Sample: 1
+ * sel ..... Gives the raw selector after processing.
+ * Sample: /get/some/script/with/dirs////?key=value
+ * traversal ..... Gives the raw selector after processing.
+ * Sample: /with/dirs////
*/
void handledir(int sock, char *path, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost,
- int istls);
+ int istls, char *sel, char *traverse);
void handlegph(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost,
- int istls);
+ int istls, char *sel, char *traverse);
void handlebin(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost,
- int istls);
+ int istls, char *sel, char *traverse);
void handletxt(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost,
- int istls);
+ int istls, char *sel, char *traverse);
void handlecgi(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost,
- int istls);
+ int istls, char *sel, char *traverse);
void handledcgi(int sock, char *file, char *port, char *base, char *args,
char *sear, char *ohost, char *chost, char *bhost,
- int istls);
+ int istls, char *sel, char *traverse);
#endif
diff --git a/ind.c b/ind.c
@@ -535,7 +535,8 @@ reverselookup(char *host)
void
setcgienviron(char *file, char *path, char *port, char *base, char *args,
- char *sear, char *ohost, char *chost, char *bhost, int istls)
+ char *sear, char *ohost, char *chost, char *bhost, int istls,
+ char *sel, char *traverse)
{
/*
* TODO: Clean environment from possible unsafe environment variables.
@@ -547,26 +548,19 @@ 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("SELECTOR", sel, 1);
+ setenv("REQUEST", sel, 1);
+ setenv("TRAVERSAL", traverse, 1);
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");
@@ -578,12 +572,9 @@ 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 {
@@ -592,10 +583,8 @@ 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);
diff --git a/ind.h b/ind.h
@@ -15,7 +15,7 @@ struct filetype {
char *end;
char *type;
void (* f)(int, char *, char *, char *, char *, char *, char *,
- char *, char *, int);
+ char *, char *, int, char *, char *);
};
filetype *gettype(char *filename);
@@ -51,7 +51,7 @@ char *smprintf(char *fmt, ...);
char *reverselookup(char *host);
void setcgienviron(char *file, char *path, char *port, char *base,
char *args, char *sear, char *ohost, char *chost,
- char *bhost, int istls);
+ char *bhost, int istls, char *sel, char *traverse);
char *humansize(off_t n);
char *humantime(const time_t *clock);
diff --git a/main.c b/main.c
@@ -137,8 +137,9 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
char *serverp, int nocgi, int istls)
{
struct stat dir;
- char recvc[1025], recvb[1025], path[1025], args[1025], argsc[1025],
- *sear, *c, *sep, *recvbp;
+ char recvc[1025], recvb[1025], path[PATH_MAX+1], rpath[PATH_MAX+1], ar…
+ argsc[1025], traverse[1025], traversec[1025],
+ *sear, *sep, *recvbp, *c;
int len = 0, fd, i, maxrecv, pathfallthrough = 0;
filetype *type;
@@ -172,6 +173,7 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
memset(recvc, 0, sizeof(recvc));
memset(args, 0, sizeof(args));
memset(argsc, 0, sizeof(argsc));
+ memset(traverse, 0, sizeof(argsc));
maxrecv = sizeof(recvb) - 1;
if (rlen > maxrecv || rlen < 0)
@@ -241,18 +243,19 @@ handlerequest(int sock, char *req, int rlen, char *base, …
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);
/* 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);
+ memmove(traversec, traverse, strlen(traverse));
+ /* Prepend to traverse. */
+ snprintf(traverse, sizeof(traverse), "/%s", traversec);
c[0] = '\0';
}
- printf("args = %s\n", args);
+ printf("traverse = %s\n", traverse);
/* Do not allow requests including "..". */
if (strstr(recvb, "..")) {
@@ -284,8 +287,7 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
* $args = $rest_of_path + "?" + $args
*/
if (stat(path, &dir) == -1) {
- printf("Not found. Try backtraversal.\n");
- memmove(argsc, args, strlen(args));
+ memmove(traversec, traverse, strlen(traverse));
snprintf(path, sizeof(path), "%s", base);
recvbp = recvb;
@@ -295,44 +297,42 @@ handlerequest(int sock, char *req, int rlen, char *base, …
* etc.
*/
while (recvbp != NULL) {
- /* Traverse multiple / in selector. */
- for (sep = recvbp; sep != recvbp && sep != recvbp+1;
- sep = strsep(&recvbp, "/"));
- printf("traversal directory = %s\n", sep);
+ /* Traverse multiple empty / in selector. */
+ while(recvbp[0] == '/')
+ recvbp++;
+ sep = strchr(recvbp, '/');
+ if (sep != NULL)
+ *sep++ = '\0';
- /* Append found directory to path. */
snprintf(path+strlen(path), sizeof(path)-strlen(path),
- "/%s", sep);
+ "/%s", recvbp);
/* 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",
- c,
- (recvbp != NULL)? "/" : "",
- (recvbp != NULL)? recvbp : "",
- (argsc[0] != '\0')? argsc : ""
- );
- printf("args = %s\n", args);
- }
+ path[strlen(path)-strlen(recvbp)-1] = '\0';
+ snprintf(traverse, sizeof(traverse),
+ "/%s%s%s%s",
+ recvbp,
+ (sep != NULL)? "/" : "",
+ (sep != NULL)? sep : "",
+ (traversec[0] != '\0')? traversec : ""
+ );
/* path fallthrough */
pathfallthrough = 1;
printf("pathfallthrough = 1\n");
break;
}
+ /* Append found directory to path. */
+ recvbp = sep;
}
}
- printf("path = %s\n", path);
- if (stat(path, &dir) != -1) {
+ if (realpath(path, (char *)&rpath) == NULL) {
+ dprintf(sock, notfounderr, recvc);
+ if (loglvl & ERRORS)
+ logentry(clienth, clientp, recvc, "not found");
+ }
+ printf("rpath = %s\n", rpath);
+ if (stat(rpath, &dir) != -1) {
/*
* If sticky bit is set, only serve if this is encrypted.
*/
@@ -349,9 +349,9 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
printf("S_ISDIR\n");
for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]);
i++) {
- len = strlen(path);
- if (len + strlen(indexf[i]) + (path[len-1] == …
- >= sizeof(path)) {
+ len = strlen(rpath);
+ if (len + strlen(indexf[i]) + (rpath[len-1] ==…
+ >= sizeof(rpath)) {
if (loglvl & ERRORS) {
logentry(clienth, clientp,
recvc,
@@ -359,21 +359,19 @@ handlerequest(int sock, char *req, int rlen, char *base, …
}
return;
}
- sprintf(path, "%s%s%s",
- path,
- (path[len-1] == '/')? "" : "/",
- indexf[i]);
- printf("path index = %s\n", path);
- fd = open(path, O_RDONLY);
+ if (rpath[len-1] != '/')
+ strcat(rpath, "/");
+ strcat(rpath, indexf[i]);
+ printf("path index = %s\n", rpath);
+ fd = open(rpath, O_RDONLY);
if (fd >= 0)
break;
/* Not found. Clear path from indexf. */
- printf("len = %d\n", len);
- path[len] = '\0';
+ rpath[len] = '\0';
}
} else {
- fd = open(path, O_RDONLY);
+ fd = open(rpath, O_RDONLY);
if (fd < 0) {
dprintf(sock, notfounderr, recvc);
if (loglvl & ERRORS) {
@@ -389,9 +387,9 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
if (fd >= 0) {
close(fd);
- c = strrchr(path, '/');
+ c = strrchr(rpath, '/');
if (c == NULL)
- c = path;
+ c = rpath;
type = gettype(c);
/*
@@ -416,8 +414,8 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
if (loglvl & FILES)
logentry(clienth, clientp, recvc, "serving");
- type->f(sock, path, port, base, args, sear, ohost,
- clienth, serverh, istls);
+ type->f(sock, rpath, port, base, args, sear, ohost,
+ clienth, serverh, istls, recvc, traverse);
}
} else {
if (pathfallthrough && S_ISDIR(dir.st_mode)) {
@@ -429,8 +427,8 @@ handlerequest(int sock, char *req, int rlen, char *base, ch…
}
if (!pathfallthrough && S_ISDIR(dir.st_mode)) {
- handledir(sock, path, port, base, args, sear, ohost,
- clienth, serverh, istls);
+ handledir(sock, rpath, port, base, args, sear, ohost,
+ clienth, serverh, istls, recvc, traverse);
if (loglvl & DIRS) {
logentry(clienth, clientp, recvc,
"dir listing");
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.