ignore after ? and make cgi+virtualhost work (sort of)

This commit is contained in:
prx 2021-01-31 21:21:15 +01:00
parent 3510035711
commit de7cd12f9f
4 changed files with 39 additions and 17 deletions

29
main.c
View file

@ -82,6 +82,9 @@ drop_privileges(const char *user, const char *path)
estrlcat(cgifullpath, cgibin, sizeof(cgifullpath));
eunveil(cgifullpath, "rx");
}
/* no more unveil later */
eunveil(NULL, NULL);
/*
* prevent system calls other parsing queryfor fread file and
* write to stdio
@ -292,6 +295,7 @@ main(int argc, char **argv)
char hostname [GEMINI_REQUEST_MAX] = {'\0'};
char uri [PATH_MAX] = {'\0'};
char user [_SC_LOGIN_NAME_MAX] = "";
char query[PATH_MAX] = {'\0'};
int virtualhost = 0;
int option = 0;
char *pos = NULL;
@ -383,6 +387,14 @@ main(int argc, char **argv)
/* copy hostname from request */
estrlcpy(hostname, request, sizeof(hostname));
/* look for "?" if any to set query for cgi, or remove it*/
pos = strchr(uri, '?');
if (pos != NULL) {
estrlcpy(query, pos+1, sizeof(query));
esetenv("QUERY_STRING", query, 1);
pos[0] = '\0';
}
/*
* if virtualhost feature is actived looking under the chroot_path +
* hostname directory gemini://foobar/hello will look for
@ -392,15 +404,16 @@ main(int argc, char **argv)
if (strlen(uri) == 0) {
estrlcpy(uri, "/index.gmi", sizeof(uri));
}
char new_uri[PATH_MAX] = {'\0'};
estrlcpy(new_uri, hostname, sizeof(new_uri));
estrlcat(new_uri, uri, sizeof(new_uri));
estrlcpy(uri, new_uri, sizeof(uri));
char tmp[PATH_MAX] = {'\0'};
estrlcpy(tmp, hostname, sizeof(tmp));
estrlcat(tmp, uri, sizeof(tmp));
estrlcpy(uri, tmp, sizeof(uri));
}
/* check if uri is cgibin */
if ((strlen(cgibin) > 0) &&
(strncmp(uri, cgibin, strlen(cgibin)) == 0)) {
char cgipath[PATH_MAX] = {'\0'};
estrlcpy(cgipath, chroot_dir, sizeof(cgipath));
estrlcat(cgipath, uri, sizeof(cgipath));
@ -410,14 +423,6 @@ main(int argc, char **argv)
esetenv("SERVER_PROTOCOL", "GEMINI", 1);
esetenv("SERVER_SOFTWARE", "vger/1", 1);
/* look for "?" to set query */
pos = strchr(cgipath, '?');
if (pos != NULL) {
char query[PATH_MAX] = {'\0'};
estrlcpy(query, pos+1, sizeof(query));
esetenv("QUERY_STRING", query, 1);
pos[0] = '\0';
}
/* look for an extension to find PATH_INFO */
pos = strrchr(cgipath, '.');
if (pos != NULL) {

View file

@ -86,6 +86,14 @@ if ! [ $OUT = "fa065a67d1f7c973501d4a9e3ca2ea57" ] ; then echo "error" ; exit 1
OUT=$(printf "gemini://host.name/cgi-bin/nope\r\n" | ../vger -d var/gemini/ -c /cgi-bin | tee /dev/stderr | $MD5)
if ! [ $OUT = "2c88347cfac44450035283a8508a29cb" ] ; then echo "error" ; exit 1 ; fi
# remove ?.* if any
OUT=$(printf "gemini://host.name/main.gmi?anything-here\r\n" | ../vger -d var/gemini/ | tee /dev/stderr | $MD5)
if ! [ $OUT = "c7e352d6aae4ee7e7604548f7874fb9d" ] ; then echo "error" ; exit 1 ; fi
# virtualhost + cgi
OUT=$(printf "gemini://perso.pw/cgi-bin/test.cgi\r\n" | ../vger -v -d var/gemini/ -c perso.pw/cgi-bin | tee /dev/stderr | $MD5)
if ! [ $OUT = "666e48200f90018b5e96c2cf974882dc" ] ; then echo "error" ; exit 1 ; fi
# must fail only on OpenBSD !
# try to escape from unveil
if [ -f /bsd ]

View file

@ -0,0 +1,9 @@
#!/bin/sh
printf "%s %s: cgi_test\r\n" "20 text/plain"
echo "env vars:"
echo $GATEWAY_INTERFACE
echo $SERVER_SOFTWARE
echo $PATH_INFO
echo $QUERY_STRING

10
vger.8
View file

@ -44,7 +44,10 @@ will read the file /var/gemini/hostname.example/file.gmi
.It Op Fl c
Enable CGI support.
.Ar cgi_path
will be executed as a cgi script. This path is relative to the served capsule. As example, for a request gemini://hostname.example/cgi-bin/hello.cgi, one must set:
will be executed as a cgi script. This path is relative to the directory set with
.Fl d
flag. If using virtualhost, you must insert the virtualhost directory in the cgi path.
As example, for a request gemini://hostname.example/cgi-bin/hello.cgi, one must set:
.Bd -literal -offset indent
vger -c /cgi-bin/hello.cgi
.Ed
@ -53,10 +56,7 @@ Note you can define a directory instead of a single file.
.Pp
In this case,
.Xr pledge 2
promises are set to "stdio proc exec"
and an additional
.Xr unveil 2
permission on the cgi script is set to "rx".
promises and unveil permission are set to enable cgi execution.
.Pp
Be very careful on how you write your CGI, it can read outside the chroot.
.It Op Fl m Ar mimetype