2.91 sandbox.c
  1#include "xs.h"
  2
  3#include "snac.h"
  4
  5#if defined(__OpenBSD__)
  6
  7void sbox_enter(const char *basedir)
  8{
  9    const char *address = xs_dict_get(srv_config, "address");
 10
 11    if (xs_is_true(xs_dict_get(srv_config, "disable_openbsd_security"))) {
 12        srv_log(xs_dup("OpenBSD security disabled by admin"));
 13        return;
 14    }
 15
 16    const xs_val *strip_exif = xs_dict_get(srv_config, "strip_exif");
 17
 18    int smail;
 19    const char *url = xs_dict_get(srv_config, "smtp_url");
 20
 21    if (xs_is_string(url) && *url)
 22        smail = 0;
 23    else
 24        smail = !xs_is_true(xs_dict_get(srv_config, "disable_email_notifications"));
 25
 26    srv_debug(1, xs_fmt("Calling unveil()"));
 27    unveil(basedir,                "rwc");
 28    unveil("/tmp",                 "rwc");
 29    unveil("/etc/resolv.conf",     "r");
 30    unveil("/etc/hosts",           "r");
 31    unveil("/etc/ssl/openssl.cnf", "r");
 32    unveil("/etc/ssl/cert.pem",    "r");
 33    unveil("/usr/share/zoneinfo",  "r");
 34
 35    if (*address == '/')
 36        unveil(address, "rwc");
 37
 38    if (strip_exif) {
 39        unveil(xs_dict_get(srv_config, "ffmpeg_path"), "x");
 40        unveil(xs_dict_get(srv_config, "mogrify_path"), "x");
 41    }
 42
 43    if (smail)
 44        unveil("/usr/sbin/sendmail",   "x");
 45
 46    unveil(NULL,                   NULL);
 47
 48    srv_debug(1, xs_fmt("Calling pledge()"));
 49
 50    xs *p = xs_str_new("stdio rpath wpath cpath flock inet proc dns fattr");
 51
 52    if (*address == '/')
 53        p = xs_str_cat(p, " unix");
 54
 55    if (smail || strip_exif)
 56        p = xs_str_cat(p, " exec");
 57
 58    pledge(p, NULL);
 59}
 60
 61#elif defined(__linux__)
 62
 63#if defined(WITH_LINUX_SANDBOX)
 64
 65#include <unistd.h>
 66
 67#define LL_PRINTERR(fmt, ...) srv_debug(0, xs_fmt(fmt, __VA_ARGS__))
 68#include "landloc.h"
 69
 70static
 71LL_BEGIN(sbox_enter_linux_, const char* basedir, const char *address, int smtp_port) {
 72
 73    const unsigned long long
 74        rd = LANDLOCK_ACCESS_FS_READ_DIR,
 75        rf = LANDLOCK_ACCESS_FS_READ_FILE,
 76        w  = LANDLOCK_ACCESS_FS_WRITE_FILE      |
 77             LANDLOCK_ACCESS_FS_TRUNCATE_COMPAT,
 78        c  = LANDLOCK_ACCESS_FS_MAKE_DIR        |
 79             LANDLOCK_ACCESS_FS_MAKE_REG        |
 80             LANDLOCK_ACCESS_FS_TRUNCATE_COMPAT |
 81             LANDLOCK_ACCESS_FS_MAKE_SYM        |
 82             LANDLOCK_ACCESS_FS_REMOVE_DIR      |
 83             LANDLOCK_ACCESS_FS_REMOVE_FILE     |
 84             LANDLOCK_ACCESS_FS_REFER_COMPAT,
 85        s  = LANDLOCK_ACCESS_FS_MAKE_SOCK,
 86        x  = LANDLOCK_ACCESS_FS_EXECUTE;
 87    char *resolved_path = NULL;
 88
 89    LL_PATH(basedir,                rf|rd|w|c);
 90    LL_PATH("/tmp",                 rf|rd|w|c);
 91#ifndef WITHOUT_SHM
 92    LL_PATH("/dev/shm",             rf|w|c   );
 93#endif
 94    LL_PATH("/dev/urandom",         rf       );
 95    LL_PATH("/etc/resolv.conf",     rf       );
 96    LL_PATH("/etc/hosts",           rf       );
 97    LL_PATH("/etc/ssl",             rf|rd    );
 98    if ((resolved_path = realpath("/etc/ssl/cert.pem", NULL))) {
 99        /* some distros like cert.pem to be a symlink */
100        LL_PATH(resolved_path,      rf       );
101        free(resolved_path);
102    }
103    LL_PATH("/usr/share/zoneinfo",  rf       );
104
105    if (mtime("/etc/pki") > 0)
106        LL_PATH("/etc/pki",         rf       );
107
108    if (*address == '/') {
109        /* the directory holding the socket must be allowed */
110        xs *l = xs_split(address, "/");
111        l = xs_list_del(l, -1);
112        xs *sdir = xs_join(l, "/");
113
114        LL_PATH(sdir, s);
115    }
116
117    if (*address != '/') {
118        unsigned short listen_port = xs_number_get(xs_dict_get(srv_config, "port"));
119        LL_PORT(listen_port, LANDLOCK_ACCESS_NET_BIND_TCP_COMPAT);
120    }
121
122    LL_PORT(80,  LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT);
123    LL_PORT(443, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT);
124    if (smtp_port > 0)
125        LL_PORT((unsigned short)smtp_port, LANDLOCK_ACCESS_NET_CONNECT_TCP_COMPAT);
126
127} LL_END
128
129void sbox_enter(const char *basedir)
130{
131    const char *errstr;
132    const char *address = xs_dict_get(srv_config, "address");
133    const char *smtp_url = xs_dict_get(srv_config, "smtp_url");
134    int smtp_port = -1;
135
136    if (xs_is_true(xs_dict_get(srv_config, "disable_sandbox"))) {
137        srv_debug(1, xs_dup("Linux sandbox disabled by admin"));
138        return;
139    }
140
141    if (xs_is_string(smtp_url) && *smtp_url != '\0') {
142        smtp_port = parse_port(smtp_url, &errstr);
143        if (errstr)
144            srv_debug(0, xs_fmt("Couldn't determine port from '%s': %s", smtp_url, errstr));
145    }
146
147    if (sbox_enter_linux_(basedir, address, smtp_port) == 0)
148        srv_debug(1, xs_dup("Linux sandbox enabled"));
149    else
150        srv_debug(0, xs_dup("Linux sandbox failed"));
151}
152
153#else /* defined(WITH_LINUX_SANDBOX) */
154
155void sbox_enter(const char *basedir)
156{
157    (void)basedir;
158
159    srv_debug(1, xs_fmt("Linux sandbox not compiled in"));
160}
161
162#endif
163
164#else
165
166/* other OSs: dummy sbox_enter() */
167
168void sbox_enter(const char *basedir)
169{
170    (void)basedir;
171}
172
173
174#endif /* __OpenBSD__ */