reducecap.c (10341B)
1 // $Id$ 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // based on reducecap.cc by Jacques Gelinas 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 #ifdef HAVE_CONFIG_H 21 # include <config.h> 22 #endif 23 24 #include "util.h" 25 #include "vserver.h" 26 27 #include <stdio.h> 28 #include <errno.h> 29 #include <unistd.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <getopt.h> 33 #include <sys/param.h> 34 35 #define ENSC_WRAPPERS_PREFIX "reducecap: " 36 #define ENSC_WRAPPERS_VSERVER 1 37 #define ENSC_WRAPPERS_UNISTD 1 38 #include <wrappers.h> 39 40 41 #undef _POSIX_SOURCE 42 #include "capability-compat.h" 43 44 45 #define CMD_HELP 0x1000 46 #define CMD_VERSION 0x1001 47 48 #define CMD_SHOW 0x2000 49 #define CMD_PID 0x2001 50 51 #define CMD_CAP 0x4000 52 #define CMD_FLAG 0x4004 53 #define CMD_SECURE 0x4006 54 55 #ifdef VC_ENABLE_API_LEGACY 56 # define CMD_OBSOLETE_CHOWN 0x8000 57 # define CMD_OBSOLETE_DAC_OVERRIDE 0x8001 58 # define CMD_OBSOLETE_DAC_READ_SEARCH 0x8002 59 # define CMD_OBSOLETE_FOWNER 0x8003 60 # define CMD_OBSOLETE_FSETID 0x8004 61 # define CMD_OBSOLETE_KILL 0x8005 62 # define CMD_OBSOLETE_SETGID 0x8006 63 # define CMD_OBSOLETE_SETUID 0x8007 64 # define CMD_OBSOLETE_SETPCAP 0x8008 65 # define CMD_OBSOLETE_SYS_TTY_CONFIG 0x8009 66 # define CMD_OBSOLETE_LEASE 0x800a 67 # define CMD_OBSOLETE_SYS_CHROOT 0x800b 68 # define CMD_OBSOLETE_X_LINUX_IMMUTABLE 0x800c 69 # define CMD_OBSOLETE_X_NET_BIND_SERVICE 0x800d 70 # define CMD_OBSOLETE_X_NET_BROADCAST 0x800e 71 # define CMD_OBSOLETE_X_NET_ADMIN 0x800f 72 # define CMD_OBSOLETE_X_NET_RAW 0x8010 73 # define CMD_OBSOLETE_X_IPC_LOCK 0x8011 74 # define CMD_OBSOLETE_X_IPC_OWNER 0x8012 75 # define CMD_OBSOLETE_X_SYS_MODULE 0x8013 76 # define CMD_OBSOLETE_X_SYS_RAWIO 0x8014 77 # define CMD_OBSOLETE_X_SYS_PACCT 0x8015 78 # define CMD_OBSOLETE_X_SYS_ADMIN 0x8016 79 # define CMD_OBSOLETE_X_SYS_BOOT 0x8017 80 # define CMD_OBSOLETE_X_SYS_NICE 0x8018 81 # define CMD_OBSOLETE_X_SYS_RESOURCE 0x8019 82 # define CMD_OBSOLETE_X_SYS_TIME 0x801a 83 # define CMD_OBSOLETE_X_MKNOD 0x801b 84 # define CMD_OBSOLETE_X_QUOTACTL 0x801c 85 86 static char const * const OBSOLETE_MAPPING[] = { 87 // 0 1 2 3 88 "CHOWN", "DAC_OVERRIDE", "DAC_READ_SEARCH", "FOWNER", 89 "FSETID", "KILL", "SETGID", "SETUID", 90 "SETPCAP", "SYS_TTY_CONFIG", "LEASE", "SYS_CHROOT", 91 "LINUX_IMMUTABLE", "NET_BIND_SERVICE", "NET_BROADCAST", "NET_ADMIN", 92 "NET_RAW", "IPC_LOCK", "IPC_OWNER", "SYS_MODULE", 93 "SYS_RAWIO", "SYS_PACCT", "SYS_ADMIN", "SYS_BOOT", 94 "SYS_NICE", "SYS_RESOURCE", "SYS_TIME", "MKNOD", 95 "QUOTACTL" }; 96 #endif 97 98 struct option const 99 CMDLINE_OPTIONS[] = { 100 { "help", no_argument, 0, CMD_HELP }, 101 { "version", no_argument, 0, CMD_VERSION }, 102 { "cap", required_argument, 0, CMD_CAP }, 103 { "flag", required_argument, 0, CMD_FLAG }, 104 { "secure", no_argument, 0, CMD_SECURE }, 105 { "show", no_argument, 0, CMD_SHOW }, 106 { "pid", required_argument, 0, CMD_PID }, 107 #ifdef VC_ENABLE_API_LEGACY 108 { "CAP_CHOWN", no_argument, 0, CMD_OBSOLETE_CHOWN }, 109 { "CAP_DAC_OVERRIDE", no_argument, 0, CMD_OBSOLETE_DAC_OVERRIDE }, 110 { "CAP_DAC_READ_SEARCH", no_argument, 0, CMD_OBSOLETE_DAC_READ_SEARCH }, 111 { "CAP_FOWNER", no_argument, 0, CMD_OBSOLETE_FOWNER }, 112 { "CAP_FSETID", no_argument, 0, CMD_OBSOLETE_FSETID }, 113 { "CAP_KILL", no_argument, 0, CMD_OBSOLETE_KILL }, 114 { "CAP_SETGID", no_argument, 0, CMD_OBSOLETE_SETGID }, 115 { "CAP_SETUID", no_argument, 0, CMD_OBSOLETE_SETUID }, 116 { "CAP_SETPCAP", no_argument, 0, CMD_OBSOLETE_SETPCAP }, 117 { "CAP_SYS_TTY_CONFIG", no_argument, 0, CMD_OBSOLETE_SYS_TTY_CONFIG }, 118 { "CAP_LEASE", no_argument, 0, CMD_OBSOLETE_LEASE }, 119 { "CAP_SYS_CHROOT", no_argument, 0, CMD_OBSOLETE_SYS_CHROOT }, 120 { "--CAP_LINUX_IMMUTABLE", no_argument, 0, CMD_OBSOLETE_X_LINUX_IMMUTABLE }, 121 { "--CAP_NET_BIND_SERVICE", no_argument, 0, CMD_OBSOLETE_X_NET_BIND_SERVICE }, 122 { "--CAP_NET_BROADCAST", no_argument, 0, CMD_OBSOLETE_X_NET_BROADCAST }, 123 { "--CAP_NET_ADMIN", no_argument, 0, CMD_OBSOLETE_X_NET_ADMIN }, 124 { "--CAP_NET_RAW", no_argument, 0, CMD_OBSOLETE_X_NET_RAW }, 125 { "--CAP_IPC_LOCK", no_argument, 0, CMD_OBSOLETE_X_IPC_LOCK }, 126 { "--CAP_IPC_OWNER", no_argument, 0, CMD_OBSOLETE_X_IPC_OWNER }, 127 { "--CAP_SYS_MODULE", no_argument, 0, CMD_OBSOLETE_X_SYS_MODULE }, 128 { "--CAP_SYS_RAWIO", no_argument, 0, CMD_OBSOLETE_X_SYS_RAWIO }, 129 { "--CAP_SYS_PACCT", no_argument, 0, CMD_OBSOLETE_X_SYS_PACCT }, 130 { "--CAP_SYS_ADMIN", no_argument, 0, CMD_OBSOLETE_X_SYS_ADMIN }, 131 { "--CAP_SYS_BOOT", no_argument, 0, CMD_OBSOLETE_X_SYS_BOOT }, 132 { "--CAP_SYS_NICE", no_argument, 0, CMD_OBSOLETE_X_SYS_NICE }, 133 { "--CAP_SYS_RESOURCE", no_argument, 0, CMD_OBSOLETE_X_SYS_RESOURCE }, 134 { "--CAP_SYS_TIME", no_argument, 0, CMD_OBSOLETE_X_SYS_TIME }, 135 { "--CAP_MKNOD", no_argument, 0, CMD_OBSOLETE_X_MKNOD }, 136 { "--CAP_QUOTACTL", no_argument, 0, CMD_OBSOLETE_X_QUOTACTL }, 137 #endif 138 { 0,0,0,0 } 139 }; 140 141 int wrapper_exit_code = 255; 142 143 static void 144 showHelp(int fd, char const *cmd, int res) 145 { 146 #if !defined(VC_ENABLE_API_COMPAT) && !defined(VC_ENABLE_API_LEGACY) 147 WRITE_MSG(1, "ERROR: tools were built without legacy API support; reducecap will not work!\n\n"); 148 #endif 149 150 WRITE_MSG(fd, "Usage:\n "); 151 WRITE_STR(fd, cmd); 152 WRITE_MSG(fd, 153 " [--show] [--secure] [--flag <flag>] [--cap <capability>] [--] <cmd> <args>*\n "); 154 WRITE_STR(fd, cmd); 155 WRITE_MSG(fd, 156 " --show [--pid <pid>]\n\n" 157 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 158 159 exit(res); 160 } 161 162 static void 163 showVersion() 164 { 165 WRITE_MSG(1, 166 "reducecap " VERSION " -- starts programs with reduced capabilities\n" 167 "This program is part of " PACKAGE_STRING "\n\n" 168 "Copyright (C) 2003,2004 Enrico Scholz\n" 169 VERSION_COPYRIGHT_DISCLAIMER); 170 exit(0); 171 } 172 173 static void 174 printReducecap(struct __user_cap_data_struct *user) 175 { 176 int i; 177 WRITE_MSG(1, " Capability Effective Permitted Inheritable\n"); 178 179 for (i=0;; ++i) { 180 size_t const len = 23 + 10*2 + 4+2; 181 char const * text = vc_cap2text(i); 182 int bit = 1<<i; 183 size_t l; 184 char buf[len]; 185 if (text==0) break; 186 187 memset(buf, ' ', sizeof buf); 188 buf[len-1] = '\n'; 189 l = MIN(strlen(text), 22); 190 memcpy(buf, text, l); 191 buf[23 + 10*0 + 4] = (user->effective & bit) ? 'X' : ' '; 192 buf[23 + 10*1 + 4] = (user->permitted & bit) ? 'X' : ' '; 193 buf[23 + 10*2 + 4] = (user->inheritable & bit) ? 'X' : ' '; 194 Vwrite(1, buf, len); 195 } 196 } 197 198 static void 199 show(pid_t pid) 200 { 201 struct __user_cap_header_struct header; 202 struct __user_cap_data_struct user; 203 header.version = _LINUX_CAPABILITY_VERSION; 204 header.pid = pid; 205 if (capget(&header,&user)==-1){ 206 perror ("reducecap: capget()"); 207 exit(wrapper_exit_code); 208 } 209 210 printReducecap(&user); 211 } 212 213 #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) 214 215 static uint32_t 216 getCap(char const *cap) 217 { 218 int bit = vc_text2cap(cap); 219 if (bit!=0) { 220 WRITE_MSG(2, "Unknown capability '"); 221 WRITE_STR(2, optarg); 222 WRITE_MSG(2, "'; try '--help' for more information\n"); 223 exit(wrapper_exit_code); 224 } 225 226 return (1<<bit); 227 } 228 229 #endif 230 231 int main (int argc, char *argv[]) 232 { 233 uint32_t remove = 0; 234 bool do_show = false; 235 uint32_t flags = 0; 236 pid_t pid = 0; 237 #ifdef VC_ENABLE_API_LEGACY 238 bool show_obsolete_warning = true; 239 #endif 240 241 while (1) { 242 int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); 243 if (c==-1) break; 244 245 #ifdef VC_ENABLE_API_LEGACY 246 if (c>=CMD_OBSOLETE_CHOWN && c<=CMD_OBSOLETE_X_QUOTACTL) { 247 if (show_obsolete_warning) { 248 WRITE_MSG(2, "reducecap: warning, obsolete CLI used\n"); 249 show_obsolete_warning = false; 250 } 251 252 remove = getCap(OBSOLETE_MAPPING[c-CMD_OBSOLETE_CHOWN]); 253 continue; 254 } 255 #endif 256 switch (c) { 257 case CMD_HELP : showHelp(1, argv[0], 0); 258 case CMD_VERSION : showVersion(); 259 case CMD_SHOW : do_show = true; break; 260 case CMD_PID : pid = atoi(optarg); break; 261 #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) 262 case CMD_SECURE : remove = vc_get_insecurebcaps(); break; 263 case CMD_CAP : remove = getCap(optarg); break; 264 case CMD_FLAG : { 265 struct vc_err_listparser err; 266 267 flags = vc_list2cflag_compat(optarg, 0, &err); 268 if (err.ptr!=0) { 269 WRITE_MSG(2, "Unknown flag '"); 270 Vwrite(2, err.ptr, err.len); 271 WRITE_MSG(2, "'\n"); 272 exit(wrapper_exit_code); 273 } 274 break; 275 } 276 #else 277 case CMD_SECURE : 278 case CMD_CAP : 279 case CMD_FLAG : flags = 0; remove = 0; break; 280 #endif 281 } 282 } 283 284 if (!do_show && optind==argc) { 285 WRITE_MSG(2, "No command given; use '--help' for more information\n"); 286 exit(wrapper_exit_code); 287 } 288 289 if (!do_show && pid!=0) { 290 WRITE_MSG(2, "A pid can be specified in '--show' mode only; use '--help' for more information\n"); 291 exit(wrapper_exit_code); 292 } 293 294 if (do_show && optind==argc) 295 show(pid); 296 #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) 297 else { 298 Evc_new_s_context(VC_SAMECTX, remove, flags); 299 if (do_show) show(pid); 300 301 WRITE_MSG(2, "Executing\n"); 302 Eexecvp(argv[optind], argv+optind); 303 } 304 #else 305 else if (do_show) 306 show(pid); 307 else { 308 WRITE_MSG(2, "reducecap: tools were built without legacy API support; can not continue\n"); 309 exit(wrapper_exit_code); 310 } 311 #endif 312 313 return EXIT_SUCCESS; 314 }