[net.sources] sudo.c

gworek@sunybcs.UUCP (Don Gworek) (12/15/85)

We have a useful command called "sudo", which verifies a
user is allowed to execute a command as root, and keeps
records of sudo usage. 

/usr/local/adm/sudoers contains a list of superusers and
their sudo priveleges.  If a user is listed in sudoers, and
the user is permitted to execute a command, the command is
executed with root's ownership. 

Permissions in sudoers are either "all", a list of commands,
an enviornment PATH variable, or a PATH followed by a list
of commands.

A record of sudo usage is kept in sudo.log, and a record
of non-superuser attempts to sudo is kept in sudo.log.failures.

Sudo with no command to execute just shows your sudo permission.

Sudo must be installed setuid root.

-----------------------------CUT----------------------------------
# To unbundle, sh this file.  This archive contains:
# sudo.8 sudo.c

echo Extracting\: sudo.8
sed 's/^X//' >sudo.8 <<'E*O*F sudo.8'
X.\" @(#)sudo.8	1.4 (SUNYAB CS) 12/14/85
X.\" This document uses the troff(1) -man macros
X.TH SUDO 8 "14 December 1985" "" "Local UNIX Programmer's Manual"
X.SH NAME
Xsudo \- do a command as the superuser
X.SH SYNOPSIS
X.B sudo
X[
Xcommand
X]
X.SH DESCRIPTION
X.I Sudo
Xlooks for your username and your
X.I sudo
Xpermission in the file /usr/local/adm/sudoers.
XIf you are permitted, 
X.I sudo
Xexecutes
X.I command
Xas the superuser.
X.I Sudo
Xwith no command arguments just shows your 
X.I sudo
Xpermission.
X.PP
XIndividual entries in /usr/local/adm/sudoers are a username
Xfollowed by the user's 
X.I sudo
Xpermission, \-- either: "all"; a list of permitted commands; an
Xenviornment PATH variable; or a PATH followed by a list
Xof permitted commands.
X.PP
XFor readability, permission entries may span several lines
X\-- each line following the first line should start with
Xwhite space.  Comment lines are blank lines or lines
Xstarting with a "#".
X.PP
XAn example sudoers file is:
X.PP
X.br
X# comment
X.br
Xroot all
X.br
Xuser1 all
X.br
Xuser2 command1 command2
X.br
Xuser3 PATH=/workingdir1:/workingdir2
X.br
Xuser4 PATH=/workingdir1 command1 command2 command3
X.br
Xuser5 PATH=/workingdir1:/workingdir2
X.br
X	command1
X.br
X	command2
X.PP
X.SH NOTES
XA working directory for a 
X.I sudo
Xenviornment PATH could be /usr/local/restrict-bin.
X.PP
X.I Sudo csh
Xcan be used as a substitute for logging in as root.
X.PP
XWhen a user is restricted to commands or a PATH,
Xif any of those commands have shell escape,
Xthe user has access to 
X.I sudo
X"all".
X.SH FILES
X/usr/local/adm/sudoers \- list of superusers
X.br
X/usr/local/adm/sudo.log \- record of 
X.I sudo
Xusage
X.br
X/usr/local/adm/sudo.log.failures \- record of attempts to use 
X.I sudo
Xby non-superusers
X.SH SEE ALSO
Xsu(1)
X.SH AUTHORS
XPhil Betchel
X.br
XCliff Spencer
X.br
XGretchen Phillips
X.br
XJohn LoVerso
X.br
XDon Gworek
E*O*F sudo.8

ls -lg sudo.8

