commit dafb57b8af432d800219a8e17900e1ac56a65c14 from: Omar Polo date: Fri Jan 15 14:03:45 2021 UTC sandbox also on FreeBSD with capsicum commit - 4ad11931ec10c823e98b7c51efc7146d8cbdd012 commit + dafb57b8af432d800219a8e17900e1ac56a65c14 blob - ee5c0662119a47cadbcb2c1b4bd115adb46c1193 blob + b9949935dc6c07b20654aa87496522be783af260 --- ChangeLog +++ ChangeLog @@ -1,5 +1,7 @@ 2021-01-15 Omar Polo + * 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, "", 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 #include -#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 +#include + +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 +#include + +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