asroot: a program that gives you root permissions for a single command

490 views
Skip to first unread message

Kevin Szabo

unread,
Dec 6, 1985, 12:25:55 PM12/6/85
to
Some time ago there was discussion about the single user
systems and the problems of running as ROOT most of the
time. In a single user system you can easily become root
(via SU) but it is dangerous to always run as ROOT since you can
clobber yourself. Unfortunately SU tends to be quite slow for
those times when you only want to execute a single command.

Thus I have written a small command called 'asroot' which will
momentarily give a process root permissions. The use of the
command is:

$ asroot cmd arg1 arg2 ...

or you can type

$ asroot

and 'asroot' will prompt you for command line.

I use 'asroot' frequently on my systemIII machine; it
should run correctly on other version of UNIX as well.

PLEASE NOTE THAT THIS PROGRAM IS A MASSIVE SECURITY HOLE.
YOU SHOULD NOT ALLOW IT TO EXIST ON A MULTI-USER SYSTEM,
OR ONE WHICH MAY BE ACCESSED REMOTELY.

So here's the program. It's too small for a shar file...


#include <stdio.h>

/*
* Asroot - execute a command with root permissions.
* compile with 'cc -o asroot asroot.c'
* then 'chown root asroot; chmod u+s asroot'.
*
* This program is a convenience for single-user systems,
* BUT it is a MASSIVE security hole. Please use caution.
*/

main( argc, argv )
int argc;
char **argv;
{
extern char *gets();
int retcode;

char string[260];

setuid( geteuid() );

if ( argc > 1 ) {
execvp( argv[1], &argv[1] );
fprintf( stderr,"%s: execution of '%s' failed: ", argv[0], argv[1] );
perror( "" );
exit( 1 );
} else {
printf("Enter string to be executed: ");
fflush( stdout );
retcode=system( gets( string ) );
if ( retcode != 0 )
fprintf(stderr,"%s: the command '%s' exited with status %d\n", argv[0], string, retcode );
exit( retcode );
}
}
--
Kevin Szabo' watmath!watvlsi!ksbszabo (U of W VLSI Group, Waterloo, Ont, Canada)

Karl Kleinpaste

unread,
Dec 8, 1985, 6:58:35 AM12/8/85
to
In article <28...@watvlsi.UUCP> ksbs...@watvlsi.UUCP (Kevin Szabo) writes:
>Thus I have written a small command called 'asroot' which will
>momentarily give a process root permissions.

Here's an alternative to `asroot.' This is a small program which does
nothing more than exec a shell (typically csh, for me) with exactly
those arguments with which it was called. I have this on multi-user
systems, but it lives in a private bin directory with mode 700, so no
one but me can get at it unless they're already root or me.

Typical usage is
% enable
which gives me a plain root shell, or
% enable -fc 'some random single command to be executed'

/* THIS PROGRAM MUST HAVE 04750 PERMISSIONS, AND BE OWNED BY */
/* USER ROOT AND THAT GROUP WHICH IS TO BE ALLOWED TO USE IT. */

main (argc, argv)
int argc;
char *argv[];
{
setgid (5);
setuid (0);
/* nice (-4); de-comment only if you want to be rude/nasty */
execv ("/bin/csh", argv);
}

--
Karl Kleinpaste

Clifford Spencer