echo Extracting\: sudo.c
sed 's/^X//' >sudo.c <<'E*O*F sudo.c'
X#ifndef lint
Xstatic char *sccsid = "@(#)sudo.c	1.4 (SUNYAB CS) 12/14/85";
X#endif
X
X/*
X * sudo - run a command as superuser
X *
X * Usage: sudo [command]
X */
X
X#include <stdio.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/timeb.h>
X#include <utmp.h>
X#include <pwd.h>
X#include <ctype.h>
X
X#define SUDOFILE	"/usr/local/adm/sudoers"
X#define	LOGFILE		"/usr/local/adm/sudo.log"
X#define	BLOGFILE	"/usr/local/adm/sudo.log.failures"
X
X#define TRUE 1
X#define FALSE 0
X
Xchar    buf[BUFSIZ];
Xchar   *bufp = buf;
Xchar   *index (), *malloc ();
X
Xstruct passwd  *pw, *getpwuid ();
X
Xmain (argc, argv, envp)
Xint     argc;
Xchar   *argv[], *envp[];
X{
X    char   *name, bufcmd[BUFSIZ], *origpath;
X    int found;
X    pw = getpwuid (getuid ());
X    name = pw -> pw_name;
X    if (setuid (0) == -1) {
X	perror (*argv);
X	exit (1);
X    }
X    argc--, argv++;
X    found = lookup (name);
X    if (argc == 0) {
X	if (*buf)
X	    printf ("%s\n", buf);	/* echo permissions, if any */
X	exit (0);
X    }
X    if (!found) {			/* not sudo permitted */
X	enterlog (BLOGFILE, name, argc, argv);
X	fprintf (stderr, "Nope.\n");
X	exit (1);
X    }
X    enterlog (LOGFILE, name, argc, argv);
X    bufp = index (bufp, ' ');
X    (void) sscanf (bufp, "%s", bufcmd);
X    if (strcmp (bufcmd, "all")) {
X	if (!strncmp (bufcmd, "PATH", 4) && index (bufcmd, '=')) {
X	    origpath = envp[2];
X	    envp[2] = bufcmd;
X	    execvp (*argv, argv);	/* return when cmd not in PATH*/
X	    envp[2] = origpath;
X	}
X	if (!inlist (argv)) {
X	    enterlog (BLOGFILE, name, argc, argv);
X	    fprintf (stderr, "Nope, you're not allowed to do that\n");
X	    exit (1);
X	}
X    }
X    execvp (*argv, argv);
X    enterlog (BLOGFILE, name, argc, argv);
X    printf ("%s: Command not found\n", *argv);
X    exit (1);
X}
X
Xlookup (name)
Xchar   *name;
X{
X    register int    namelen;
X    register    FILE * fp;
X    namelen = strlen (name);
X    if ((fp = fopen (SUDOFILE, "r")) == 0) {
X	perror (SUDOFILE);
X	exit (1);
X    }
X    while (getbuf (buf, BUFSIZ, fp) > 0) {
X	if (!strncmp (buf, name, namelen)) {
X	    (void) fclose (fp);
X	    return (TRUE);
X	}
X    }
X    (void) fclose (fp);
X    return (FALSE);
X}
X
Xgetbuf (buffer, buflim, fp)
Xchar   *buffer;
Xint     buflim;
XFILE * fp;
X{
X    char    ch, eof=EOF;
X    int     buflen = 0;
X    while (buflen < buflim && ((ch = getc (fp)) != eof))
X	if ((ch == '\n') && buflen && (!isspace (ungetc (getc (fp), fp)))) {
X		*buffer = '\0';
X		return (buflen);
X	}
X	else {
X	    if (isspace (ch))
X		ch = ' ';
X	    buflen++;
X	    *buffer++ = ch;
X	}
X    *buffer = '\0';
X    return (buflen);
X}
X
Xinlist (cmd)
Xchar  **cmd;
X{
X    int     cmdlen;
X    char    bcmd[BUFSIZ];
X    cmdlen = strlen (*cmd);
X    while (bufp = index (bufp, ' ')) {
X	(void) sscanf (++bufp, "%s", bcmd);
X	if (!strncmp (bcmd, *cmd, cmdlen)) {
X	    if (bufp = index (bufp, '='))
X		(void) sscanf (++bufp, "%s", *cmd); 	/* substitute a path */
X	    return (TRUE);
X	}
X    }
X    return (FALSE);
X}
X
Xenterlog (logfile, name, argc, argv)
Xchar   *logfile, *name;
Xint     argc;
Xchar  **argv;
X{
X    char   *s;
X    time_t  now;
X    FILE * fp;
X    now = time ((time_t *) 0);
X    fp = fopen (logfile, "a");
X    s = (char *) ctime (&now);
X    fprintf (fp, "%-18.20s: %10s: ", s, name);
X    while (argc--)
X	fprintf (fp, "%s ", *argv++);
X    fprintf (fp, "\n");
X    (void) fclose (fp);
X}
E*O*F sudo.c

ls -lg sudo.c
exit 0