]>
Commit | Line | Data |
---|---|---|
189935b1 | 1 | /* |
2 | ** Copyright (C) 2000 by Kevin L. Mitchell <klmitch@mit.edu> | |
3 | ** | |
4 | ** This program is free software; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU General Public License as published by | |
6 | ** the Free Software Foundation; either version 2 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU General Public License | |
15 | ** along with this program; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | ** | |
18 | ** @(#)$Id: wrapper.c,v 1.3 2004/05/15 14:50:09 entrope Exp $ | |
19 | */ | |
20 | #include <string.h> | |
21 | #include <stdlib.h> | |
22 | #include <stdio.h> | |
23 | #include <pwd.h> | |
24 | #include <grp.h> | |
25 | #include <sys/time.h> | |
26 | #include <sys/types.h> | |
27 | #include <sys/resource.h> | |
28 | #include <unistd.h> | |
29 | ||
30 | /* | |
31 | * Try and find the correct name to use with getrlimit() for setting the max. | |
32 | * number of files allowed to be open by this process. | |
33 | * | |
34 | * Shamelessly stolen from ircu... | |
35 | */ | |
36 | #ifdef RLIMIT_FDMAX | |
37 | #define RLIMIT_FD_MAX RLIMIT_FDMAX | |
38 | #else | |
39 | #ifdef RLIMIT_NOFILE | |
40 | #define RLIMIT_FD_MAX RLIMIT_NOFILE | |
41 | #else | |
42 | #ifdef RLIMIT_OPEN_MAX | |
43 | #define RLIMIT_FD_MAX RLIMIT_OPEN_MAX | |
44 | #else | |
45 | #error Unable to find a valid RLIMIT_FD_MAX | |
46 | #endif | |
47 | #endif | |
48 | #endif | |
49 | ||
50 | /*fix for change uid/gid with chroot #ubra 08/02/03*/ | |
51 | int uid, gid; | |
52 | ||
53 | /* | |
54 | * Set the hard and soft limits for maximum file descriptors. | |
55 | */ | |
56 | int | |
57 | set_fdlimit(unsigned int max_descriptors) | |
58 | { | |
59 | struct rlimit limit; | |
60 | ||
61 | limit.rlim_max = limit.rlim_cur = max_descriptors; | |
62 | ||
63 | return setrlimit(RLIMIT_FD_MAX, &limit); | |
64 | } | |
65 | ||
66 | /* | |
67 | * Change directories to the indicated root directory, then make it the | |
68 | * root directory. | |
69 | */ | |
70 | int | |
71 | change_root(char *root) | |
72 | { | |
73 | if (chdir(root)) | |
74 | return -1; | |
75 | if (chroot(root)) | |
76 | return -1; | |
77 | ||
78 | return 0; | |
79 | } | |
80 | ||
81 | /* | |
82 | * Change the user and group ids--including supplementary groups!--as | |
83 | * appropriate. | |
84 | * | |
85 | * fix for change uid/gid with chroot #ubra 08/02/03 | |
86 | * old change_user() got splited into get_user() and set_user() | |
87 | */ | |
88 | int | |
89 | get_user(char *user, char *group) | |
90 | { | |
91 | struct passwd *pwd; | |
92 | struct group *grp; | |
93 | char *tmp; | |
94 | ||
95 | /* Track down a struct passwd describing the desired user */ | |
96 | uid = strtol(user, &tmp, 10); /* was the user given as a number? */ | |
97 | if (*tmp) { /* strtol() failed to parse; look up as a user name */ | |
98 | if (!(pwd = getpwnam(user))) | |
99 | return -1; | |
100 | } else if (!(pwd = getpwuid(uid))) /* look up uid */ | |
101 | return -1; | |
102 | ||
103 | uid = pwd->pw_uid; /* uid to change to */ | |
104 | gid = pwd->pw_gid; /* default gid for user */ | |
105 | ||
106 | if (group) { /* a group was specified; track down struct group */ | |
107 | gid = strtol(group, &tmp, 10); /* was the group given as a number? */ | |
108 | if (*tmp) { /* strtol() failed to parse; look up as a group name */ | |
109 | if (!(grp = getgrnam(group))) | |
110 | return -1; | |
111 | } else if (!(grp = getgrgid(gid))) /* look up gid */ | |
112 | return -1; | |
113 | ||
114 | gid = grp->gr_gid; /* set the gid */ | |
115 | } | |
116 | ||
117 | if (initgroups(pwd->pw_name, gid)) /* initialize supplementary groups */ | |
118 | return -1; | |
119 | return 0; /* success! */ | |
120 | } | |
121 | ||
122 | int | |
123 | set_user(void) { | |
124 | if (setgid(gid)) /* change our current group */ | |
125 | return -1; | |
126 | if (setuid(uid)) /* change our current user */ | |
127 | return -1; | |
128 | ||
129 | return 0; /* success! */ | |
130 | } | |
131 | ||
132 | /* | |
133 | * Explain how to use this program. | |
134 | */ | |
135 | void | |
136 | usage(char *prog, int retval) | |
137 | { | |
138 | fprintf(stderr, "Usage: %s [-u <user>] [-g <group>] [-l <limit>] [-c <root>]" | |
139 | " -- \\\n\t\t<cmd> [<cmdargs>]\n", prog); | |
140 | fprintf(stderr, " %s -h\n", prog); | |
141 | ||
142 | exit(retval); | |
143 | } | |
144 | ||
145 | int | |
146 | main(int argc, char **argv) | |
147 | { | |
148 | int c, limit = -1; | |
149 | char *prog, *user = 0, *group = 0, *root = 0; | |
150 | ||
151 | /* determine program name for error reporting */ | |
152 | if ((prog = strrchr(argv[0], '/'))) | |
153 | prog++; | |
154 | else | |
155 | prog = argv[0]; | |
156 | ||
157 | /* process command line arguments */ | |
158 | while ((c = getopt(argc, argv, "hu:g:l:c:")) > 0) | |
159 | switch (c) { | |
160 | case 'h': /* requested help */ | |
161 | usage(prog, 0); | |
162 | break; | |
163 | ||
164 | case 'u': /* suggested a user */ | |
165 | user = optarg; | |
166 | break; | |
167 | ||
168 | case 'g': /* suggested a group */ | |
169 | group = optarg; | |
170 | break; | |
171 | ||
172 | case 'l': /* file descriptor limit */ | |
173 | limit = strtol(optarg, 0, 10); | |
174 | break; | |
175 | ||
176 | case 'c': /* select a root directory */ | |
177 | root = optarg; | |
178 | break; | |
179 | ||
180 | default: /* unknown command line argument */ | |
181 | usage(prog, 1); | |
182 | break; | |
183 | } | |
184 | ||
185 | /* Not enough arguments; we must have a command to execute! */ | |
186 | if (optind >= argc) | |
187 | usage(prog, 1); | |
188 | ||
189 | if (limit > 0) /* set the requested fd limit */ | |
190 | if (set_fdlimit(limit) < 0) { | |
191 | perror(prog); | |
192 | return 1; | |
193 | } | |
194 | ||
195 | if(user) /* get the selected user account uid/gid*/ | |
196 | if (get_user(user, group)) { | |
197 | perror(prog); | |
198 | return 1; | |
199 | } | |
200 | ||
201 | ||
202 | if (root) /* change root directories */ | |
203 | if (change_root(root)) { | |
204 | perror(prog); | |
205 | return 1; | |
206 | } | |
207 | ||
208 | if (user) /* change to selected user account */ | |
209 | if (set_user()) { | |
210 | perror(prog); | |
211 | return 1; | |
212 | } | |
213 | ||
214 | /* execute the requested command */ | |
215 | execvp(argv[optind], argv + optind); | |
216 | ||
217 | /* If we got here, execvp() failed; report the error */ | |
218 | perror(prog); | |
219 | return 1; | |
220 | } |