s6-ipcserver-access.c (6031B)
1 /* ISC license. */ 2 3 #include <string.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <stdlib.h> 7 8 #include <skalibs/gccattributes.h> 9 #include <skalibs/types.h> 10 #include <skalibs/strerr.h> 11 #include <skalibs/sgetopt.h> 12 #include <skalibs/cdb.h> 13 #include <skalibs/djbunix.h> 14 #include <skalibs/socket.h> 15 #include <skalibs/exec.h> 16 17 #include <s6/config.h> 18 #include <s6/accessrules.h> 19 20 #ifdef S6_USE_EXECLINE 21 #include <execline/config.h> 22 #endif 23 24 #define USAGE "s6-ipcserver-access [ -v verbosity ] [ -e | -E ] [ -l localname ] [ -i rulesdir | -x rulesfile ] prog..." 25 26 static unsigned int verbosity = 1 ; 27 28 /* Utility functions */ 29 30 static inline void dieusage (void) gccattr_noreturn ; 31 static inline void dieusage () 32 { 33 strerr_dieusage(100, USAGE) ; 34 } 35 36 static inline void dienomem (void) gccattr_noreturn ; 37 static inline void dienomem () 38 { 39 strerr_diefu1sys(111, "update environment") ; 40 } 41 42 static inline void X (void) gccattr_noreturn ; 43 static inline void X () 44 { 45 strerr_dief1x(101, "internal inconsistency. Please submit a bug-report.") ; 46 } 47 48 49 /* Logging */ 50 51 static void logit (pid_t pid, uid_t uid, gid_t gid, int h) 52 { 53 char fmtpid[PID_FMT] ; 54 char fmtuid[UID_FMT] ; 55 char fmtgid[GID_FMT] ; 56 fmtpid[pid_fmt(fmtpid, pid)] = 0 ; 57 fmtuid[uid_fmt(fmtuid, uid)] = 0 ; 58 fmtgid[gid_fmt(fmtgid, gid)] = 0 ; 59 if (h) strerr_warni7x("allow", " pid ", fmtpid, " uid ", fmtuid, " gid ", fmtgid) ; 60 else strerr_warni7sys("deny", " pid ", fmtpid, " uid ", fmtuid, " gid ", fmtgid) ; 61 } 62 63 static inline void log_accept (pid_t pid, uid_t uid, gid_t gid) 64 { 65 logit(pid, uid, gid, 1) ; 66 } 67 68 static inline void log_deny (pid_t pid, uid_t uid, gid_t gid) 69 { 70 logit(pid, uid, gid, 0) ; 71 } 72 73 74 /* Checking */ 75 76 static s6_accessrules_result_t check_cdb (uid_t uid, gid_t gid, char const *file, s6_accessrules_params_t *params) 77 { 78 cdb c = CDB_ZERO ; 79 s6_accessrules_result_t r ; 80 if (!cdb_init(&c, file)) strerr_diefu2sys(111, "cdb_init ", file) ; 81 r = s6_accessrules_uidgid_cdb(uid, gid, &c, params) ; 82 cdb_free(&c) ; 83 return r ; 84 } 85 86 static inline int check (s6_accessrules_params_t *params, char const *rules, unsigned int rulestype, uid_t uid, gid_t gid) 87 { 88 char const *x = "" ; 89 s6_accessrules_result_t r ; 90 switch (rulestype) 91 { 92 case 0 : 93 if (verbosity >= 2) strerr_warnw1x("invoked without a ruleset!") ; 94 return 1 ; 95 case 1 : 96 r = s6_accessrules_uidgid_fs(uid, gid, rules, params) ; 97 x = "fs" ; 98 break ; 99 case 2 : 100 r = check_cdb(uid, gid, rules, params) ; 101 x = "cdb" ; 102 break ; 103 default : X() ; 104 } 105 switch (r) 106 { 107 case S6_ACCESSRULES_ERROR : strerr_diefu4sys(111, "check ", x, " ruleset in ", rules) ; 108 case S6_ACCESSRULES_ALLOW : return 1 ; 109 case S6_ACCESSRULES_DENY : return (errno = EACCES, 0) ; 110 case S6_ACCESSRULES_NOTFOUND : return (errno = ENOENT, 0) ; 111 default : X() ; 112 } 113 } 114 115 int main (int argc, char const *const *argv) 116 { 117 s6_accessrules_params_t params = S6_ACCESSRULES_PARAMS_ZERO ; 118 char const *rules = 0 ; 119 char const *localname = 0 ; 120 char const *proto ; 121 size_t protolen ; 122 uid_t uid = 0 ; 123 gid_t gid = 0 ; 124 unsigned int rulestype = 0 ; 125 int doenv = 1 ; 126 PROG = "s6-ipcserver-access" ; 127 { 128 subgetopt l = SUBGETOPT_ZERO ; 129 for (;;) 130 { 131 int opt = subgetopt_r(argc, argv, "v:Eel:i:x:", &l) ; 132 if (opt == -1) break ; 133 switch (opt) 134 { 135 case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; 136 case 'E' : doenv = 0 ; break ; 137 case 'e' : doenv = 1 ; break ; 138 case 'l' : localname = l.arg ; break ; 139 case 'i' : rules = l.arg ; rulestype = 1 ; break ; 140 case 'x' : rules = l.arg ; rulestype = 2 ; break ; 141 default : dieusage() ; 142 } 143 } 144 argc -= l.ind ; argv += l.ind ; 145 } 146 if (!argc) dieusage() ; 147 if (!*argv[0]) dieusage() ; 148 149 proto = getenv("PROTO") ; 150 if (!proto) strerr_dienotset(100, "PROTO") ; 151 protolen = strlen(proto) ; 152 153 { 154 char const *x ; 155 char tmp[protolen + 11] ; 156 memcpy(tmp, proto, protolen) ; 157 memcpy(tmp + protolen, "REMOTEEUID", 11) ; 158 x = getenv(tmp) ; 159 if (!x) strerr_dienotset(100, tmp) ; 160 if (!uid0_scan(x, &uid)) strerr_dieinvalid(100, tmp) ; 161 tmp[protolen + 7] = 'G' ; 162 x = getenv(tmp) ; 163 if (!x) strerr_dienotset(100, tmp) ; 164 if (!gid0_scan(x, &gid)) strerr_dieinvalid(100, tmp) ; 165 } 166 167 if (check(¶ms, rules, rulestype, uid, gid)) goto accepted ; 168 169 if (verbosity >= 2) log_deny(getpid(), uid, gid) ; 170 return 1 ; 171 172 accepted: 173 if (verbosity) log_accept(getpid(), uid, gid) ; 174 175 if (doenv) 176 { 177 char tmp[protolen + 10] ; 178 memcpy(tmp, proto, protolen) ; 179 memcpy(tmp + protolen, "LOCALPATH", 10) ; 180 if (localname) 181 { 182 if (!env_addmodif(¶ms.env, tmp, localname)) dienomem() ; 183 } 184 else 185 { 186 char curname[IPCPATH_MAX+1] ; 187 int dummy ; 188 if (ipc_local(0, curname, IPCPATH_MAX+1, &dummy) < 0) 189 strerr_diefu1sys(111, "ipc_local") ; 190 if (!env_addmodif(¶ms.env, tmp, curname)) dienomem() ; 191 } 192 } 193 else 194 { 195 char tmp[protolen + 11] ; 196 memcpy(tmp, proto, protolen) ; 197 memcpy(tmp + protolen, "REMOTEEUID", 11) ; 198 if (!env_addmodif(¶ms.env, "PROTO", 0)) dienomem() ; 199 if (!env_addmodif(¶ms.env, tmp, 0)) dienomem() ; 200 tmp[protolen + 7] = 'G' ; 201 if (!env_addmodif(¶ms.env, tmp, 0)) dienomem() ; 202 memcpy(tmp + protolen + 6, "PATH", 5) ; 203 if (!env_addmodif(¶ms.env, tmp, 0)) dienomem() ; 204 memcpy(tmp + protolen, "LOCALPATH", 10) ; 205 if (!env_addmodif(¶ms.env, tmp, 0)) dienomem() ; 206 memcpy(tmp + protolen, "CONNNUM", 8) ; 207 if (!env_addmodif(¶ms.env, tmp, 0)) dienomem() ; 208 } 209 210 if (params.exec.len) 211 #ifdef S6_USE_EXECLINE 212 { 213 char *specialargv[4] = { EXECLINE_EXTBINPREFIX "execlineb", "-Pc", params.exec.s, 0 } ; 214 xmexec_m((char const *const *)specialargv, params.env.s, params.env.len) ; 215 } 216 #else 217 strerr_warnw1x("exec file found but ignored because s6 was compiled without execline support!") ; 218 #endif 219 xmexec_m(argv, params.env.s, params.env.len) ; 220 }