Merge branch 'master' of tildegit.org:solene/vger
This commit is contained in:
commit
de52acecfc
2 changed files with 28 additions and 65 deletions
81
main.c
81
main.c
|
@ -27,12 +27,14 @@
|
||||||
*/
|
*/
|
||||||
#define GEMINI_REQUEST_MAX 1025
|
#define GEMINI_REQUEST_MAX 1025
|
||||||
|
|
||||||
|
int virtualhost;
|
||||||
|
|
||||||
void autoindex(const char *);
|
void autoindex(const char *);
|
||||||
void cgi(const char *cgicmd);
|
void cgi(const char *cgicmd);
|
||||||
void display_file(const char *);
|
void display_file(const char *);
|
||||||
void status(const int, const char *);
|
void status(const int, const char *);
|
||||||
void status_redirect(const int, const char *);
|
void status_redirect(const int, const char *);
|
||||||
|
void status_error(const int, const char*);
|
||||||
void drop_privileges(const char *, const char *);
|
void drop_privileges(const char *, const char *);
|
||||||
int uridecode(char *);
|
int uridecode(char *);
|
||||||
|
|
||||||
|
@ -129,16 +131,14 @@ drop_privileges(const char *user, const char *path)
|
||||||
|
|
||||||
eunveil(cgifullpath, "rx");
|
eunveil(cgifullpath, "rx");
|
||||||
}
|
}
|
||||||
/* forbid more unveil */
|
|
||||||
eunveil(NULL, NULL);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prevent system calls other parsing queryfor fread file and
|
* prevent system calls other parsing queryfor fread file and
|
||||||
* write to stdio
|
* write to stdio
|
||||||
*/
|
*/
|
||||||
if (strlen(cgibin) > 0) {
|
if (strlen(cgibin) > 0) {
|
||||||
/* cgi need execlp() (exec) and fork() (proc) */
|
/* cgi need execlp() (exec) */
|
||||||
epledge("stdio rpath exec proc", NULL);
|
epledge("stdio rpath exec", NULL);
|
||||||
} else {
|
} else {
|
||||||
epledge("stdio rpath", NULL);
|
epledge("stdio rpath", NULL);
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,13 @@ status_redirect(const int code, const char *url)
|
||||||
code, url);
|
code, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
status_error(const int code, const char *reason)
|
||||||
|
{
|
||||||
|
printf("%i %s\r\n",
|
||||||
|
code, reason);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
display_file(const char *uri)
|
display_file(const char *uri)
|
||||||
{
|
{
|
||||||
|
@ -190,7 +197,9 @@ display_file(const char *uri)
|
||||||
if (S_ISDIR(sb.st_mode) != 0) {
|
if (S_ISDIR(sb.st_mode) != 0) {
|
||||||
if (fp[strlen(fp) -1 ] != '/') {
|
if (fp[strlen(fp) -1 ] != '/') {
|
||||||
/* no ending "/", redirect to "path/" */
|
/* no ending "/", redirect to "path/" */
|
||||||
estrlcpy(tmp, uri, sizeof(tmp));
|
if (virtualhost)
|
||||||
|
estrlcat(tmp, "gemini://", sizeof(tmp));
|
||||||
|
estrlcat(tmp, uri, sizeof(tmp));
|
||||||
estrlcat(tmp, "/", sizeof(tmp));
|
estrlcat(tmp, "/", sizeof(tmp));
|
||||||
status_redirect(31, tmp);
|
status_redirect(31, tmp);
|
||||||
return;
|
return;
|
||||||
|
@ -229,7 +238,7 @@ display_file(const char *uri)
|
||||||
|
|
||||||
err:
|
err:
|
||||||
/* return an error code and no content */
|
/* return an error code and no content */
|
||||||
status(51, "text/gemini");
|
status_error(51, "file not found");
|
||||||
syslog(LOG_DAEMON, "path invalid %s", fp);
|
syslog(LOG_DAEMON, "path invalid %s", fp);
|
||||||
goto closefd;
|
goto closefd;
|
||||||
|
|
||||||
|
@ -255,11 +264,8 @@ autoindex(const char *path)
|
||||||
char *pos = NULL;
|
char *pos = NULL;
|
||||||
struct dirent **namelist; /* this must be freed at last */
|
struct dirent **namelist; /* this must be freed at last */
|
||||||
|
|
||||||
|
|
||||||
syslog(LOG_DAEMON, "autoindex: %s", path);
|
syslog(LOG_DAEMON, "autoindex: %s", path);
|
||||||
|
|
||||||
status(20, "text/gemini");
|
|
||||||
|
|
||||||
/* display link to parent */
|
/* display link to parent */
|
||||||
char parent[PATH_MAX] = {'\0'};
|
char parent[PATH_MAX] = {'\0'};
|
||||||
/* parent is "path" without chroot_dir */
|
/* parent is "path" without chroot_dir */
|
||||||
|
@ -273,13 +279,14 @@ autoindex(const char *path)
|
||||||
if (pos != NULL) {
|
if (pos != NULL) {
|
||||||
pos[1] = '\0'; /* at worse, parent is now "/" */
|
pos[1] = '\0'; /* at worse, parent is now "/" */
|
||||||
}
|
}
|
||||||
printf("=> %s ../\n", parent);
|
|
||||||
|
|
||||||
/* use alphasort to always have the same order on every system */
|
/* use alphasort to always have the same order on every system */
|
||||||
if ((n = scandir(path, &namelist, NULL, alphasort)) < 0) {
|
if ((n = scandir(path, &namelist, NULL, alphasort)) < 0) {
|
||||||
status(51, "text/gemini");
|
status_error(50, "Internal server error");
|
||||||
errlog("Can't scan %s", path);
|
errlog("Can't scan %s", path);
|
||||||
} else {
|
} else {
|
||||||
|
status(20, "text/gemini");
|
||||||
|
printf("=> %s ../\n", parent);
|
||||||
for(int j = 0; j < n; j++) {
|
for(int j = 0; j < n; j++) {
|
||||||
/* skip self and parent */
|
/* skip self and parent */
|
||||||
if ((strcmp(namelist[j]->d_name, ".") == 0) ||
|
if ((strcmp(namelist[j]->d_name, ".") == 0) ||
|
||||||
|
@ -301,58 +308,11 @@ autoindex(const char *path)
|
||||||
void
|
void
|
||||||
cgi(const char *cgicmd)
|
cgi(const char *cgicmd)
|
||||||
{
|
{
|
||||||
|
|
||||||
int pipedes[2] = {0};
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
/* get a pipe to get stdout */
|
|
||||||
if (pipe(pipedes) != 0) {
|
|
||||||
status(42, "text/gemini");
|
|
||||||
err(1, "pipe failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
|
|
||||||
if (pid < 0) {
|
|
||||||
close(pipedes[0]);
|
|
||||||
close(pipedes[1]);
|
|
||||||
status(42, "text/gemini");
|
|
||||||
err(1, "fork failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid > 0) { /* parent */
|
|
||||||
char buf[3];
|
|
||||||
size_t nread = 0;
|
|
||||||
FILE *output = NULL;
|
|
||||||
|
|
||||||
close(pipedes[1]); /* make sure entry is closed so fread() gets EOF */
|
|
||||||
|
|
||||||
/* use fread/fwrite because are buffered */
|
|
||||||
output = fdopen(pipedes[0], "r");
|
|
||||||
if (output == NULL) {
|
|
||||||
status(42, "text/gemini");
|
|
||||||
err(1, "fdopen failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read pipe output */
|
|
||||||
while ((nread = fread(buf, 1, sizeof(buf), output)) != 0) {
|
|
||||||
fwrite(buf, 1, nread, stdout);
|
|
||||||
}
|
|
||||||
close(pipedes[0]);
|
|
||||||
fclose(output);
|
|
||||||
|
|
||||||
wait(NULL); /* wait for child to terminate */
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
|
|
||||||
} else if (pid == 0) { /* child */
|
|
||||||
dup2(pipedes[1], STDOUT_FILENO); /* set pipe output equal to stdout */
|
|
||||||
close(pipedes[1]); /* no need this file descriptor : it is now stdout */
|
|
||||||
execlp(cgicmd, cgicmd, NULL);
|
execlp(cgicmd, cgicmd, NULL);
|
||||||
/* if execlp is ok, this will never be reached */
|
/* if execlp is ok, this will never be reached */
|
||||||
status(42, "text/gemini");
|
status(42, "Couldn't execute CGI script");
|
||||||
errlog("error when trying to execlp %s", cgicmd);
|
errlog("error when trying to execlp %s", cgicmd);
|
||||||
}
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -363,7 +323,6 @@ main(int argc, char **argv)
|
||||||
char uri [PATH_MAX] = {'\0'};
|
char uri [PATH_MAX] = {'\0'};
|
||||||
char user [_SC_LOGIN_NAME_MAX] = "";
|
char user [_SC_LOGIN_NAME_MAX] = "";
|
||||||
char query[PATH_MAX] = {'\0'};
|
char query[PATH_MAX] = {'\0'};
|
||||||
int virtualhost = 0;
|
|
||||||
int option = 0;
|
int option = 0;
|
||||||
char *pos = NULL;
|
char *pos = NULL;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,10 @@ if ! [ $OUT = "fcc5a293f316e01f7b3103f97eca26b1" ] ; then echo "error" ; exit 1
|
||||||
OUT=$(printf "gemini://host.name/subdir\r\n" | ../vger -d var/gemini/ | tee /dev/stderr | MD5)
|
OUT=$(printf "gemini://host.name/subdir\r\n" | ../vger -d var/gemini/ | tee /dev/stderr | MD5)
|
||||||
if ! [ $OUT = "84e5e7bb3eee0dfcc8db14865dc83e77" ] ; then echo "error" ; exit 1 ; fi
|
if ! [ $OUT = "84e5e7bb3eee0dfcc8db14865dc83e77" ] ; then echo "error" ; exit 1 ; fi
|
||||||
|
|
||||||
|
# redirect to uri with trailing / if directory and vhost enabled
|
||||||
|
OUT=$(printf "gemini://perso.pw/cgi-bin\r\n" | ../vger -vd var/gemini | tee /dev/stderr | MD5)
|
||||||
|
if ! [ $OUT = "c782da4173898f57033a0804b8e96fc3" ] ; then echo "error" ; exit 1 ; fi
|
||||||
|
|
||||||
# file from local directory with lang=fr and markdown MIME type
|
# file from local directory with lang=fr and markdown MIME type
|
||||||
OUT=$(printf "gemini://perso.pw/file.md\r\n" | ../vger -d var/gemini/ -l fr | tee /dev/stderr | MD5)
|
OUT=$(printf "gemini://perso.pw/file.md\r\n" | ../vger -d var/gemini/ -l fr | tee /dev/stderr | MD5)
|
||||||
if ! [ $OUT = "e663f17730d5ddc24010c14a238e1e78" ] ; then echo "error" ; exit 1 ; fi
|
if ! [ $OUT = "e663f17730d5ddc24010c14a238e1e78" ] ; then echo "error" ; exit 1 ; fi
|
||||||
|
@ -85,7 +89,7 @@ if ! [ $OUT = "fa065a67d1f7c973501d4a9e3ca2ea57" ] ; then echo "error" ; exit 1
|
||||||
|
|
||||||
# cgi with error
|
# cgi with error
|
||||||
OUT=$(printf "gemini://host.name/cgi-bin/nope\r\n" | ../vger -d var/gemini/ -c /cgi-bin | tee /dev/stderr | MD5)
|
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
|
if ! [ $OUT = "4156170c2aa8a6a8a0892ff5a61bf5f5" ] ; then echo "error" ; exit 1 ; fi
|
||||||
|
|
||||||
# remove ?.* if any
|
# remove ?.* if any
|
||||||
OUT=$(printf "gemini://host.name/main.gmi?anything-here\r\n" | ../vger -d var/gemini/ | tee /dev/stderr | MD5)
|
OUT=$(printf "gemini://host.name/main.gmi?anything-here\r\n" | ../vger -d var/gemini/ | tee /dev/stderr | MD5)
|
||||||
|
|
Loading…
Reference in a new issue