Commit Diff


commit - 4ad11931ec10c823e98b7c51efc7146d8cbdd012
commit + dafb57b8af432d800219a8e17900e1ac56a65c14
blob - ee5c0662119a47cadbcb2c1b4bd115adb46c1193
blob + b9949935dc6c07b20654aa87496522be783af260
--- ChangeLog
+++ ChangeLog
@@ -1,5 +1,7 @@
 2021-01-15  Omar Polo  <op@omarpolo.com>
 
+	* sandbox.c (sandbox): sandbox on OpenBSD (pledge/unveil, as before) and on FreeBSD (capsicum) too
+
 	* sample.conf: added sample configuration
 
 	* gmid.c (main): changed behaviour: daemon off by default
blob - fe3b4ced6eb113cf1d47fa27bd1920da55b6cf96
blob + c405482cf0cc1dd816e22b43ccec4bd381107688
--- Makefile
+++ Makefile
@@ -14,8 +14,9 @@ lex.yy.c: lex.l y.tab.c
 y.tab.c: parse.y
 	${YACC} -b y -d parse.y
 
-gmid: gmid.o iri.o utf8.o lex.yy.o y.tab.o
-	${CC} gmid.o iri.o utf8.o lex.yy.o y.tab.o -o gmid ${LDFLAGS}
+OBJS = gmid.o iri.o utf8.o lex.yy.o y.tab.o sandbox.o
+gmid: ${OBJS}
+	${CC} ${OBJS} -o gmid ${LDFLAGS}
 
 TAGS: gmid.c iri.c utf8.c
 	-etags gmid.c iri.c utf8.c || true
blob - b9dd29ed5da687c5e075789df19e2ed515ec0090
blob + 658208fced0275052cc1b87f657a2d5675ea3f37
--- README.md
+++ README.md
@@ -22,6 +22,7 @@ CGI scripts are enabled, while the given directory is 
  - (very) low memory footprint
  - small codebase, easily hackable
  - virtual hosts
+ - sandboxed on OpenBSD and FreeBSD
 
 
 ## Drawbacks
@@ -30,7 +31,10 @@ CGI scripts are enabled, while the given directory is 
    connection per-second you'd probably want to run multiple gmid
    instances behind relayd/haproxy or a different server.
 
+ - the sandbox on FreeBSD is **NOT** activated if CGI scripts are
+   enabled: CGI script cannot be used with the way `capsicum(4)` works
 
+
 ## Building
 
 gmid depends a POSIX libc and libtls.  It can probably be linked
blob - f69df77c026fc133d482b361d15021f2a7a1304a
blob + 6eed3f6f0eebe59619b009011f4be30440c13ee7
--- gmid.c
+++ gmid.c
@@ -29,11 +29,6 @@
 
 #include "gmid.h"
 
-#define LOGE(c, fmt, ...) logs(LOG_ERR,    c, fmt, __VA_ARGS__)
-#define LOGN(c, fmt, ...) logs(LOG_NOTICE, c, fmt, __VA_ARGS__)
-#define LOGI(c, fmt, ...) logs(LOG_INFO,   c, fmt, __VA_ARGS__)
-#define LOGD(c, fmt, ...) logs(LOG_DEBUG,  c, fmt, __VA_ARGS__)
-
 struct vhost hosts[HOSTSLEN];
 
 int connected_clients;
@@ -90,8 +85,7 @@ fatal(const char *fmt, ...)
 	exit(1);
 }
 
-__attribute__ ((format (printf, 3, 4)))
-static inline void
+void
 logs(int priority, struct client *c,
     const char *fmt, ...)
 {
@@ -103,13 +97,18 @@ logs(int priority, struct client *c,
 
 	va_start(ap, fmt);
 
-	len = sizeof(c->addr);
-	ec = getnameinfo((struct sockaddr*)&c->addr, len,
-	    hbuf, sizeof(hbuf),
-	    sbuf, sizeof(sbuf),
-	    NI_NUMERICHOST | NI_NUMERICSERV);
-	if (ec != 0)
-		fatal("getnameinfo: %s", gai_strerror(ec));
+	if (c == NULL) {
+		strncpy(hbuf, "<internal>", sizeof(hbuf));
+		sbuf[0] = '\0';
+	} else {
+		len = sizeof(c->addr);
+		ec = getnameinfo((struct sockaddr*)&c->addr, len,
+			hbuf, sizeof(hbuf),
+			sbuf, sizeof(sbuf),
+			NI_NUMERICHOST | NI_NUMERICSERV);
+		if (ec != 0)
+			fatal("getnameinfo: %s", gai_strerror(ec));
+	}
 
 	if (vasprintf(&fmted, fmt, ap) == -1)
 		fatal("vasprintf: %s", strerror(errno));
@@ -961,31 +960,7 @@ load_vhosts(struct tls_config *tlsconf)
 	}
 }
 
-/* we can augment this function to handle also capsicum and seccomp eventually */
 void
