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