snac2

Fork of https://codeberg.org/grunfink/snac2
git clone https://git.inz.fi/snac2
Log | Files | Refs | README | LICENSE

sandbox.c (4680B)


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