-sandbox()
-{
-        struct vhost *h;
-	int has_cgi = 0;
-
-	for (h = hosts; h->domain != NULL; ++h) {
-		if (unveil(h->dir, "rx") == -1)
-			err(1, "unveil %s for domain %s", h->dir, h->domain);
-
-		if (h->cgi != NULL)
-			has_cgi = 1;
-	}
-
-	if (pledge("stdio rpath inet proc exec", NULL) == -1)
-		err(1, "pledge");
-
-	/* drop proc and exec if cgi isn't enabled */
-	if (!has_cgi)
-		if (pledge("stdio rpath inet", NULL) == -1)
-			err(1, "pledge");
-}
-
-void
 usage(const char *me)
 {
 	fprintf(stderr,
@@ -1002,7 +977,7 @@ main(int argc, char **argv)
 	int sock4, sock6, ch;
 	const char *config_path = NULL;
 	size_t i;
-	int conftest = 0, has_cgi = 0;
+	int conftest = 0;
 
 	bzero(hosts, sizeof(hosts));
 	for (i = 0; i < HOSTSLEN; ++i)
blob - cbf9da3a94d38b5df3a8bccbdfd732a482c719c9
blob + 3477cfefefdabc2af14d5ee18d930710a7c10588
--- gmid.h
+++ gmid.h
@@ -28,11 +28,6 @@
 #include <tls.h>
 #include <unistd.h>
 
-#ifndef __OpenBSD__
-# define pledge(a, b) 0
-# define unveil(a, b) 0
-#endif
-
 #ifndef INFTIM
 # define INFTIM -1
 #endif
@@ -52,6 +47,12 @@
 
 #define HOSTSLEN	64
 
+#define LOGE(c, fmt, ...) logs(LOG_ERR,     c, fmt, __VA_ARGS__)
+#define LOGW(c, fmt, ...) logs(LOG_WARNING, c, fmt, __VA_ARGS__)
+#define LOGN(c, fmt, ...) logs(LOG_NOTICE,  c, fmt, __VA_ARGS__)
+#define LOGI(c, fmt, ...) logs(LOG_INFO,    c, fmt, __VA_ARGS__)
+#define LOGD(c, fmt, ...) logs(LOG_DEBUG,   c, fmt, __VA_ARGS__)
+
 struct vhost {
 	const char	*domain;
 	const char	*cert;
@@ -118,6 +119,8 @@ enum {
 };
 
 /* gmid.c */
+__attribute__ ((format (printf, 3, 4))) void logs(int, struct client*, const char*, ...);
+
 void		 sig_handler(int);
 int		 starts_with(const char*, const char*);
 
@@ -149,7 +152,6 @@ void		 yyerror(const char*);
 int		 parse_portno(const char*);
 void		 parse_conf(const char*);
 void		 load_vhosts(struct tls_config*);
-void		 sandbox();
 
 void		 usage(const char*);
 
@@ -158,6 +160,9 @@ extern int yylineno;
 extern int yyparse(void);
 extern int yylex(void);
 
+/* sandbox.c */
+void		 sandbox();
+
 /* utf8.c */
 int		 valid_multibyte_utf8(struct parser*);
 
blob - /dev/null
blob + 6618e5dcce42d7857979866b6b22fe504b86a57c (mode 644)
--- /dev/null
+++ sandbox.c
@@ -0,0 +1,71 @@
+#include "gmid.h"
+
+#if defined(__FreeBSD__)
+
+#include <sys/capsicum.h>
+#include <err.h>
+
+void
+sandbox()
+{
+	struct vhost *h;
+	int has_cgi = 0;
+
+	for (h = hosts; h->domain != NULL; ++h)
+		if (h->cgi != NULL)
+			has_cgi = 1;
+
+	if (has_cgi) {
+		LOGW(NULL, "disabling sandbox because CGI scripts are enabled");
+		return;
+	}
+
+	if (cap_enter() == -1)
+		err(1, "cap_enter");
+}
+
+#elif defined(__linux__)
+
+void
+sandbox()
+{
+	/* TODO: seccomp */
+}
+
+#elif defined(__OpenBSD__)
+
+#include <err.h>
+#include <unistd.h>
+
+void
+sandbox()
+{
+	struct vhost *h;
+	int has_cgi = 0;
+
+	for (h = hosts; h->domain != NULL; ++h) {
+		if (unveil(h->dir, "rx") == -1)
+			err(1, "unveil %s for domain %s", h->dir, h->domain);
+
+		if (h->cgi != NULL)
+			has_cgi = 1;
+	}
+
+	if (pledge("stdio rpath inet proc exec", NULL) == -1)
+		err(1, "pledge");
+
+	/* drop proc and exec if cgi isn't enabled */
+	if (!has_cgi)
+		if (pledge("stdio rpath inet", NULL) == -1)
+			err(1, "pledge");
+}
+
+#else
+
+void
+sandbox()
+{
+        LOGN(NULL, "%s", "no sandbox method known for this OS");
+}
+
+#endif