unread,
Dec 9, 1985, 4:39:21 PM12/9/85
to
> >momentarily give a process root permissions.
> Here's an alternative to `asroot.' This is a small program which does
Okay I'll bite, here's my `sudo' program that tries to maintain
some control over who runs it.
% sudo command
runs that command as root.bin

# This is a shell archive. Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file". (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# sudo.c Makefile sudo.8

echo x - sudo.c
sed -e 's/^X//' > "sudo.c" << '//E*O*F sudo.c//'
X#ifndef lint
Xstatic char rcsid[]="$Header: sudo.c,v 1.3 85/11/09 16:07:18 cspencer Exp $";
X#endif lint
X/*
X * sudo - run a command as su.
X * to compile:
X * cc -O sudo.c -o sudo.c; /etc/chown root sudo; chmod u+s sudo
X */
X#include <stdio.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <pwd.h>
X
Xchar *userfile = "/usr/adm/sudo.users";
X/* define LOGFILE to log all commands run as sudo - some find this offensive */
X#define LOGFILE "/usr/adm/sudo.log"
X
Xchar *progname;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char *checkname();
X char *username;
X int uid;
X
X progname = argv[0];
X
X if(argc < 2) {
X fprintf(stderr, "usage: %s cmd\n", progname);
X exit(-1);
X }
X
X /* remember who this user really is */
X uid = getuid();
X
X if((setuid(0)) < 0)
X eperror("setuid");
X
X if((setgid(3)) < 0)
X eperror("setgid");
X
X if (( username = checkname(uid)) == NULL)
X exit(1);
X argv++, argc--;
X#ifdef LOGFILE
X log(username, argc, argv);
X#endif LOGFILE
X execvp(*argv, argv);
X eperror(*argv);
X}
X
X/*
X * look for a user in USERFILE - check perms and modes of USERFILE
X */
Xlookup(name)
Xchar *name;
X{
X register FILE *fp;
X char buf[BUFSIZ];
X struct stat statb;
X
X if (stat(userfile, &statb))
X eperror(userfile);
X
X if (statb.st_uid != 0)
X errexit("%s must be owned by root\n", userfile);
X
X if (statb.st_mode & 022) /* should be og-w */
X errexit("bad modes on %s\n", userfile);
X
X if ((fp = fopen(userfile,"r")) == 0 )
X eperror(userfile);
X
X while ((fscanf(fp,"%s",buf)) != EOF)
X if(buf[0] == '#') /* munch comments */
X fgets(buf,BUFSIZ,fp);
X else if((strncmp(buf,name,strlen(name))) == 0) {
X return 1;
X break;
X }
X return 0;
X}
X
X
X/*
X * get this user's name and check if that name list of permitted users
X */
Xchar *
Xcheckname(uid)
Xregister int uid;
X{
X struct passwd *pw;
X
X if ((pw = getpwuid(uid)) == NULL)
X return NULL;
X if(lookup(pw->pw_name) == 0) {
X fprintf(stderr,"nope\n");
X return NULL;
X }
X return pw->pw_name;
X}
X
X#ifdef LOGFILE
X/*
X * log this command in the log file
X */
Xlog(username, argc, argv)
Xchar *username;
Xint argc;
Xchar **argv;
X{
X register FILE *fp;
X long now;
X char *ctime();
X
X time(&now);
X fp = fopen(LOGFILE,"a");
X if (fp == NULL)
X errexit("can't open %s.\n", LOGFILE);
X
X fprintf (fp, "%20.20s ", ctime(&now));
X
X fprintf (fp,"%s: ",username);
X while (argc--)
X fprintf (fp,"%s ",*argv++);
X fprintf (fp,"\n");
X fclose (fp);
X return 0;
X}
X#endif LOGFILE
X
Xeperror(s)
Xregister char *s;
X{
X fprintf(stderr,"%s: ",progname);
X perror(s);
X exit(-1);
X}
X
Xerrexit(fmt, arg)
Xregister char *fmt, *arg;
X{
X fprintf(stderr,"%s: ", progname);
X fprintf(stderr, fmt, arg);
X exit(-1);
X}
//E*O*F sudo.c//

echo x - Makefile
sed -e 's/^X//' > "Makefile" << '//E*O*F Makefile//'
XCFLAGS=-O
XLIBES=
XDESTDIR=/u1/cspencer
XINSTALL=/usr/bin/install
X
Xall: sudo
X
Xinstall all.install: sudo.install
X
Xsudo.install: sudo
X ${INSTALL} -m 4755 -o root sudo ${DESTDIR}
X
Xsudo: sudo.o
X cc ${CFLAGS} sudo.o -o sudo ${LIBES}
Xclean:
X -rm -f sudo.o make.out sudo
//E*O*F Makefile//

echo x - sudo.8
sed -e 's/^X//' > "sudo.8" << '//E*O*F sudo.8//'
X.TH SUDO 8
X.SH NAME
Xsudo \- do a super thing
X.SH SYNOPSIS
X.B sudo
Xcommand
X.SH DESCRIPTION
X.I Sudo
Xallows a permitted user to execute a command as root.
X.I Sudo
Xdetermines who is an authorized user by consulting the file
X.I sudo.users.
XIf a match is found
X.I command
Xis executed with uid 0 and gid 3.
XLines in
X.I sudo.users
Xbeginning with a
X.I '#'
Xare considered comments and are ignored.
X.SH DIAGNOSTICS
X.I Sudo
Xwill complain and exit if
X.I sudo.users
Xis not owned by root or if it is writeable by anyone other than root.
X.SH BUGS
XShell builtins such as
X.I 'cd'
Xwill fail.
X.SH FILES
X.nf
X/usr/adm/sudo.users list of authorized users
X.br
X/usr/adm/sudo.log record of all invocations of sudo
X.fi
X.SH SEE ALSO
Xsu(1)
//E*O*F sudo.8//

exit 0
--
cliff spencer {harvard, ihnp4, decvax}!bbnccv!cspencer cspe...@bbncc5.arpa

Paul Summers

unread,
Dec 10, 1985, 1:51:53 PM12/10/85
to
With the rash of un-secure programs that turn the average user into
root without the courtesy of using su, I felt that I should post a
program that we have been using fairly successfully here at wjvax.
The main difference between this program and 'asroot' and its spiritual
bretheren is that it keeps a copy of the encrypted root password,
and prompts for it before letting the casual terminal snatcher get
away with murder or worse.

I make no guarantees about portability (we're running bsd 4.2) or
security. The main point that I am stressing is the password. A little time
is sacrificed to make sure that only super user privilidged people can use
this program.
(I know of a particular system that has 'chown' set userid root...)

The main idea is to save time.
Have any of you tried the '-f' option on su?

---------------------cut here-------------------------------------
/*
* force.c: execute $* as user root.
*
* A relatively secure program that executes its arguments
* as the super user. A small speed sacrifice is made to prompt
* for a password. Install the program with mode 4750, owner
* root, group root (or operator).
*
* Written by: Paul M. Summers (wjvax!paul)
* 10/85
*
* Compile: cc -o /usr/local/bin/force force.c
* chmod 4750 /usr/local/bin/force
*/
#include <pwd.h>
/*
* Modify the next 2 lines as appropriate.
*/
#define SA "System Administrator's name"
#define ROOTPW "Encrypted root password from /etc/passwd"

main(argc,argv)
int argc;
char *argv[];
{
char *pwd,*cpwd,*crypt(),*getpass(),salt[2];
struct passwd *getpwuid(),*pwdent;

pwd = getpass("Password: ");

strncpy(salt,ROOTPW,2);
cpwd = crypt(pwd,salt);

if (strcmp(ROOTPW,cpwd) == 0) {
setuid(0);
/* nice(-5); /* Overdrive... */
execvp(argv[1],&argv[1]);
printf("%s: command not found\n",argv[1]);
exit(1);
}

/*
* Check for changed root password.
*/

setpwent();
pwdent = getpwuid(0);

if (strcmp(pwdent->pw_passwd,ROOTPW) != 0) {
printf("Root password has changed to %s\n",pwdent->pw_passwd);
printf("Notify %s that force must be changed\n",SA);
}
else
printf("Bad password.\n");
}

Paul Hubbard

unread,
Dec 13, 1985, 11:33:34 AM12/13/85
to
---------

Several people have requested my modified ttype source, so here it is.


--------8<-----------8<------------8<-------------8<------------8<--------
/*
* ttype By Chris Bertin, 1983
* Modified by Paul Hubbard, 1985
*
* Description: TTYPE allows you to practice terminal or typewriter
* typing. TTYPE is self-explanatory if you request
* instructions.
*
* Compilation: cc -o ttype ttype.c -lcurses -ltermlib
*
* Invocation: ttype
*/

static char cpright[] = "(C) Chris Bertin, 1983";
static char cpleft[] = "Paul Hubbard, 1985";

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <curses.h>

#define WORDLIST "/usr/dict/words"
#define LFCR "\n\r"
#define CHAR 0 /* answer types */
#define NUM 1 /* ... */
#define PRACTICE 0 /* run types */
#define DICT 1 /* ... */
#define FILEIN 2 /* ... */
#define MAX 128 /* std array size as well as max ASCII */
#define SPEED 0 /* screen locations */
#define SCORE 2 /* ... */
#define TYPE LINES -12 /* ... */
#define ASK LINES - 3 /* ... */
#define BOTTOM LINES - 2 /* ... */
#define ALLCHARS "&*()_+|\\{}:\"~<>?-=[];'`,./!#$%^ ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 abcdefghijklmnopqrstuvwxyz"

