merge with 0.30.213
[util-vserver.git] / src / reducecap.c
1 // $Id: reducecap.c 2279 2006-01-22 19:31:53Z ensc $
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 }