From 2b835bc39cffe3c446269d4420cd5b4c642ac63a Mon Sep 17 00:00:00 2001 From: prx Date: Wed, 17 Aug 2022 21:28:09 +0200 Subject: [PATCH 01/21] import regex functions to parse request --- utils.c | 15 +++++++++++++++ utils.h | 1 + vger.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ vger.h | 1 + 4 files changed, 69 insertions(+) diff --git a/utils.c b/utils.c index 50e2191..740f545 100644 --- a/utils.c +++ b/utils.c @@ -1,5 +1,8 @@ +#include + #include #include +#include #include #include #include @@ -115,3 +118,15 @@ print_file(FILE *fd) datasent += fwrite(buffer, 1, nread, stdout); return datasent; } + +void +getsubexp(const char *str, regmatch_t m, char *dst) +{ + size_t len = 0; + + if (m.rm_eo > m.rm_so) { /* skip empty substring */ + len = m.rm_eo - m.rm_so; + memcpy(dst, str + m.rm_so, len); + dst[len] = '\0'; + } +} diff --git a/utils.h b/utils.h index 982a3e0..72d64e8 100644 --- a/utils.h +++ b/utils.h @@ -1,3 +1,4 @@ +void getsubexp(const char *, regmatch_t, char *); void echdir (const char *); void epledge(const char *, const char *); void eunveil(const char *, const char *); diff --git a/vger.c b/vger.c index d02f420..04b3c12 100644 --- a/vger.c +++ b/vger.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -503,3 +504,54 @@ get_query(char *path, char *query, size_t querysiz) } return query; } + +void +split_request(const char *request, char *hostname, char *path, char *query) +{ + regex_t greg = {0}; /* compiled gemini regex */ + regmatch_t *match = {0}; /* matches founds */ + size_t nmatch = 4; /* number of substrings to look for */ + char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ + int ret = 0; + + const char *gemini_regex = "^gemini://+([^/|^\?]*)/*([^\?]*)[\?]?(.*)$"; + /* + * ^gemini://+ : in case of gemini:/// + * 1: hostname + * ([^/|^\?]*) : + * catch everything, stop when / or ? is found + * then skip multiple / + * 2: path + * ([^\?]*) : + * catch everything and stop at ? if any + * 3 : query + * [\?]?(.*)$: + * catch everything after ? if any + */ + + if ((ret = regcomp(&greg, gemini_regex, REG_EXTENDED)) != 0) { + regerror(ret, &greg, buf, sizeof(buf)); + regfree(&greg); + status(50, "Internal server error"); + stop(EXIT_FAILURE, "%s", buf); + } + + if ((ret = regexec(&greg, request, nmatch, match, 0)) != 0) { + regerror(ret, &greg, buf, sizeof(buf)); + regfree(&greg); + status(59, "Malformed request"); + stop(EXIT_FAILURE, "Malformed request, error:%s", buf); + } + + /* one may want to check the return of getsubexp + * and change memcpy to strlcpy + * to make sure we didn't try to copy too long + * and that string isn't trunkated. + * It is unlikely to happen since dest string are as long as request + */ + getsubexp(request, match[1], hostname); + getsubexp(request, match[2], path); + getsubexp(request, match[3], query); + + regfree(&greg); +} diff --git a/vger.h b/vger.h index 0585e4a..7a9f5db 100644 --- a/vger.h +++ b/vger.h @@ -31,6 +31,7 @@ char * get_query(char *, char *, size_t); void status(const int, const char *, ...); void strip_trailing_slash(char *); int uridecode (char *); +void split_request(const char *, char *, char *, char *); void stop(const int, const char *, ...); #endif // vger_h_INCLUDED From 26ca6c422dfe1efb4d1b3dae073562ec45a26966 Mon Sep 17 00:00:00 2001 From: prx Date: Wed, 17 Aug 2022 21:32:06 +0200 Subject: [PATCH 02/21] move regex to vger.h --- vger.c | 15 --------------- vger.h | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/vger.c b/vger.c index 04b3c12..0dad323 100644 --- a/vger.c +++ b/vger.c @@ -514,21 +514,6 @@ split_request(const char *request, char *hostname, char *path, char *query) char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ int ret = 0; - const char *gemini_regex = "^gemini://+([^/|^\?]*)/*([^\?]*)[\?]?(.*)$"; - /* - * ^gemini://+ : in case of gemini:/// - * 1: hostname - * ([^/|^\?]*) : - * catch everything, stop when / or ? is found - * then skip multiple / - * 2: path - * ([^\?]*) : - * catch everything and stop at ? if any - * 3 : query - * [\?]?(.*)$: - * catch everything after ? if any - */ - if ((ret = regcomp(&greg, gemini_regex, REG_EXTENDED)) != 0) { regerror(ret, &greg, buf, sizeof(buf)); regfree(&greg); diff --git a/vger.h b/vger.h index 7a9f5db..9468d73 100644 --- a/vger.h +++ b/vger.h @@ -11,6 +11,22 @@ */ #define GEMINI_REQUEST_MAX 1025 +/* gemini_regex: + * ============= + * ^gemini://+ : in case of gemini:/// + * 1: hostname + * ([^/|^\?]*) : + * catch everything, stop when / or ? is found + * then skip multiple / + * 2: path + * ([^\?]*) : + * catch everything and stop at ? if any + * 3 : query + * [\?]?(.*)$: + * catch everything after ? if any + */ +const char *gemini_regex = "^gemini://+([^/|^\?]*)/*([^\?]*)[\?]?(.*)$"; + /* global vars */ static int _retcode = 0; static ssize_t _datasiz = 0; From 883bfed7a7af3a40864e04c5905828e671e3afbc Mon Sep 17 00:00:00 2001 From: prx Date: Wed, 17 Aug 2022 21:34:37 +0200 Subject: [PATCH 03/21] make tests easier to read --- vger.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/vger.c b/vger.c index 0dad323..293cb38 100644 --- a/vger.c +++ b/vger.c @@ -508,20 +508,22 @@ get_query(char *path, char *query, size_t querysiz) void split_request(const char *request, char *hostname, char *path, char *query) { - regex_t greg = {0}; /* compiled gemini regex */ + regex_t greg = {0}; /* compiled gemini regex */ regmatch_t *match = {0}; /* matches founds */ - size_t nmatch = 4; /* number of substrings to look for */ - char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ - int ret = 0; + size_t nmatch = 4; /* number of substrings to look for */ + char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ + int ret = 0; - if ((ret = regcomp(&greg, gemini_regex, REG_EXTENDED)) != 0) { + ret = regcomp(&greg, gemini_regex, REG_EXTENDED); + if (ret != 0) { regerror(ret, &greg, buf, sizeof(buf)); regfree(&greg); status(50, "Internal server error"); stop(EXIT_FAILURE, "%s", buf); } - if ((ret = regexec(&greg, request, nmatch, match, 0)) != 0) { + ret = regexec(&greg, request, nmatch, match, 0); + if (ret != 0) { regerror(ret, &greg, buf, sizeof(buf)); regfree(&greg); status(59, "Malformed request"); From be0f86df8d74db6aedf530ea029bd15d594adb6d Mon Sep 17 00:00:00 2001 From: prx Date: Wed, 17 Aug 2022 21:36:54 +0200 Subject: [PATCH 04/21] keep globals notation --- vger.c | 2 +- vger.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vger.c b/vger.c index 293cb38..3097ee7 100644 --- a/vger.c +++ b/vger.c @@ -514,7 +514,7 @@ split_request(const char *request, char *hostname, char *path, char *query) char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ int ret = 0; - ret = regcomp(&greg, gemini_regex, REG_EXTENDED); + ret = regcomp(&greg, _gemini_regex, REG_EXTENDED); if (ret != 0) { regerror(ret, &greg, buf, sizeof(buf)); regfree(&greg); diff --git a/vger.h b/vger.h index 9468d73..b130052 100644 --- a/vger.h +++ b/vger.h @@ -25,7 +25,7 @@ * [\?]?(.*)$: * catch everything after ? if any */ -const char *gemini_regex = "^gemini://+([^/|^\?]*)/*([^\?]*)[\?]?(.*)$"; +static const char *_gemini_regex = "^gemini://+([^/|^\?]*)/*([^\?]*)[\?]?(.*)$"; /* global vars */ static int _retcode = 0; From 5063f3e95b92c53c03adbc839fec9424874c2bd2 Mon Sep 17 00:00:00 2001 From: prx Date: Wed, 17 Aug 2022 22:08:16 +0200 Subject: [PATCH 05/21] ensure errors msg are followed by \n, specify in a define the number of matches we need, remove bad structure init --- vger.c | 22 +++++----------------- vger.h | 3 +++ 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/vger.c b/vger.c index 3097ee7..ab14d5e 100644 --- a/vger.c +++ b/vger.c @@ -43,6 +43,7 @@ stop(const int r, const char *fmt, ...) va_start(ap2, fmt); vfprintf(stderr, fmt, ap2); va_end(ap2); + fprintf(stderr, "\n"); } exit(r); @@ -344,8 +345,8 @@ check_request(char *request) */ char *pos = NULL; - /* read 1024 +1 chars from stdin to get the request (1024 + \0) */ + if (fgets(request, GEMINI_REQUEST_MAX, stdin) == NULL) { /* EOF reached before reading anything */ if (feof(stdin)) { @@ -368,22 +369,9 @@ check_request(char *request) /* remove \r\n at the end of string */ request[strcspn(request, "\r\n")] = '\0'; - /* - * check if the beginning of the request starts with - * gemini:// - */ - if (strncmp(request, "gemini://", GEMINI_PART) != 0) { - /* error code url malformed */ - status(59, "request «%s» doesn't match gemini://", request); - stop(EXIT_FAILURE, "request «%s» doesn't match gemini://", request); - } - /* save request for logs */ estrlcpy(_request, request, sizeof(_request)); - /* remove the gemini:// part */ - memmove(request, request + GEMINI_PART, strlen(request) + 1 - GEMINI_PART); - /* remove all "/.." for safety reasons */ while ((pos = strstr(request, "/..")) != NULL) memmove(request, pos + 3, strlen(pos) + 1 - 3); /* "/.." = 3 */ @@ -508,11 +496,11 @@ get_query(char *path, char *query, size_t querysiz) void split_request(const char *request, char *hostname, char *path, char *query) { - regex_t greg = {0}; /* compiled gemini regex */ - regmatch_t *match = {0}; /* matches founds */ - size_t nmatch = 4; /* number of substrings to look for */ + size_t nmatch = SE_MAX; /* 3 "()" + 1 for whole match */ char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ int ret = 0; + regex_t greg; /* compiled gemini regex */ + regmatch_t match[SE_MAX]; /* matches founds */ ret = regcomp(&greg, _gemini_regex, REG_EXTENDED); if (ret != 0) { diff --git a/vger.h b/vger.h index b130052..04b0ade 100644 --- a/vger.h +++ b/vger.h @@ -11,6 +11,9 @@ */ #define GEMINI_REQUEST_MAX 1025 +/* max subexpression in regex : 3 + 1 */ +#define SE_MAX 4 + /* gemini_regex: * ============= * ^gemini://+ : in case of gemini:/// From f388d2a57ad742c872f4d7e368738660b9768292 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 10:53:08 +0200 Subject: [PATCH 06/21] improve regex to handle :1234 in url --- vger.c | 3 +++ vger.h | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/vger.c b/vger.c index ab14d5e..e4b537d 100644 --- a/vger.c +++ b/vger.c @@ -527,6 +527,9 @@ split_request(const char *request, char *hostname, char *path, char *query) getsubexp(request, match[1], hostname); getsubexp(request, match[2], path); getsubexp(request, match[3], query); + syslog(LOG_DAEMON, "hostname:%s", hostname); + syslog(LOG_DAEMON, "path:%s", path); + syslog(LOG_DAEMON, "query:%s", query); regfree(&greg); } diff --git a/vger.h b/vger.h index 04b0ade..3f0f926 100644 --- a/vger.h +++ b/vger.h @@ -18,9 +18,11 @@ * ============= * ^gemini://+ : in case of gemini:/// * 1: hostname - * ([^/|^\?]*) : - * catch everything, stop when / or ? is found - * then skip multiple / + * ([^/|^\?|^:]*) : + * catch everything, stop when /, ? or : is found + * don't catch :port + * [:[0-9]*]? : skip :1234 (port number) if any + * / * : skip "/" if any * 2: path * ([^\?]*) : * catch everything and stop at ? if any @@ -28,7 +30,8 @@ * [\?]?(.*)$: * catch everything after ? if any */ -static const char *_gemini_regex = "^gemini://+([^/|^\?]*)/*([^\?]*)[\?]?(.*)$"; +static const char *_gemini_regex = + "^gemini://+([^/|^\?|^:]*)[:[0-9]*]?/*([^\?]*)[\?]?(.*)$"; /* global vars */ static int _retcode = 0; From 504dd3f759414f37bab8441e0ade16e62c5eabe6 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 10:54:13 +0200 Subject: [PATCH 07/21] rename check_request to read_request --- main.c | 30 +++++++++++++++--------------- vger.c | 2 +- vger.h | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/main.c b/main.c index fae3d9e..366c6e3 100644 --- a/main.c +++ b/main.c @@ -3,16 +3,16 @@ int main(int argc, char **argv) { - char request[GEMINI_REQUEST_MAX] = {'\0'}; - char user[_SC_LOGIN_NAME_MAX] = {'\0'}; - char hostname[GEMINI_REQUEST_MAX] = {'\0'}; - char query[PATH_MAX] = {'\0'}; - char path[PATH_MAX] = {'\0'}; - char chroot_dir[PATH_MAX] = DEFAULT_CHROOT; - char file[FILENAME_MAX] = DEFAULT_INDEX; - char dir[PATH_MAX] = {'\0'}; - int option = 0; - int virtualhost = 0; + char request[GEMINI_REQUEST_MAX] = {'\0'}; + char user[_SC_LOGIN_NAME_MAX] = {'\0'}; + char hostname[GEMINI_REQUEST_MAX] = {'\0'}; + char path[GEMINI_REQUEST_MAX] = {'\0'}; + char query[GEMINI_REQUEST_MAX] = {'\0'}; + char chroot_dir[PATH_MAX] = DEFAULT_CHROOT; + char file[FILENAME_MAX] = DEFAULT_INDEX; + char dir[PATH_MAX] = {'\0'}; + int option = 0; + int virtualhost = 0; /* * request : contain the whole request from client : gemini://...\r\n @@ -21,7 +21,6 @@ main(int argc, char **argv) * query : file requested in cgi : gemini://...?query * file : file basename to display. Emtpy is a directory has been requested * dir : directory requested. vger will chdir() in to find file - * pos : used to parse request and split into interesting parts */ while ((option = getopt(argc, argv, ":d:l:m:u:c:vi")) != -1) { @@ -56,10 +55,11 @@ main(int argc, char **argv) */ drop_privileges(user, chroot_dir, cgi_dir); - check_request(request); - get_hostname(request, hostname, sizeof(hostname)); - get_path(request, path, sizeof(path), virtualhost, hostname); - get_query(path, query, sizeof(query)); + read_request(request); + split_request(request, hostname, path, query); + //get_hostname(request, hostname, sizeof(hostname)); + //get_path(request, path, sizeof(path), virtualhost, hostname); + //get_query(path, query, sizeof(query)); /* percent decode */ uridecode(query); diff --git a/vger.c b/vger.c index e4b537d..778186a 100644 --- a/vger.c +++ b/vger.c @@ -338,7 +338,7 @@ strip_trailing_slash(char *path) } char * -check_request(char *request) +read_request(char *request) { /* * read the request, check for errors and sanitize the input diff --git a/vger.h b/vger.h index 3f0f926..f1b38e3 100644 --- a/vger.h +++ b/vger.h @@ -41,7 +41,7 @@ static char _request[GEMINI_REQUEST_MAX] = {'\0'}; /* functions */ ssize_t autoindex(const char *); void cgi(const char *); -char * check_request(char *); +char * read_request(char *); void check_path(char *, size_t, const char *, int); ssize_t display_file(const char *); int do_cgi(const char *, const char *, const char *, const char *, const char *); From b18f3a3c7b9eb5a7b3b27bf128a5359ecdf22584 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 10:58:38 +0200 Subject: [PATCH 08/21] rename function --- main.c | 2 +- vger.c | 2 +- vger.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 366c6e3..e050577 100644 --- a/main.c +++ b/main.c @@ -76,7 +76,7 @@ main(int argc, char **argv) check_path(path, sizeof(path), hostname, virtualhost); /* split dir and filename */ - get_dir_file(path, dir, sizeof(dir), file, sizeof(file)); + split_dir_file(path, dir, sizeof(dir), file, sizeof(file)); /* go to dir */ echdir(dir); diff --git a/vger.c b/vger.c index 778186a..ff1b68b 100644 --- a/vger.c +++ b/vger.c @@ -464,7 +464,7 @@ check_path(char *path, size_t pathsiz, const char *hstnm, int virtualhost) } void -get_dir_file(char *path, char *dir, size_t dirsiz, char *file, size_t filesiz) +split_dir_file(char *path, char *dir, size_t dirsiz, char *file, size_t filesiz) { char *pos = NULL; diff --git a/vger.h b/vger.h index f1b38e3..0586268 100644 --- a/vger.h +++ b/vger.h @@ -46,7 +46,7 @@ void check_path(char *, size_t, const char *, int); ssize_t display_file(const char *); int do_cgi(const char *, const char *, const char *, const char *, const char *); void drop_privileges(const char *, const char *, const char *); -void get_dir_file(char *, char *, size_t, char *, size_t); +void split_dir_file(char *, char *, size_t, char *, size_t); char * get_hostname(const char *, char *, size_t); char * get_path(const char *, char *, size_t, int, const char *); char * get_query(char *, char *, size_t); From e2567fcf01954cd4dc2ed5555e3b5f7d8782115a Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 11:05:21 +0200 Subject: [PATCH 09/21] modify function to set path according to virtualhost --- main.c | 2 +- vger.c | 18 ++++++------------ vger.h | 2 +- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/main.c b/main.c index e050577..d0d75c4 100644 --- a/main.c +++ b/main.c @@ -58,7 +58,7 @@ main(int argc, char **argv) read_request(request); split_request(request, hostname, path, query); //get_hostname(request, hostname, sizeof(hostname)); - //get_path(request, path, sizeof(path), virtualhost, hostname); + set_path(request, path, sizeof(path), virtualhost, hostname); //get_query(path, query, sizeof(query)); /* percent decode */ diff --git a/vger.c b/vger.c index ff1b68b..db90f71 100644 --- a/vger.c +++ b/vger.c @@ -399,24 +399,18 @@ get_hostname(const char *request, char *hstnm, size_t hstnmsiz) } char * -get_path(const char *request, char *path, size_t pathsiz, int virtualhost, const char *hostname) +set_path(const char *request, char *path, size_t pathsiz, int virtualhost, const char *hostname) { - char *pos = NULL; - - /* path must be relative to chroot */ - estrlcpy(path, "./", pathsiz); + char tmp[GEMINI_REQUEST_MAX] = {'\0'}; /* path is in a subdir named hostname */ if (virtualhost) { - estrlcat(path, hostname, pathsiz); - estrlcat(path, "/", pathsiz); + estrlcpy(tmp, hostname, sizeof(tmp)); + estrlcat(tmp, "/", sizeof(tmp)); + estrlcat(tmp, path, sizeof(tmp)); + estrlcpy(path, tmp, pathsiz); } - /* path is after hostname/ */ - pos = strchr(request, '/'); - if (pos != NULL) /* append the path. pos +1 to remove leading '/' */ - estrlcat(path, pos+1, pathsiz); - return path; } diff --git a/vger.h b/vger.h index 0586268..97823e4 100644 --- a/vger.h +++ b/vger.h @@ -48,7 +48,7 @@ int do_cgi(const char *, const char *, const char *, const char *, const char * void drop_privileges(const char *, const char *, const char *); void split_dir_file(char *, char *, size_t, char *, size_t); char * get_hostname(const char *, char *, size_t); -char * get_path(const char *, char *, size_t, int, const char *); +char * set_path(const char *, char *, size_t, int, const char *); char * get_query(char *, char *, size_t); void status(const int, const char *, ...); void strip_trailing_slash(char *); From f8d215869d2cea649060740326d9eea302663bff Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 11:05:56 +0200 Subject: [PATCH 10/21] remove unused function --- main.c | 1 - vger.c | 19 ------------------- vger.h | 3 +-- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/main.c b/main.c index d0d75c4..6beb886 100644 --- a/main.c +++ b/main.c @@ -57,7 +57,6 @@ main(int argc, char **argv) read_request(request); split_request(request, hostname, path, query); - //get_hostname(request, hostname, sizeof(hostname)); set_path(request, path, sizeof(path), virtualhost, hostname); //get_query(path, query, sizeof(query)); diff --git a/vger.c b/vger.c index db90f71..5cfc8b1 100644 --- a/vger.c +++ b/vger.c @@ -379,25 +379,6 @@ read_request(char *request) return request; } -char * -get_hostname(const char *request, char *hstnm, size_t hstnmsiz) -{ - char *pos = NULL; - - /* first make a copy of request */ - estrlcpy(hstnm, request, hstnmsiz); - - /* look for hostname : stops at first '/' if any */ - if ( (pos = strchr(hstnm, '/')) != NULL) - pos[0] = '\0'; /* end string at the end of hostname */ - - /* check if client added :port at end of hostname and remove it */ - if ( (pos = strchr(hstnm, ':')) != NULL) - pos[0] = '\0'; /* end string at : */ - - return hstnm; -} - char * set_path(const char *request, char *path, size_t pathsiz, int virtualhost, const char *hostname) { diff --git a/vger.h b/vger.h index 97823e4..4741d1a 100644 --- a/vger.h +++ b/vger.h @@ -47,9 +47,8 @@ ssize_t display_file(const char *); int do_cgi(const char *, const char *, const char *, const char *, const char *); void drop_privileges(const char *, const char *, const char *); void split_dir_file(char *, char *, size_t, char *, size_t); -char * get_hostname(const char *, char *, size_t); -char * set_path(const char *, char *, size_t, int, const char *); char * get_query(char *, char *, size_t); +char * set_path(const char *, char *, size_t, int, const char *); void status(const int, const char *, ...); void strip_trailing_slash(char *); int uridecode (char *); From e3932483ef4a29f72d58056cf607dd0970b24056 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 11:06:37 +0200 Subject: [PATCH 11/21] remove unused parameter --- main.c | 2 +- vger.c | 2 +- vger.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 6beb886..de26cef 100644 --- a/main.c +++ b/main.c @@ -57,7 +57,7 @@ main(int argc, char **argv) read_request(request); split_request(request, hostname, path, query); - set_path(request, path, sizeof(path), virtualhost, hostname); + set_path(path, sizeof(path), virtualhost, hostname); //get_query(path, query, sizeof(query)); /* percent decode */ diff --git a/vger.c b/vger.c index 5cfc8b1..0142091 100644 --- a/vger.c +++ b/vger.c @@ -380,7 +380,7 @@ read_request(char *request) } char * -set_path(const char *request, char *path, size_t pathsiz, int virtualhost, const char *hostname) +set_path(char *path, size_t pathsiz, int virtualhost, const char *hostname) { char tmp[GEMINI_REQUEST_MAX] = {'\0'}; diff --git a/vger.h b/vger.h index 4741d1a..c9e79bc 100644 --- a/vger.h +++ b/vger.h @@ -48,7 +48,7 @@ int do_cgi(const char *, const char *, const char *, const char *, const char * void drop_privileges(const char *, const char *, const char *); void split_dir_file(char *, char *, size_t, char *, size_t); char * get_query(char *, char *, size_t); -char * set_path(const char *, char *, size_t, int, const char *); +char * set_path(char *, size_t, int, const char *); void status(const int, const char *, ...); void strip_trailing_slash(char *); int uridecode (char *); From 27549119efcb50da8aa918ee07310f3a805b50ea Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 13:59:54 +0200 Subject: [PATCH 12/21] simplify and fix redirections after regex --- main.c | 9 +++++++-- vger.c | 24 ++++++++++-------------- vger.h | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/main.c b/main.c index de26cef..fb2dc0b 100644 --- a/main.c +++ b/main.c @@ -58,6 +58,7 @@ main(int argc, char **argv) read_request(request); split_request(request, hostname, path, query); set_path(path, sizeof(path), virtualhost, hostname); + //get_query(path, query, sizeof(query)); /* percent decode */ @@ -69,16 +70,20 @@ main(int argc, char **argv) if (do_cgi(chroot_dir, cgi_dir, path, hostname, query) == 0) stop(EXIT_SUCCESS, NULL); + syslog(LOG_DAEMON, "path:%s", path); /* *** from here, cgi didn't run *** * check if path available */ - check_path(path, sizeof(path), hostname, virtualhost); + check_path(path, sizeof(path), virtualhost, strlen(hostname)); /* split dir and filename */ split_dir_file(path, dir, sizeof(dir), file, sizeof(file)); + syslog(LOG_DAEMON, "dir:%s", dir); + syslog(LOG_DAEMON, "file:%s", file); /* go to dir */ - echdir(dir); + if (*dir) + echdir(dir); /* regular file to stdout */ display_file(file); diff --git a/vger.c b/vger.c index 0142091..79a842c 100644 --- a/vger.c +++ b/vger.c @@ -384,6 +384,9 @@ set_path(char *path, size_t pathsiz, int virtualhost, const char *hostname) { char tmp[GEMINI_REQUEST_MAX] = {'\0'}; + if (strlen(path) == 0) /* this is root dir */ + estrlcpy(path, "./", pathsiz); + /* path is in a subdir named hostname */ if (virtualhost) { estrlcpy(tmp, hostname, sizeof(tmp)); @@ -396,7 +399,7 @@ set_path(char *path, size_t pathsiz, int virtualhost, const char *hostname) } void -check_path(char *path, size_t pathsiz, const char *hstnm, int virtualhost) +check_path(char *path, size_t pathsiz, int virtualhost, size_t hstnm_o) { struct stat sb = {0}; char tmp[PATH_MAX] = {'\0'}; @@ -416,17 +419,13 @@ check_path(char *path, size_t pathsiz, const char *hstnm, int virtualhost) /* check if dir path end with "/" */ if (path[strlen(path) - 1] != '/') { /* redirect to the dir with appropriate ending '/' */ - - /* remove leading '.' for redirection*/ - if (virtualhost) /* remove ./host.name */ - memmove(path, path+2+strlen(hstnm), - strlen(path + 2) + strlen(hstnm) + 1); + estrlcpy(tmp, "/", sizeof(tmp)); + if (virtualhost) /* skip hostname */ + estrlcat(tmp, path+hstnm_o+1, sizeof(tmp)); else - memmove(path, path+1, - strlen(path + 1) + 1); /* +1 for \0 */ - - estrlcat(path, "/", pathsiz); - status(31, "%s", path); + estrlcat(tmp, path, sizeof(tmp)); + estrlcat(tmp, "/", sizeof(tmp)); + status(31, "%s", tmp); stop(EXIT_SUCCESS, NULL); } /* check if DEFAULT_INDEX exists in directory */ @@ -502,9 +501,6 @@ split_request(const char *request, char *hostname, char *path, char *query) getsubexp(request, match[1], hostname); getsubexp(request, match[2], path); getsubexp(request, match[3], query); - syslog(LOG_DAEMON, "hostname:%s", hostname); - syslog(LOG_DAEMON, "path:%s", path); - syslog(LOG_DAEMON, "query:%s", query); regfree(&greg); } diff --git a/vger.h b/vger.h index c9e79bc..b9d71c0 100644 --- a/vger.h +++ b/vger.h @@ -42,7 +42,7 @@ static char _request[GEMINI_REQUEST_MAX] = {'\0'}; ssize_t autoindex(const char *); void cgi(const char *); char * read_request(char *); -void check_path(char *, size_t, const char *, int); +void check_path(char *, size_t, int, size_t); ssize_t display_file(const char *); int do_cgi(const char *, const char *, const char *, const char *, const char *); void drop_privileges(const char *, const char *, const char *); From 63616a97fc58d7e9a42b6b5cda791aaef096a191 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:00:51 +0200 Subject: [PATCH 13/21] remove unused function --- main.c | 2 -- vger.c | 15 --------------- vger.h | 1 - 3 files changed, 18 deletions(-) diff --git a/main.c b/main.c index fb2dc0b..1ba03ee 100644 --- a/main.c +++ b/main.c @@ -59,8 +59,6 @@ main(int argc, char **argv) split_request(request, hostname, path, query); set_path(path, sizeof(path), virtualhost, hostname); - //get_query(path, query, sizeof(query)); - /* percent decode */ uridecode(query); uridecode(path); diff --git a/vger.c b/vger.c index 79a842c..1fe1a8c 100644 --- a/vger.c +++ b/vger.c @@ -452,21 +452,6 @@ split_dir_file(char *path, char *dir, size_t dirsiz, char *file, size_t filesiz) } } -char * -get_query(char *path, char *query, size_t querysiz) -{ - char *pos = NULL; - - /* remove a query string before percent decoding */ - /* look for "?" if any to set query for cgi, remove it */ - pos = strchr(path, '?'); - if (pos != NULL) { - estrlcpy(query, pos + 1, querysiz); - pos[0] = '\0'; /* path end where query begins */ - } - return query; -} - void split_request(const char *request, char *hostname, char *path, char *query) { diff --git a/vger.h b/vger.h index b9d71c0..ed3b6eb 100644 --- a/vger.h +++ b/vger.h @@ -47,7 +47,6 @@ ssize_t display_file(const char *); int do_cgi(const char *, const char *, const char *, const char *, const char *); void drop_privileges(const char *, const char *, const char *); void split_dir_file(char *, char *, size_t, char *, size_t); -char * get_query(char *, char *, size_t); char * set_path(char *, size_t, int, const char *); void status(const int, const char *, ...); void strip_trailing_slash(char *); From 5cb310dd1bd9a1c1bce45a40912c1243379d648b Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:01:12 +0200 Subject: [PATCH 14/21] test no longer required since path can't be empty with set_path --- main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.c b/main.c index 1ba03ee..34a7d70 100644 --- a/main.c +++ b/main.c @@ -80,8 +80,7 @@ main(int argc, char **argv) syslog(LOG_DAEMON, "file:%s", file); /* go to dir */ - if (*dir) - echdir(dir); + echdir(dir); /* regular file to stdout */ display_file(file); From 34667eb018bc6616677f6e61d2ebe03e447e573e Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:02:45 +0200 Subject: [PATCH 15/21] Revert "test no longer required since path can't be empty with set_path" This reverts commit 5cb310dd1bd9a1c1bce45a40912c1243379d648b. --- main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 34a7d70..1ba03ee 100644 --- a/main.c +++ b/main.c @@ -80,7 +80,8 @@ main(int argc, char **argv) syslog(LOG_DAEMON, "file:%s", file); /* go to dir */ - echdir(dir); + if (*dir) + echdir(dir); /* regular file to stdout */ display_file(file); From fc5c2a1b41bb7ab7a5813302371a2af000ff3dcc Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:12:38 +0200 Subject: [PATCH 16/21] fix cgi and simplify now we use regex --- main.c | 8 ++------ vger.c | 7 +++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/main.c b/main.c index 1ba03ee..4cde739 100644 --- a/main.c +++ b/main.c @@ -67,17 +67,13 @@ main(int argc, char **argv) if (*cgi_dir) if (do_cgi(chroot_dir, cgi_dir, path, hostname, query) == 0) stop(EXIT_SUCCESS, NULL); + /* *** from here, cgi didn't run *** */ - syslog(LOG_DAEMON, "path:%s", path); - /* *** from here, cgi didn't run *** - * check if path available - */ + /* check if path available */ check_path(path, sizeof(path), virtualhost, strlen(hostname)); /* split dir and filename */ split_dir_file(path, dir, sizeof(dir), file, sizeof(file)); - syslog(LOG_DAEMON, "dir:%s", dir); - syslog(LOG_DAEMON, "file:%s", file); /* go to dir */ if (*dir) diff --git a/vger.c b/vger.c index 1fe1a8c..f942c86 100644 --- a/vger.c +++ b/vger.c @@ -220,7 +220,6 @@ do_cgi(const char *chroot_dir, const char *cgi_dir, const char *path, const char /* check if path starts with cgi_dir * compare beginning of path with cgi_dir - * path + 2 : skip "./" * cgi_dir + strlen(chrootdir) (skip chrootdir) */ @@ -229,7 +228,7 @@ do_cgi(const char *chroot_dir, const char *cgi_dir, const char *path, const char while (*cgirp == '/') estrlcpy(cgirp, cgirp+1, sizeof(cgirp)); - if (strncmp(cgirp, path+2, strlen(cgirp)) != 0) + if (strncmp(cgirp, path, strlen(cgirp)) != 0) return 1; /* not in cgi_dir, go to display_file */ /* set env variables for CGI @@ -250,11 +249,11 @@ do_cgi(const char *chroot_dir, const char *cgi_dir, const char *path, const char */ /* find next item after cgi_dir in path: - * path + 2 (skip "./") + strlen(cgirp) + 1 (skip '/') + * path + strlen(cgirp) + 1 (skip '/') */ /* cgi file to execute */ - estrlcpy(cgifp, path + 2 + strlen(cgirp) + 1, sizeof(cgifp)); + estrlcpy(cgifp, path + strlen(cgirp) + 1, sizeof(cgifp)); if (!(*cgifp)) /* problem with cgi file, abort */ return 1; From b1f92f7c9c4cac78bae7871609a5803d352ca4c2 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:27:52 +0200 Subject: [PATCH 17/21] fix indent --- vger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vger.c b/vger.c index f942c86..1d572fe 100644 --- a/vger.c +++ b/vger.c @@ -454,7 +454,7 @@ split_dir_file(char *path, char *dir, size_t dirsiz, char *file, size_t filesiz) void split_request(const char *request, char *hostname, char *path, char *query) { - size_t nmatch = SE_MAX; /* 3 "()" + 1 for whole match */ + size_t nmatch = SE_MAX; /* 3 "()" + 1 for whole match */ char buf[BUFSIZ] = {'\0'}; /* to handle error messages */ int ret = 0; regex_t greg; /* compiled gemini regex */ From 45e5ae32fa691938992f1c62fb0b284abbbd3675 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:32:19 +0200 Subject: [PATCH 18/21] useless line --- vger.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vger.c b/vger.c index 1d572fe..2bdacdd 100644 --- a/vger.c +++ b/vger.c @@ -43,9 +43,8 @@ stop(const int r, const char *fmt, ...) va_start(ap2, fmt); vfprintf(stderr, fmt, ap2); va_end(ap2); - fprintf(stderr, "\n"); - } + } exit(r); } From 75bfaee73e2fd3bd4d83c54bf21ee754d36ba522 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 14:34:04 +0200 Subject: [PATCH 19/21] remove useless function && reorder declarations --- vger.c | 11 ----------- vger.h | 7 +++---- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/vger.c b/vger.c index 2bdacdd..018549e 100644 --- a/vger.c +++ b/vger.c @@ -324,17 +324,6 @@ cgi(const char *cgicmd) } -void -strip_trailing_slash(char *path) -{ - size_t end = strlen(path); - if (end == 0) - return; - end--; - while (path[end] == '/') - path[end--] = '\0'; -} - char * read_request(char *request) { diff --git a/vger.h b/vger.h index ed3b6eb..e86b85d 100644 --- a/vger.h +++ b/vger.h @@ -46,13 +46,12 @@ void check_path(char *, size_t, int, size_t); ssize_t display_file(const char *); int do_cgi(const char *, const char *, const char *, const char *, const char *); void drop_privileges(const char *, const char *, const char *); -void split_dir_file(char *, char *, size_t, char *, size_t); char * set_path(char *, size_t, int, const char *); -void status(const int, const char *, ...); -void strip_trailing_slash(char *); -int uridecode (char *); void split_request(const char *, char *, char *, char *); +void split_dir_file(char *, char *, size_t, char *, size_t); +void status(const int, const char *, ...); void stop(const int, const char *, ...); +int uridecode (char *); #endif // vger_h_INCLUDED From 875f167eb922d8457fe7e2d47ffe7af14f463aa8 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 15:27:44 +0200 Subject: [PATCH 20/21] skip useless test --- utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.c b/utils.c index 740f545..89bc991 100644 --- a/utils.c +++ b/utils.c @@ -124,7 +124,7 @@ getsubexp(const char *str, regmatch_t m, char *dst) { size_t len = 0; - if (m.rm_eo > m.rm_so) { /* skip empty substring */ + if ((len = m.rm_eo - m.rm_so) > 0) { /* skip empty substring */ len = m.rm_eo - m.rm_so; memcpy(dst, str + m.rm_so, len); dst[len] = '\0'; From 9d23a48ae2896e1417fafe04fe315c92db09bb63 Mon Sep 17 00:00:00 2001 From: prx Date: Thu, 18 Aug 2022 22:23:59 +0200 Subject: [PATCH 21/21] remove useless functions --- main.c | 15 ++------------- vger.c | 27 ++++++--------------------- vger.h | 1 - 3 files changed, 8 insertions(+), 35 deletions(-) diff --git a/main.c b/main.c index 4cde739..e9c7b92 100644 --- a/main.c +++ b/main.c @@ -9,8 +9,6 @@ main(int argc, char **argv) char path[GEMINI_REQUEST_MAX] = {'\0'}; char query[GEMINI_REQUEST_MAX] = {'\0'}; char chroot_dir[PATH_MAX] = DEFAULT_CHROOT; - char file[FILENAME_MAX] = DEFAULT_INDEX; - char dir[PATH_MAX] = {'\0'}; int option = 0; int virtualhost = 0; @@ -18,9 +16,7 @@ main(int argc, char **argv) * request : contain the whole request from client : gemini://...\r\n * user : username, used in drop_privileges() * hostname : extracted from hostname. used with virtualhosts and cgi SERVER_NAME - * query : file requested in cgi : gemini://...?query - * file : file basename to display. Emtpy is a directory has been requested - * dir : directory requested. vger will chdir() in to find file + * query : after a ? in cgi : gemini://...?query */ while ((option = getopt(argc, argv, ":d:l:m:u:c:vi")) != -1) { @@ -72,15 +68,8 @@ main(int argc, char **argv) /* check if path available */ check_path(path, sizeof(path), virtualhost, strlen(hostname)); - /* split dir and filename */ - split_dir_file(path, dir, sizeof(dir), file, sizeof(file)); - - /* go to dir */ - if (*dir) - echdir(dir); - /* regular file to stdout */ - display_file(file); + display_file(path); stop(EXIT_SUCCESS, NULL); } diff --git a/vger.c b/vger.c index 018549e..f4e0b97 100644 --- a/vger.c +++ b/vger.c @@ -168,23 +168,23 @@ drop_privileges(const char *user, const char *chroot_dir, const char *cgi_dir) } ssize_t -display_file(const char *fname) +display_file(const char *path) { FILE *fd = NULL; const char *file_mime; /* - * special case : fname empty. The user requested just a dir name + * special case : path ends with "/". The user requested a dir */ - if ((strlen(fname) == 0) && (doautoidx)) { + if ((path[strlen(path)-1] == '/') && (doautoidx)) { /* no index.gmi, so display autoindex if enabled */ - _datasiz += autoindex("."); + _datasiz += autoindex(path); return _datasiz; } /* open the file requested */ - if ((fd = fopen(fname, "r")) != NULL) { - file_mime = get_file_mime(fname, default_mime); + if ((fd = fopen(path, "r")) != NULL) { + file_mime = get_file_mime(path, default_mime); if (strcmp(file_mime, "text/gemini") == 0) status(20, "%s; %s", file_mime, lang); else @@ -424,21 +424,6 @@ check_path(char *path, size_t pathsiz, int virtualhost, size_t hstnm_o) } } -void -split_dir_file(char *path, char *dir, size_t dirsiz, char *file, size_t filesiz) -{ - char *pos = NULL; - - pos = strrchr(path, '/'); - if (pos != NULL) { - estrlcpy(file, pos+1, filesiz); /* +1 : not heading / */ - pos[0] = '\0'; /* stop path at file */ - estrlcpy(dir, path, dirsiz); - } else { - estrlcpy(file, path, filesiz); - } -} - void split_request(const char *request, char *hostname, char *path, char *query) { diff --git a/vger.h b/vger.h index e86b85d..8246f1f 100644 --- a/vger.h +++ b/vger.h @@ -48,7 +48,6 @@ int do_cgi(const char *, const char *, const char *, const char *, const char * void drop_privileges(const char *, const char *, const char *); char * set_path(char *, size_t, int, const char *); void split_request(const char *, char *, char *, char *); -void split_dir_file(char *, char *, size_t, char *, size_t); void status(const int, const char *, ...); void stop(const int, const char *, ...); int uridecode (char *);