summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2021-09-25 18:33:40 -0400
committerJune McEnroe <june@causal.agency>2021-09-25 18:40:39 -0400
commiteafe6df2d4b1619afee2564a945742f9bc333de8 (patch)
tree6083e637dedeb80f482afc9878e4c85ca8b01ea4
parentSet SO_REUSEADDR in quick (diff)
downloadsrc-eafe6df2d4b1619afee2564a945742f9bc333de8.tar.gz
src-eafe6df2d4b1619afee2564a945742f9bc333de8.zip
Sandbox up on both FreeBSD and OpenBSD
This is a bit messy. pledge(2) calls based on [1].

[1]: https://kristaps.bsd.lv/kcgi/tutorial6.html
Diffstat (limited to '')
-rw-r--r--www/temp.causal.agency/up.c102
1 files changed, 68 insertions, 34 deletions
diff --git a/www/temp.causal.agency/up.c b/www/temp.causal.agency/up.c
index 999e4958..9fca922a 100644
--- a/www/temp.causal.agency/up.c
+++ b/www/temp.causal.agency/up.c
@@ -33,8 +33,9 @@
 #include <kcgi.h>
 #include <kcgihtml.h>
 
-static int cwd = -1;
+static int dir = -1;
 
+static const char *Page = "up";
 static const struct kvalid Key = { NULL, "file" };
 
 static enum kcgi_err head(struct kreq *req, enum khttp http, enum kmime mime) {
@@ -55,7 +56,7 @@ static const char *upload(const char *ext, void *ptr, size_t len) {
 		(intmax_t)time(NULL), arc4random(),
 		(ext && ext[0] != '.' ? "." : ""), (ext ? ext : "")
 	);
-	int fd = openat(cwd, name, O_CREAT | O_EXCL | O_WRONLY, 0644);
+	int fd = openat(dir, name, O_CREAT | O_EXCL | O_WRONLY, 0644);
 	if (fd < 0) {
 		warn("%s", name);
 		return NULL;
@@ -136,47 +137,80 @@ static enum kcgi_err handle(struct kreq *req) {
 	}
 }
 
-static void sandbox(void) {
-	cwd = open(".", O_DIRECTORY);
-	if (cwd < 0) err(EX_CONFIG, ".");
+static void cgi(void) {
+#ifdef __OpenBSD__
+	if (pledge("stdio wpath cpath proc", NULL)) err(EX_OSERR, "pledge");
+#endif
+
+	struct kreq req;
+	enum kcgi_err error = khttp_parse(&req, &Key, 1, &Page, 1, 0);
+	if (error) errx(EX_PROTOCOL, "khttp_parse: %s", kcgi_strerror(error));
+
+#ifdef __OpenBSD__
+	if (pledge("stdio wpath cpath", NULL)) err(EX_OSERR, "pledge");
+#endif
+#ifdef __FreeBSD__
+	if (cap_enter()) err(EX_OSERR, "cap_enter");
+#endif
+
+	error = handle(&req);
+	if (error) errx(EX_PROTOCOL, "%s", kcgi_strerror(error));
+	khttp_free(&req);
+}
+
+static void fcgi(void) {
+#ifdef __OpenBSD__
+	if (pledge("stdio wpath cpath unix sendfd recvfd proc", NULL)) {
+		err(EX_OSERR, "pledge");
+	}
+#endif
 
+	struct kfcgi *fcgi;
+	enum kcgi_err error = khttp_fcgi_init(&fcgi, &Key, 1, &Page, 1, 0);
+	if (error) errx(EX_CONFIG, "khttp_fcgi_init: %s", kcgi_strerror(error));
+
+#ifdef __OpenBSD__
+	if (pledge("stdio wpath cpath recvfd", NULL)) err(EX_OSERR, "pledge");
+#endif
 #ifdef __FreeBSD__
-	int error = cap_enter();
-	if (error) err(EX_OSERR, "cap_enter");
+	if (cap_enter()) err(EX_OSERR, "cap_enter");
+#endif
 
+	for (
+		struct kreq req;
+		KCGI_OK == (error = khttp_fcgi_parse(fcgi, &req));
+		khttp_free(&req)
+	) {
+		error = handle(&req);
+		if (error && error != KCGI_HUP) break;
+	}
+	if (error != KCGI_EXIT) {
+		errx(EX_PROTOCOL, "khttp_fcgi_parse: %s", kcgi_strerror(error));
+	}
+	khttp_fcgi_free(fcgi);
+}
+
+int main(int argc, char *argv[]) {
+	int error;
+	const char *path = (argc > 1 ? argv[1] : ".");
+	dir = open(path, O_DIRECTORY);
+	if (dir < 0) err(EX_NOINPUT, "%s", path);
+
+#ifdef __OpenBSD__
+	error = unveil(path, "wc");
+	if (error) err(EX_OSERR, "unveil");
+#endif
+
+#ifdef __FreeBSD__
 	cap_rights_t rights;
 	cap_rights_init(&rights, CAP_LOOKUP, CAP_CREATE, CAP_PWRITE);
-	error = cap_rights_limit(cwd, &rights);
+	error = cap_rights_limit(dir, &rights);
 	if (error) err(EX_OSERR, "cap_rights_limit");
 #endif
-}
 
-int main(void) {
-	const char *page = "up";
 	if (khttp_fcgi_test()) {
-		struct kfcgi *fcgi;
-		enum kcgi_err error = khttp_fcgi_init(&fcgi, &Key, 1, &page, 1, 0);
-		if (error) errx(EX_CONFIG, "khttp_fcgi_init: %s", kcgi_strerror(error));
-		sandbox();
-		for (
-			struct kreq req;
-			KCGI_OK == (error = khttp_fcgi_parse(fcgi, &req));
-			khttp_free(&req)
-		) {
-			error = handle(&req);
-			if (error && error != KCGI_HUP) break;
-		}
-		if (error != KCGI_EXIT) {
-			errx(EX_PROTOCOL, "khttp_fcgi_parse: %s", kcgi_strerror(error));
-		}
-		khttp_fcgi_free(fcgi);
+		fcgi();
 	} else {
-		struct kreq req;
-		enum kcgi_err error = khttp_parse(&req, &Key, 1, &page, 1, 0);
-		if (error) errx(EX_PROTOCOL, "khttp_parse: %s", kcgi_strerror(error));
-		sandbox();
-		error = handle(&req);
-		if (error) errx(EX_PROTOCOL, "%s", kcgi_strerror(error));
-		khttp_free(&req);
+		cgi();
 	}
 }