X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=blobdiff_plain;f=tools%2Fwrapper.c;fp=tools%2Fwrapper.c;h=448598e22a1e2b64d2dba61632bc50e64fccf736;hp=0000000000000000000000000000000000000000;hb=0400a5a6479398d82526785c18c0df8bc8b92dce;hpb=d17e10da972ce5776c60b4c317267c6abe0e1ead diff --git a/tools/wrapper.c b/tools/wrapper.c new file mode 100644 index 0000000..448598e --- /dev/null +++ b/tools/wrapper.c @@ -0,0 +1,220 @@ +/* +** Copyright (C) 2000 by Kevin L. Mitchell +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** +** @(#)$Id$ +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Try and find the correct name to use with getrlimit() for setting the max. + * number of files allowed to be open by this process. + * + * Shamelessly stolen from ircu... + */ +#ifdef RLIMIT_FDMAX +#define RLIMIT_FD_MAX RLIMIT_FDMAX +#else +#ifdef RLIMIT_NOFILE +#define RLIMIT_FD_MAX RLIMIT_NOFILE +#else +#ifdef RLIMIT_OPEN_MAX +#define RLIMIT_FD_MAX RLIMIT_OPEN_MAX +#else +#error Unable to find a valid RLIMIT_FD_MAX +#endif +#endif +#endif + +/*fix for change uid/gid with chroot #ubra 08/02/03*/ +int uid, gid; + +/* + * Set the hard and soft limits for maximum file descriptors. + */ +int +set_fdlimit(unsigned int max_descriptors) +{ + struct rlimit limit; + + limit.rlim_max = limit.rlim_cur = max_descriptors; + + return setrlimit(RLIMIT_FD_MAX, &limit); +} + +/* + * Change directories to the indicated root directory, then make it the + * root directory. + */ +int +change_root(char *root) +{ + if (chdir(root)) + return -1; + if (chroot(root)) + return -1; + + return 0; +} + +/* + * Change the user and group ids--including supplementary groups!--as + * appropriate. + * + * fix for change uid/gid with chroot #ubra 08/02/03 + * old change_user() got splited into get_user() and set_user() + */ +int +get_user(char *user, char *group) +{ + struct passwd *pwd; + struct group *grp; + char *tmp; + + /* Track down a struct passwd describing the desired user */ + uid = strtol(user, &tmp, 10); /* was the user given as a number? */ + if (*tmp) { /* strtol() failed to parse; look up as a user name */ + if (!(pwd = getpwnam(user))) + return -1; + } else if (!(pwd = getpwuid(uid))) /* look up uid */ + return -1; + + uid = pwd->pw_uid; /* uid to change to */ + gid = pwd->pw_gid; /* default gid for user */ + + if (group) { /* a group was specified; track down struct group */ + gid = strtol(group, &tmp, 10); /* was the group given as a number? */ + if (*tmp) { /* strtol() failed to parse; look up as a group name */ + if (!(grp = getgrnam(group))) + return -1; + } else if (!(grp = getgrgid(gid))) /* look up gid */ + return -1; + + gid = grp->gr_gid; /* set the gid */ + } + + if (initgroups(pwd->pw_name, gid)) /* initialize supplementary groups */ + return -1; + return 0; /* success! */ +} + +int +set_user(void) { + if (setgid(gid)) /* change our current group */ + return -1; + if (setuid(uid)) /* change our current user */ + return -1; + + return 0; /* success! */ +} + +/* + * Explain how to use this program. + */ +void +usage(char *prog, int retval) +{ + fprintf(stderr, "Usage: %s [-u ] [-g ] [-l ] [-c ]" + " -- \\\n\t\t []\n", prog); + fprintf(stderr, " %s -h\n", prog); + + exit(retval); +} + +int +main(int argc, char **argv) +{ + int c, limit = -1; + char *prog, *user = 0, *group = 0, *root = 0; + + /* determine program name for error reporting */ + if ((prog = strrchr(argv[0], '/'))) + prog++; + else + prog = argv[0]; + + /* process command line arguments */ + while ((c = getopt(argc, argv, "hu:g:l:c:")) > 0) + switch (c) { + case 'h': /* requested help */ + usage(prog, 0); + break; + + case 'u': /* suggested a user */ + user = optarg; + break; + + case 'g': /* suggested a group */ + group = optarg; + break; + + case 'l': /* file descriptor limit */ + limit = strtol(optarg, 0, 10); + break; + + case 'c': /* select a root directory */ + root = optarg; + break; + + default: /* unknown command line argument */ + usage(prog, 1); + break; + } + + /* Not enough arguments; we must have a command to execute! */ + if (optind >= argc) + usage(prog, 1); + + if (limit > 0) /* set the requested fd limit */ + if (set_fdlimit(limit) < 0) { + perror(prog); + return 1; + } + + if(user) /* get the selected user account uid/gid*/ + if (get_user(user, group)) { + perror(prog); + return 1; + } + + + if (root) /* change root directories */ + if (change_root(root)) { + perror(prog); + return 1; + } + + if (user) /* change to selected user account */ + if (set_user()) { + perror(prog); + return 1; + } + + /* execute the requested command */ + execvp(argv[optind], argv + optind); + + /* If we got here, execvp() failed; report the error */ + perror(prog); + return 1; +}