]> jfr.im git - irc/quakenet/snircd.git/blame - tools/wrapper.c
Initial import of 2.10.12.01
[irc/quakenet/snircd.git] / tools / wrapper.c
CommitLineData
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*/
51int uid, gid;
52
53/*
54 * Set the hard and soft limits for maximum file descriptors.
55 */
56int
57set_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 */
70int
71change_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 */
88int
89get_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
122int
123set_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 */
135void
136usage(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
145int
146main(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}