#define moveto(x,y,str) if(CA)move(x,y),clrtoeol();else pr(0,str);
#define dorefresh() if(CA){clearok(stdscr,TRUE);refresh();clearok(stdscr,FALSE);}
#define sethelp() wclear(helpscr);wrefresh(helpscr);moveto(TYPE,0,LFCR);

char what_chars[MAX*2]; /* the characters to practice on */
char try_str[MAX*2]; /* the string to be retyped */
char typed_str[MAX*2]; /* the chars being typed by the user */
char work_str[MAX*2]; /* work space (temp string) */
char badchar[MAX]; /* errors; the mistyped chars are pointers into them */
char gbadchar[MAX]; /* same but session total */
int xcoor,ycoor; /* temp coordinates */
int isafastscreen; /* is a fast screen? */
int trials; /* number of trials */
int npractice; /* number of characters to practice on (practice opt.)*/
char lasterr[500]; /* last error, the next string will start with it */
int err_num; /* last error pointer */
int linerrors, toterrors, gtoterrors; /* errors per line / run / session */
float totlngth, gtotlngth; /* chars typed per run / session */
float tottime, gtottime; /* time spent per run / session */

struct timeb tb, ta;
struct stat sbuf;
FILE *fp, *dictfp, *fopen();
WINDOW *helpscr, *subwin();

