commit - 4ad11931ec10c823e98b7c51efc7146d8cbdd012
commit + dafb57b8af432d800219a8e17900e1ac56a65c14
blob - ee5c0662119a47cadbcb2c1b4bd115adb46c1193
blob + b9949935dc6c07b20654aa87496522be783af260
--- ChangeLog
+++ ChangeLog
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
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
- (very) low memory footprint
- small codebase, easily hackable
- virtual hosts
+ - sandboxed on OpenBSD and FreeBSD
## Drawbacks
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
#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;
exit(1);
}
-__attribute__ ((format (printf, 3, 4)))
-static inline void
+void
logs(int priority, struct client *c,
const char *fmt, ...)
{
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));
}
}
-/* 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,
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
#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
#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;
};
/* 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*);
int parse_portno(const char*);
void parse_conf(const char*);
void load_vhosts(struct tls_config*);
-void sandbox();
void usage(const char*);
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
+#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