aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2020-11-06 18:05:44 +0100
committerOmar Polo <op@omarpolo.com>2020-11-06 18:05:44 +0100
commit72f653b65247a296f1be344f3c6c1ad981b9fbcf (patch)
tree08b7d05ed20a3a2b7466b6fabb54f2e619fba4a9
parentf65ed01841f4603f861bed55224227501f56372b (diff)
[cgi] execute cgi scripts only inside a specific directory
change the meaning of the -x flag: now it takes a string and executes CGI scripts only if they are inside a directory with the given name, relatively to the document root.
-rw-r--r--gmid.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/gmid.c b/gmid.c
index a5d4310..133f513 100644
--- a/gmid.c
+++ b/gmid.c
@@ -107,12 +107,12 @@ struct etm { /* file extension to mime */
dprintf(logfd, "[%s] " fmt "\n", buf, __VA_ARGS__); \
} while (0)
-const char *dir;
+const char *dir, *cgi;
int dirfd, logfd;
-int cgi;
int connected_clients;
void siginfo_handler(int);
+int starts_with(const char*, const char*);
char *url_after_proto(char*);
char *url_start_of_request(char*);
@@ -147,13 +147,23 @@ siginfo_handler(int sig)
(void)sig;
}
+int
+starts_with(const char *str, const char *prefix)
+{
+ size_t i;
+
+ for (i = 0; prefix[i] != '\0'; ++i)
+ if (str[i] != prefix[i])
+ return 0;
+ return 1;
+}
+
char *
url_after_proto(char *url)
{
char *s;
const char *proto = "gemini";
const char *marker = "://";
- size_t i;
/* a relative URL */
if ((s = strstr(url, marker)) == NULL)
@@ -162,9 +172,8 @@ url_after_proto(char *url)
if (s - strlen(proto) != url)
return NULL;
- for (i = 0; proto[i] != '\0'; ++i)
- if (url[i] != proto[i])
- return NULL;
+ if (!starts_with(url, proto))
+ return NULL;
/* a valid gemini:// URL */
return s + strlen(marker);
@@ -353,7 +362,8 @@ open_file(char *path, char *query, struct pollfd *fds, struct client *c)
return 0;
}
- if (cgi && (sb.st_mode & S_IXUSR)) {
+ /* +2 to skip the ./ */
+ if ((sb.st_mode & S_IXUSR) && cgi != NULL && starts_with(fpath+2, cgi)) {
start_cgi(fpath, query, fds, c);
return 0;
}
@@ -868,7 +878,8 @@ void
usage(const char *me)
{
fprintf(stderr,
- "USAGE: %s [-h] [-c cert.pem] [-d docs] [-k key.pem]\n",
+ "USAGE: %s [-h] [-c cert.pem] [-d docs] [-k key.pem] "
+ "[-l logfile] [-x cgi-bin]\n",
me);
}
@@ -892,9 +903,9 @@ main(int argc, char **argv)
dir = "docs/";
logfd = 2; /* stderr */
- cgi = 0;
+ cgi = NULL;
- while ((ch = getopt(argc, argv, "c:d:hk:l:x")) != -1) {
+ while ((ch = getopt(argc, argv, "c:d:hk:l:x:")) != -1) {
switch (ch) {
case 'c':
cert = optarg;
@@ -920,7 +931,7 @@ main(int argc, char **argv)
break;
case 'x':
- cgi = 1;
+ cgi = optarg;
break;
default:
@@ -953,11 +964,17 @@ main(int argc, char **argv)
if ((dirfd = open(dir, O_RDONLY | O_DIRECTORY)) == -1)
err(1, "open: %s", dir);
- if (unveil(dir, cgi ? "rx" : "r") == -1)
- err(1, "unveil");
-
- if (pledge(cgi ? "stdio rpath inet proc exec" : "stdio rpath inet", NULL) == -1)
- err(1, "pledge");
+ if (cgi != NULL) {
+ if (unveil(dir, "rx") == -1)
+ err(1, "unveil");
+ if (pledge("stdio rpath inet proc exec", NULL) == -1)
+ err(1, "pledge");
+ } else {
+ if (unveil(dir, "r") == -1)
+ err(1, "unveil");
+ if (pledge("stdio rpath inet", NULL) == -1)
+ err(1, "pledge");
+ }
loop(ctx, sock);