main()
{
register option, screenloc, lngth, more = 1;
int out_size, nwords, instruct;
char fname[MAX];
float chkstr();

setbuf(stdin, (char *)NULL);
ftime(&ta);
srandom(getpid() + ta.millitm - getuid()); /* should be unique... */
initscr();
scrollok(stdscr, FALSE);
(void) signal(SIGFPE, SIG_IGN);
if(CA) /* Do we have cursor control?? */
isafastscreen = highspeed();
else
pr(1, "[No cursor addressing, using hard copy mode]\n");
raw(), noecho();
moveto(TYPE - 6, 0, "");
pr(2, "\t\t\tP R A C T I C E T Y P I N G");
pr(2, "\t\t\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
if(instruct = answer(work_str, "Instructions? (y or n)", CHAR) == 1)
helpscr = subwin(stdscr, 9, COLS, TYPE, 0);
gtoterrors = gtotlngth = gtottime = 0.;
zero(gbadchar, sizeof gbadchar);
while(more) {
screenloc = TYPE;
if(instruct)
help1();
(void) answer(work_str, "What text type do you want?", CHAR);
if(! strcmp(work_str, "words")) {
option = DICT;
if(dictfp == NULL) /* don't redo it */
if(((stat(WORDLIST, &sbuf)) < 0) ||
((dictfp = fopen(WORDLIST,"r")) == NULL)){
note("Can't open %s", WORDLIST);
continue;
}
if(instruct)
help3();
nwords = answer(work_str,
"How many words in each line?", NUM);
if(nwords > COLS/11)
note("Set to maximum allowed (%d)",
(nwords = COLS/11));
}
else if(! strcmp(work_str, "file")) {
option = FILEIN;
if(instruct)
help2();
(void) answer(fname, "Enter file name:", CHAR);
if(! *fname)
continue;
if((fp = fopen(fname, "r")) == NULL) {
note("Can't open %s", fname);
continue;
}
}
else {
option = PRACTICE;
strcpy(what_chars, work_str[0] ? work_str : ALLCHARS);
npractice = strlen(what_chars);
if(instruct)
help4();
out_size = answer(work_str,
"How many characters in each string?", NUM);
}
if(option != FILEIN) {
if(instruct)
help5();
trials = answer(work_str, "How many trials?", NUM);
}
if(instruct)
help7();
zero(badchar, sizeof badchar);
err_num = toterrors = 0;
totlngth = tottime = 0.;
if(CA)
clear();
moveto(SCORE, 0, LFCR);
pr(2, "\tNext line: ^C, Quit: ^D, Redraw: ^L");
while(makestr(option, out_size, nwords) >= 0) {
ioctl(0, TIOCFLUSH, 0);
if(CA)
note("", "");
if((lngth = chkstr(screenloc)) == 0)
continue;
totlngth += lngth;
toterrors += linerrors;
if(isafastscreen)
score(badchar, toterrors, totlngth, tottime);
if((screenloc += 3) > (ASK - 2))
screenloc = TYPE;
}
gtotlngth += totlngth;
gtoterrors += toterrors;
if( ! CA || ! isafastscreen)
score(badchar, toterrors, totlngth, tottime);
more = answer(work_str, "Try again?", CHAR);
}
leave();
}

answer(str, msg, type)
register char *str;
char *msg;
{
register c, i, ret = 0;

for(;;) {
moveto(ASK, 10, "\n\r> ");
pr(1, "%s: ", msg);
for(i=0; ((c = getch()) != '\n' && c != '\r') ;)
switch(c) {
case '\f':
dorefresh();
break;
case '\10':
if(i>0)
--i, pr(1, "\010 \010");
break;
case '\04':
case '\03':
case 0177:
leave();
default:
pr(1, "%c", (str[i++] = noctrl(c)));
}
if(CA)
note("", "");
while(str[--i] == ' ') ;
str[++i] = 0;
if(type == CHAR)
if(*str == 'y')
return(1);
else
return(0);
if((ret = atoi(str)) <= 0) {
note("Numeric value (> 0) required", "");
continue;
}
return(ret);
}
}

makestr(opt, lng, n_of_wrds) /* builds the string to be typed */
{
register ind;

if(opt != FILEIN && trials <= 0)
return(-1);
zero(try_str, sizeof try_str);
switch(opt) {
case FILEIN:
if(fgets(try_str, sizeof try_str, fp) == NULL)
return(fclose(fp));
fixstr(try_str);
return(1);
case DICT:
for(ind = 0; ind < n_of_wrds ; ++ind, strcat(try_str, " ")) {
if(fseek(dictfp, random()%(long)sbuf.st_size, 0) == -1)
strcpy(work_str, "fseek failed!!!");
fgets(work_str, sizeof work_str, dictfp);
if(fgets(work_str, sizeof work_str, dictfp) == NULL)
strcpy(work_str, "End of file!!!");
work_str[strlen(work_str) - 1] = 0;
strcat(try_str, work_str);
}
return(--trials);
case PRACTICE:
for(ind = 0 ; ind < lng ; ++ind)
try_str[ind] = what_chars[(int)random() % npractice];
try_str[0] = (lasterr[err_num] ? lasterr[err_num] : try_str[0]);
err_num = 0;
return(--trials);
}
/* NOTREACHED */
}

fixstr(str)
char *str;
{
register char *in, *out;
short space = 0;

for(in = str ; isspace(*in) ; ++in) ;
for(out = str ; *in ; ++in) {
if(*in == '\010') {
if(out > str)
out--;
continue;
}
if(isspace(*in) && space)
continue;
space = isspace(*in);
*out++ = noctrl(*in);
}
*out = 0;
}

float
chkstr(location) /* checks the typing */
{
register ind, c = 0;
register char *typed_pnt;
register float n_of_chars;
float f, elapsed, starttime, gettime();

zero(typed_str, sizeof typed_str);
typed_pnt = typed_str;
if(strlen(try_str) >= COLS-1) {
note("Line too long, truncated", "");
try_str[COLS-1] = 0;
}
if((n_of_chars = (float) putline(try_str, location)) == 0.)
return(0.);
moveto(location+1, 0, LFCR);
refresh();
for(linerrors = ind = 0; ind < n_of_chars ; ++ind) {
switch(c = getch()) {
case '\n':
case '\r':
--ind;
break;
case 0177:
case '\b':
getyx(stdscr,ycoor,xcoor);
move(ycoor,xcoor-1);
delch();
if (lasterr[err_num-1] == try_str[ind-1])
{
--linerrors;
--badchar[lasterr[err_num-1]];
--gbadchar[lasterr[err_num-1]];
--err_num;
}
clrtoeol();
refresh();
ind -= 2;
break;
case '\f':
dorefresh();
--ind;
break;
case '\03':
if((n_of_chars = ind) == 0) /* force out */
return(0.);
break;
case '\04':
gtotlngth += totlngth + ind;
gtoterrors += toterrors + linerrors;
leave();
default: /* a character... */
if(ind == 0)
starttime = gettime(0, "");
if(c != try_str[ind]) { /* error */
pr(0, "%c", ch_case(c, try_str[ind]));
warnerror(location+1, ind+1);
lasterr[err_num] = try_str[ind];
++err_num;
++linerrors;
++badchar[lasterr[err_num-1]];
++gbadchar[lasterr[err_num-1]];
}
else {
pr(0, "%c", noctrl(c));
clrtoeol();
}
refresh();
break;
}
}
*typed_pnt = 0;
standend();
clrtoeol();
elapsed = gettime(12, "/ ") - starttime;
tottime += elapsed;
gtottime += elapsed;
moveto(SPEED, COLS-40, LFCR);
standout();
if(! CA)
printf("\t\t\t\t");
pr(2, "%.1f secs, %d error(s), %.2f w/min", elapsed, linerrors,
(f=((n_of_chars / 5.) - linerrors) / (elapsed / 60.))>0.?f:0.0);
standend();
refresh();
return(n_of_chars);
}

float
gettime(where, str)
register char *str;
{
struct tm *localtime();
register struct tm *tm;
register x, y;

ftime(&tb);
if(isafastscreen) {
tm = localtime(&tb.time);
getyx(stdscr, y, x);
move(SPEED, where);
pr(1, "%s%02d:%02d:%02d.%02d", str, tm->tm_hour, tm->tm_min,
tm->tm_sec, (tb.millitm / 10));
clrtoeol();
move(y, x);
refresh();
}
return((float) (tb.time - ta.time) + ((float)tb.millitm / 1000.));
}

putline(outstr, where)
register char *outstr;
{
register n;
char *rindex();
register char *back = rindex(outstr, '\0') - 1;

while(isspace(*back))
*back-- = 0;
moveto(where, 0, "\r");
for(n = 0 ; *outstr ; ++n)
pr(0, "%c", noctrl(*outstr++));
if(n)
refresh();
return(n);
}

warnerror(x, y)
{
if(! isafastscreen || y > COLS-15) {
putchar('\07');
return;
}
clrtoeol();
move(x, y+3);
standout();
pr(0, " Error");
standend();
move(x, y);
refresh();
}

/* NOSTRICT */
/* VARARGS */
note(str1, str2)
char *str1;
long str2;
{
moveto(BOTTOM+1, COLS-40, LFCR);
clrtoeol();
standout();
pr(2, str1, str2);
standend();
}

ch_case(bad, good) /* converts to upper or lower case */
{
register ret;

if(isupper(bad))
return((good - (ret=tolower(bad))) ? ret : bad);
if(islower(bad))
return((good - (ret=toupper(bad))) ? ret : bad);
return(noctrl(bad));
}

noctrl(ch)
register ch;
{
if(ch == '\t')
return(' ');
return(iscntrl(ch) ? (ch - '\01' + 'A') : ch);
}

score(errstr, err, lng, ttime) /* prints the score */
char *errstr;
register float lng, ttime;
{
register s, i, n=0;
float f;

if(lng == 0.)
return;
moveto(SCORE, 0, "\n\n\r");
s = (lng - (float) err) * 100. / lng;
pr(0,"%d errors on %.0f characters (%d %% error), ", err, lng, (100-s));
pr(1, "average speed: %.2f words/minute",
((f = ((lng / 5.) - err) / (ttime / 60.)) >0. ? f : 0.), err);
if(err) {
moveto(SCORE + 2, 0, LFCR);
for(n = i = 0 ; i < MAX ; ++i)
if(errstr[i] != 0) {
pr(0, "%4d errors on '%c'", errstr[i], i);
if(++n > 3) {
n = 0;
pr(1, LFCR);
}
}
pr(1, LFCR);
}
return;
}

/* NOSTRICT */
/* VARARGS */
pr(mode, fmt, str1, str2, str3, str4, str5) /* mode 2: add LFCR, 1: refresh() */
char *fmt;
long str1, str2, str3, str4, str5;
{
if( CA) {
printw(fmt, str1, str2, str3, str4, str5);
if(mode == 2)
printw(LFCR);
if(mode > 0)
refresh();
}
else {
printf(fmt, str1, str2, str3, str4, str5);
if(mode == 2)
printf(LFCR);
fflush(stdout);
}
}

highspeed() /*return 1 if 1200 baud or more */
{
struct sgttyb mod;

gtty(0, &mod);
if(mod.sg_ispeed >= B1200)
return(1);
move(ASK, 10);
pr(1, "[Using slow terminal mode]");
return(0);
}

help1()
{
sethelp();
pr(2,"\tIf you hit <RETURN>, the system will give you a random string");
pr(2,"\tof characters to practice on. If you want to limit the range");
pr(2,"\tof characters, enter a character list. To practice on random");
pr(2,"\twords from the dictionary type 'words'. To practice on the");
pr(2,"\ttext in a file, type 'file'.");
}

help2()
{
sethelp();
pr(2, "\tThe system will print one by one all the lines from the file");
pr(2, "\tand wait for you to retype them. If the file is not in the");
pr(2, "\tcurrent directory, enter the full path name (Ex:/home/test).");
pr(2, "\tNote: trailing spaces and tabs are truncated, tabs in the");
pr(2, "\tlines are replaced with spaces and empty lines are skipped.");
}

help3()
{
sethelp();
pr(2, "\tThe program will pick random words from the dictionary.");
pr(2, "\tEnter the number of words you want the system to give you");
pr(2, "\ton each line. (More words produce a more accurate speed");
pr(2, "\trating.)");
}

help4()
{
sethelp();
pr(2, "\tThe program will make strings of characters for you to");
pr(2, "\tenter. Enter the length of string. (More letters produce");
pr(2, "\ta more accurate speed rating.)");
}

help5()
{
sethelp();
pr(2, "\tHow many lines do you want the system to give you in this");
pr(2, "\tsession?");
}

help6()
{
sethelp();
pr(2,"\t Do you want to see the characters you are typing as you type");
pr(2,"\tthem? If you type 'no', only the errors will be printed.");
}

help7()
{
sethelp();
pr(2, "\tMiscellaneous Notes: <RETURN> and <LINE-FEED> are ignored.");
pr(2, "\tEach error subtracts one word from the speed. You can use ");
pr(2, "\tbackspaces to recover from errors.");
if(CA)
(void) answer(work_str, "Hit <RETURN> to continue", CHAR);
}

leave()
{
if(gtotlngth) {
moveto(SPEED, 0, LFCR);
pr(2, "\t\t\tS E S S I O N T O T A L");
score(gbadchar, gtoterrors, gtotlngth, gtottime);
}
clrtobot();
moveto(BOTTOM, 0, LFCR);
refresh();
endwin();
exit(0);
}

zero(str, n)
register char *str;
register n;
{
while(n--)
*str++ = 0;
}

Thomas Scott Christiansen

unread,
Dec 14, 1985, 10:19:18 AM12/14/85
to
isn't this the same as saying:

su -f root -c "some commands here"

why reinvent the wheel? plus this doens't have to be recompiled when
there is a new root passwd.

i find that most unix programs get written again and again and again,
when the one you wanted was already there in the first place.

tom
--

Tom Christiansen
University of Wisconsin
Computer Science Systems Lab
...!{allegra,heurikon,ihnp4,seismo,uwm-evax}!uwvax!tom
t...@wisc-crys.arpa

Don Gworek

unread,
Dec 14, 1985, 11:59:30 PM12/14/85
to
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

Reply all
Reply to author
Forward
0 new messages