home *** CD-ROM | disk | FTP | other *** search
- /*++
- /* NAME
- /* opcom 8
- /* SUMMARY
- /* execute an operator command.
- /* SYNOPSIS
- /* .fi
- /* .B opcom
- /* command [ arguments ]
- /* DESCRIPTION
- /* .I Opcom
- /* enables users belonging to a special group (as defined in /etc/group)
- /* to execute a limited set of commands with another userid (e.g. root)
- /* or groupid. The file
- /* .I XCOMMANDS
- /* describes which commands are allowed for which groups and which
- /* userid (groupid) must be used.
- /* .br
- /* .I Command
- /* is a valid operator command, if it matches an entry in
- /* .I XCOMMANDS.
- /* Those entries have the following form:
- /*
- /* path-name : operator-group : [ new-userid ] [ : [ new-groupid ]]
- /*
- /* .I Command
- /* matches an entry, if it is the basename of
- /* .I path-name
- /* and if the user executing
- /* .I opcom
- /* is a member of the group
- /* .I operator-group
- /* (as defined in /etc/group).
- /* If
- /* .I command
- /* matches more than one entry, the first matching entry is selected.
- /* This allows multiple levels of privilege.
- /* .br
- /* If no match is found,
- /* .I opcom
- /* aborts with the message "access denied.".
- /*
- /* .I Command
- /* is executed with the given
- /* .I arguments.
- /* The environment is the current environment with the following
- /* exceptions:
- /* .br
- /* If
- /* .I user-id (group-id)
- /* is not empty, the effective and real userid (groupid) are set to
- /* .I user-id (group-id).
- /* .br
- /* If
- /* .I user-id (group-id)
- /* is empty, the effective and real userid (groupid)
- /* are set to the real userid (groupid).
- /*
- /* The following environment variables are set:
- /* .IP \- 2.4
- /* COMMAND to
- /* .I command.
- /* .IP \-
- /* GROUP to
- /* .I operator-group.
- /* .IP \-
- /* IFS to blank, tab and new line.
- /* .IP \-
- /* ORGUSER to the login name of the real userid of the invoker of
- /* .I opcom.
- /* .IP \-
- /* PATH to /
- /* .IP \-
- /* USER and LOGNAME to the login name of the real userid executing
- /* .I command.
- /* .RE
- /*
- /* If the script
- /* .I XPROFILE
- /* exists, this script will be executed
- /* within the shell, that executes
- /* .I command.
- /* So changes to the environment (e.g. PATH) can be put there.
- /* FILES
- /* XCOMMANDS
- /* XPROFILE
- /* /etc/group
- /* CAVEAT
- /* Beware of Trojan horses: don't allow commands with shell escapes.
- /* BUGS
- /* The syntax of entries in
- /* .I XCOMMANDS
- /* is not checked rigorously.
- /* DIAGNOSTICS
- /* In case of error
- /* .I opcom
- /* prints an error message on standard error and terminates
- /* with nonzero status.
- /* AUTHOR(S)
- /*
- /* C.G.S.M. Braam
- /* Eindhoven University of Technology
- /* Computing Centre
- /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- /* BUG REPORTS TO
- /* rccarel@eutrc3.UUCP
- /* CREATION DATE
- /* Wed Jan 4 14:12:59 MET 1989
- /* LAST MODIFICATION
- /* Tue Jan 17 13:15:08 MET 1989
- /* VERSION/RELEASE
- /* 1.3
- /*--*/
-
- #include <stdio.h>
- #include "sysdep.h"
- #include <grp.h>
- #include <pwd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <varargs.h>
- #include <ctype.h>
-
- extern void exit ();
- extern void perror ();
-
- extern int errno;
- extern char *sys_errlist [];
- extern int sys_nerr;
-
- extern int geteuid ();
- extern int getgid ();
- extern int setuid ();
- extern struct group *getgrnam ();
- extern struct passwd *getpwnam ();
- extern struct passwd *getpwuid ();
- extern char *malloc ();
- extern int putenv ();
- extern int system ();
-
- #define WARN 0
- #define ABORT 1
-
- struct command {
- char *name;
- char path [1024];
- char group [32];
- char new_group [32];
- char new_user [32];
- };
-
- void PERROR ();
- int check_group ();
- void error ();
- void exec_cmnd ();
- struct command *get_command ();
- char *nextitem ();
- void usage_error ();
- void set_env ();
- void set_ids ();
-
- char orguser [32];
- char *progname; /* used for diagnostics */
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- int fd;
- struct command *command;
-
- /* close all file descriptors > 2 */
- for (fd = 3; fd <= _NFILE; fd++)
- (void) close (fd);
- if (progname = strrchr (*argv, '/'))
- progname++;
- else
- progname = *argv;
- argv++; argc--;
-
- if (argc == 0)
- usage_error ();
-
- command = get_command (*argv);
- set_ids (command->new_user, command->new_group);
- exec_cmnd (command, argc-1, argv+1);
- return (0); /* makes lint happy */
- }
-
- struct command *get_command (name)
- char *name;
- {
- static char cmndbuf [BUFSIZ];
- static struct command command;
- int found = 0;
- char ch,
- *cmnd,
- *pc,
- *ptail,
- *pt;
- FILE *file;
-
- if ((file = fopen (COMMANDS, "r")) == NULL)
- error (ABORT, "cannot open %s for reading.", COMMANDS);
- command.name = name;
- while (fgets (cmndbuf, BUFSIZ, file) != NULL) {
- for (cmnd = cmndbuf; isspace (*cmnd); cmnd++);
- pt = command.path;
- ptail = cmnd;
- while (! (isspace (ch = *ptail) || (ch == ':') || (ch == 0))) {
- *pt++ = ch;
- ptail++;
- }
- *pt = 0;
- while (isspace (*ptail))
- ptail++;
- if (*ptail != ':') /* invalid entry */
- continue;
- pt = command.path;
- if ((pc = strrchr (pt, '/')) == NULL)
- pc = pt;
- else
- pc++;
- if (strcmp (name, pc) == 0) {
- ptail = nextitem (ptail+1, command.group);
- if ((found = check_group (command.group)))
- break;
- }
- }
- if (! found)
- error (ABORT, "access denied.");
- (void) fclose (file);
- ptail = nextitem (ptail, command.new_user);
- ptail = nextitem (ptail, command.new_group);
- return (&command);
- }
-
- char *nextitem (pstart, target)
- char *pstart,
- *target;
- {
- char ch,
- *ps = pstart,
- *pt = target;
-
- while (isspace (*ps)) ps++;
- if (*ps == 0) {
- *pt = 0;
- return (ps);
- }
- for (ch = *ps; (ch != ':') & (ch != 0); ch = *++ps)
- *pt++ = ch;
- *pt-- = 0;
- for (ch = *pt; isspace (ch); ch = *pt--)
- *pt = 0;
- if (*ps == 0)
- return (ps);
- else
- return (ps+1);
- }
-
- int check_group (groupname)
- char *groupname;
- {
- int found = 0;
- char **gr_list;
- struct group *group;
- struct passwd *passwd;
-
- if ((passwd = getpwuid (getuid ())) == NULL)
- error (ABORT, "cannot find passwd entry for userid %d.", getuid ());
- (void) strcpy (orguser, passwd->pw_name);
- if ((group = getgrnam (groupname)) != NULL)
- for (gr_list = group->gr_mem; *gr_list != NULL; gr_list++) {
- if ((found = (strcmp (orguser, *gr_list) == 0)))
- break;
- }
- return (found);
- }
-
- void set_ids (new_user, new_group)
- char *new_user,
- *new_group;
- {
- struct group *group;
- struct passwd *passwd;
-
- if (*new_group != 0) {
- /* not empty, must be set before uid is set */
- if ((group = getgrnam (new_group)) == NULL)
- error (ABORT, "cannot find group entry for groupid %s.", new_group);
- if (setgid (group->gr_gid) < 0)
- PERROR (ABORT);
- }
- if (*new_user != 0) { /* not empty */
- if ((passwd = getpwnam (new_user)) == NULL)
- error (ABORT, "cannot find passwd entry for userid %s.", new_user);
- if (setuid (passwd->pw_uid) < 0)
- PERROR (ABORT);
- } else if (setuid (getuid ()) < 0)
- PERROR (ABORT);
- }
-
- void exec_cmnd (command, argc, argv)
- struct command *command;
- int argc;
- char **argv;
- {
- unsigned cmnd_size = 0;
- int i,
- rslt;
- struct stat prstat;
- char
- *cmnd,
- *pa,
- *pc;
-
- set_env (command->name, command->group, command->new_user);
- cmnd_size = strlen (command->path)+32;
- for (i = 0; i < argc; i++)
- cmnd_size += strlen (argv [i])+1;
- pc = cmnd = malloc (cmnd_size+strlen (PROFILE));
- if ((stat (PROFILE, &prstat) == 0) && (prstat.st_mode & 0400)) {
- /* We must execute the profile */
- (void) sprintf (pc, ". %s;", PROFILE);
- pc += strlen (pc);
- }
- pa = command->path;
- while (*pa != 0)
- *pc++ = *pa++;
- *pc++ = ' ';
- while (argc-- > 0) {
- pa = *argv++;
- while (*pa != 0)
- *pc++ = *pa++;
- *pc++ = ' ';
- }
- *pc = 0; /* close string */
-
- if ((rslt = system (cmnd)) < 0)
- PERROR (ABORT);
- exit (rslt);
- }
-
- void set_env (name, group, new_user)
- char *name,
- *group,
- *new_user;
- {
- #define PUTENV(e) { if (putenv (e) < 0) PERROR (ABORT); }
- static char envbuf [512];
- char *penv = envbuf;
-
- PUTENV ("IFS= \t\n");
- PUTENV ("PATH=/");
- (void) sprintf (penv, "ORGUSER=%s", orguser);
- PUTENV (penv);
- penv += strlen (penv)+1;
- (void) sprintf (penv, "COMMAND=%s", name);
- PUTENV (penv);
- penv += strlen (penv)+1;
- (void) sprintf (penv, "GROUP=%s", group);
- PUTENV (penv);
- penv += strlen (penv)+1;
- if (*new_user == 0) {
- (void) sprintf (penv, "USER=%s", orguser);
- PUTENV (penv);
- penv += strlen (penv)+1;
- (void) sprintf (penv, "LOGNAME=%s", orguser);
- PUTENV (penv);
- } else {
- (void) sprintf (penv, "USER=%s", new_user);
- PUTENV (penv);
- penv += strlen (penv)+1;
- (void) sprintf (penv, "LOGNAME=%s", new_user);
- PUTENV (penv);
- }
- }
-
- void PERROR (why)
- int why;
- {
- perror (progname);
- if (why == ABORT)
- exit (1);
- }
-
- void usage_error ()
- {
- error (ABORT, "usage: %s command [ arguments ]", progname);
- }
-
- /* error - barf and quit */
-
- /* VARARGS1 */
-
- void error (why, fmt, va_alist)
- int why;
- register char *fmt;
- va_dcl
- {
- va_list s;
-
- va_start(s);
-
- (void) fprintf (stderr, "%s: ", progname);
- for (/* void */; *fmt; fmt++) {
- if (*fmt != '%') {
- (void) putc(*fmt,stderr);
- } else if (*++fmt == 's') {
- (void) fputs(va_arg(s,char *),stderr);
- } else if (*fmt == 'c') {
- (void) putc(va_arg(s,int),stderr);
- } else if (*fmt == 'u') {
- (void) fprintf(stderr,"%u",va_arg(s,unsigned));
- } else if (*fmt == 'd') {
- (void) fprintf(stderr,"%d",va_arg(s,int));
- }
- }
- va_end(s);
- (void) fprintf (stderr, "\n");
- if (why != WARN)
- exit (why);
- (void) fflush (stderr);
- }
-