used indent to "fix" coding style

This commit is contained in:
Todd C. Miller
1993-10-04 19:10:33 +00:00
parent 847ce91e0f
commit e75a6d3b54
7 changed files with 1030 additions and 979 deletions

191
check.c
View File

@@ -65,38 +65,38 @@ static int timedir_is_good;
void check_user() void check_user()
{ {
register int rtn; register int rtn;
umask ( 077 ); /* make sure the timestamp files are private */ umask(077); /* make sure the timestamp files are private */
if ( setuid (0) ) { /* have to be root to see timestamps */ if (setuid(0)) { /* have to be root to see timestamps */
perror("setuid(0)"); perror("setuid(0)");
exit(1); exit(1);
} }
rtn = check_timestamp(); rtn = check_timestamp();
if ( setruid (uid) ) { /* don't want to be root longer than necessary */ if (setruid(uid)) { /* don't want to be root longer than
* necessary */
#ifndef _AIX #ifndef _AIX
perror("setruid(uid)"); perror("setruid(uid)");
exit(1); exit(1);
#endif #endif
} }
if (rtn && uid) /* if timestamp is not current... */
if ( rtn && uid ) /* if timestamp is not current... */
check_passwd(); check_passwd();
if ( setuid (0) ) { /* have to be root to play with timestamps */ if (setuid(0)) { /* have to be root to play with timestamps */
perror("setuid(0)"); perror("setuid(0)");
exit(1); exit(1);
} }
update_timestamp(); update_timestamp();
if ( setruid (uid) ) { /* don't want to be root longer than necessary */ if (setruid(uid)) { /* don't want to be root longer than
* necessary */
#ifndef _AIX #ifndef _AIX
perror("setruid(uid)"); perror("setruid(uid)");
exit(1); exit(1);
#endif #endif
} }
umask(022); /* want a real umask to exec() the command */
umask ( 022 ); /* want a real umask to exec() the command */
} }
@@ -113,69 +113,67 @@ umask ( 022 ); /* want a real umask to exec() the command */
static int check_timestamp() static int check_timestamp()
{ {
static char timestampfile[MAXPATHLEN+1]; static char timestampfile[MAXPATHLEN + 1];
register char *p; register char *p;
struct stat statbuf; struct stat statbuf;
register int timestamp_is_old = -1; register int timestamp_is_old = -1;
time_t now; time_t now;
(void) sprintf(timestampfile, "%s/%s", TIMEDIR, user);
timestampfile_p = timestampfile;
timedir_is_good = 1; /* now there's an assumption for ya... */
sprintf ( timestampfile, "%s/%s", TIMEDIR, user ); /*
timestampfile_p = timestampfile; * walk through the path one directory at a time
*/
timedir_is_good = 1; /* now there's an assumption for ya... */ for (p = timestampfile + 1; p = index(p, '/'); *p++ = '/') {
*p = '\0';
if (stat(timestampfile, &statbuf) < 0) {
/* walk through the path one directory at a time */ if (strcmp(timestampfile, TIMEDIR))
(void) fprintf(stderr, "Cannot stat() %s\n", timestampfile);
for ( p=timestampfile+1; p=index(p,'/'); *p++='/' ) {
*p='\0';
if ( stat(timestampfile,&statbuf) < 0) {
if ( strcmp ( timestampfile, TIMEDIR ))
fprintf ( stderr, "Cannot stat() %s\n", timestampfile );
timedir_is_good = 0; timedir_is_good = 0;
*p='/'; *p = '/';
break; break;
} }
} }
/*
if ( timedir_is_good ) { /* if all the directories are stat()able */ * if all the directories are stat()able
if ( stat(timestampfile, &statbuf) ) { /* does the file exist? */ */
if ( uid ) reminder(); /* if not, do the reminder */ if (timedir_is_good) {
timestamp_is_old=1; /* and return (1) */ if (stat(timestampfile, &statbuf)) { /* does the file exist? */
} if (uid)
else { /* otherwise, check the time */ reminder(); /* if not, do the reminder */
now = time ( (time_t *) NULL ); timestamp_is_old = 1; /* and return (1) */
if ( now - statbuf.st_mtime < 60 * TIMEOUT ) } else { /* otherwise, check the time */
now = time((time_t *) NULL);
if (now - statbuf.st_mtime < 60 * TIMEOUT)
timestamp_is_old = 0; /* if file is recent, return(0) */ timestamp_is_old = 0; /* if file is recent, return(0) */
else else
timestamp_is_old = 1; /* else make 'em enter password */ timestamp_is_old = 1; /* else make 'em enter password */
} }
} }
/*
/* there was a problem stat()ing a directory */ * there was a problem stat()ing a directory
*/
else { else {
timestamp_is_old = 1; /* user has to enter password */ timestamp_is_old = 1; /* user has to enter password */
if ( mkdir (TIMEDIR, 0700 ) ) { /* make the TIMEDIR directory */ if (mkdir(TIMEDIR, 0700)) { /* make the TIMEDIR directory */
perror("check_timestamp: mkdir"); perror("check_timestamp: mkdir");
timedir_is_good = 0; timedir_is_good = 0;
} } else {
else { timedir_is_good = 1;/* TIMEDIR now exists */
timedir_is_good = 1; /* TIMEDIR now exists */
reminder(); reminder();
} }
} }
return (timestamp_is_old); return (timestamp_is_old);
} }
/******************************************************************** /********************************************************************
* *
* update_timestamp() * update_timestamp()
@@ -185,20 +183,18 @@ return (timestamp_is_old);
static void update_timestamp() static void update_timestamp()
{ {
register int fd; register int fd;
if ( timedir_is_good ) { if (timedir_is_good) {
unlink ( timestampfile_p ); unlink(timestampfile_p);
if (( fd = open (timestampfile_p, O_WRONLY|O_CREAT|O_TRUNC, 0600 )) < 0 ) if ((fd = open(timestampfile_p, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
perror( "update_timestamp: open" ); perror("update_timestamp: open");
close (fd); close(fd);
} }
} }
/******************************************************************** /********************************************************************
* *
* check_passwd() * check_passwd()
@@ -209,44 +205,41 @@ if ( timedir_is_good ) {
static void check_passwd() static void check_passwd()
{ {
char *crypt(); char *crypt();
struct passwd *pw_ent; struct passwd *pw_ent;
char *encrypted; /* this comes from /etc/passwd */ char *encrypted; /* this comes from /etc/passwd */
char *pass; /* this is what gets entered */ char *pass; /* this is what gets entered */
register int counter=TRIES_FOR_PASSWORD; register int counter = TRIES_FOR_PASSWORD;
if ((pw_ent = getpwuid(uid)) == NULL) {
if ( (pw_ent = getpwuid( uid )) == NULL ) { (void) sprintf(user, "%u", uid);
sprintf ( user, "%u", uid ); log_error(GLOBAL_NO_PW_ENT);
log_error( GLOBAL_NO_PW_ENT ); inform_user(GLOBAL_NO_PW_ENT);
inform_user ( GLOBAL_NO_PW_ENT ); exit(1);
exit (1);
} }
encrypted = pw_ent -> pw_passwd;
encrypted = pw_ent -> pw_passwd; /*
* you get TRIES_FOR_PASSWORD times to guess your password
/* you get TRIES_FOR_PASSWORD times to guess your password */ */
while (counter > 0) {
while ( counter > 0 ) { pass = getpass("Password:");
pass = getpass ( "Password:" ); if (*pass == (char) NULL)
if ( *pass == (char)NULL ) exit(0); exit(0);
if ( !strcmp(encrypted, crypt(pass,encrypted))) if (!strcmp(encrypted, crypt(pass, encrypted)))
return; /* if the passwd is correct return() */ return; /* if the passwd is correct return() */
-- counter; /* otherwise, try again */ --counter; /* otherwise, try again */
fprintf ( stderr, "%s\n", INCORRECT_PASSWORD ); (void) fprintf(stderr, "%s\n", INCORRECT_PASSWORD);
} }
log_error( PASSWORD_NOT_CORRECT ); log_error(PASSWORD_NOT_CORRECT);
inform_user ( PASSWORD_NOT_CORRECT ); inform_user(PASSWORD_NOT_CORRECT);
exit (1);
exit(1);
} }
/******************************************************************** /********************************************************************
* *
* reminder() * reminder()
@@ -256,21 +249,17 @@ exit (1);
static void reminder() static void reminder()
{ {
#ifdef SHORT_MESSAGE #ifdef SHORT_MESSAGE
fprintf(stderr,"\n%s\n%s\n\n%s\n%s\n\n", (void) fprintf(stderr, "\n%s\n%s\n\n%s\n%s\n\n",
#else #else
fprintf(stderr,"\n%s\n%s\n%s\n\n%s\n%s\n\n%s\n%s\n\n", (void) fprintf(stderr, "\n%s\n%s\n%s\n\n%s\n%s\n\n%s\n%s\n\n",
" sudo version 1.1, Copyright (C) 1991 The Root Group, Inc.",
" sudo version 1.1, Copyright (C) 1991 The Root Group, Inc.", " sudo comes with ABSOLUTELY NO WARRANTY. This is free software,",
" sudo comes with ABSOLUTELY NO WARRANTY. This is free software,", " and you are welcome to redistribute it under certain conditions.",
" and you are welcome to redistribute it under certain conditions.",
#endif #endif
"We trust you have received the usual lecture from the local Systems",
"We trust you have received the usual lecture from the local Systems", "Administrator. It usually boils down to these two things:",
"Administrator. It usually boils down to these two things:", " #1) Respect the privacy of others.",
" #2) Think before you type."
" #1) Respect the privacy of others.", );
" #2) Think before you type."
);
} }

View File

@@ -36,8 +36,7 @@
/* /*
* Most of this code has been rewritten to fix bugs and bears little * Most of this code has been rewritten to fix bugs and bears little
* resemblence to the original. As such, this file conforms to my * resemblence to the original.
* personal coding style.
* *
* Todd C. Miller (millert@colorado.edu) Sat Sep 4 12:22:04 MDT 1993 * Todd C. Miller (millert@colorado.edu) Sat Sep 4 12:22:04 MDT 1993
*/ */
@@ -76,23 +75,27 @@ char *find_path(file)
{ {
register char *n; /* for traversing path */ register char *n; /* for traversing path */
char *path = NULL; /* contents of PATH env var */ char *path = NULL; /* contents of PATH env var */
char fn[MAXPATHLEN+1]; /* filename (path + file) */ char fn[MAXPATHLEN + 1]; /* filename (path + file) */
struct stat statbuf; /* for stat(2) */ struct stat statbuf; /* for stat(2) */
int statfailed; /* stat(2) return value */ int statfailed; /* stat(2) return value */
int checkdot = 0; /* check current dir? */ int checkdot = 0; /* check current dir? */
char *qualify(); char *qualify();
if (strlen(file) > MAXPATHLEN) { if (strlen(file) > MAXPATHLEN) {
fprintf(stderr, "%s: path too long: %s\n", Argv[0], file); (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], file);
exit(1); exit(1);
} }
/* do we need to search the path? */ /*
* do we need to search the path?
*/
if (index(file, '/')) if (index(file, '/'))
return (qualify(file)); return (qualify(file));
/* grab PATH out of environment and make a local copy */ /*
if ((path = getenv("PATH") ) == NULL) * grab PATH out of environment and make a local copy
*/
if ((path = getenv("PATH")) == NULL)
return (NULL); return (NULL);
if ((path = strdup(path)) == NULL) { if ((path = strdup(path)) == NULL) {
@@ -101,27 +104,27 @@ char *find_path(file)
} }
do { do {
/* cheap strtok() */
if ((n = index(path, ':'))) if ((n = index(path, ':')))
*n = '\0'; *n = '\0';
/* /*
* search current dir last if it is in PATH * search current dir last if it is in PATH This will miss sneaky
* This will miss sneaky things like using './' or './/' * things like using './' or './/'
*/ */
if (*path == NULL || (*path == '.' && *(path+1) == NULL)) { if (*path == NULL || (*path == '.' && *(path + 1) == NULL)) {
checkdot = 1; checkdot = 1;
path = n + 1; path = n + 1;
continue; continue;
} }
/* filename to try */ (void) sprintf(fn, "%s/%s", path, file);
(void)sprintf(fn, "%s/%s", path, file);
/* stat the file to make sure it exists and is executable */ /*
* stat the file to make sure it exists and is executable
*/
statfailed = stat(fn, &statbuf); statfailed = stat(fn, &statbuf);
if (!statfailed && (statbuf.st_mode & 0000111)) if (!statfailed && (statbuf.st_mode & 0000111))
return(qualify(fn)); return (qualify(fn));
else if (statfailed && errno != ENOENT && errno != ENOTDIR) { else if (statfailed && errno != ENOENT && errno != ENOTDIR) {
perror("find_path: stat"); perror("find_path: stat");
exit(1); exit(1);
@@ -130,20 +133,24 @@ char *find_path(file)
} while (n); } while (n);
/* check current dir if dot was in the PATH */ /*
* check current dir if dot was in the PATH
*/
if (checkdot) { if (checkdot) {
(void)sprintf(fn, "./%s", file); (void) sprintf(fn, "./%s", file);
/* stat the file to make sure it exists and is executable */ /*
* stat the file to make sure it exists and is executable
*/
statfailed = stat(fn, &statbuf); statfailed = stat(fn, &statbuf);
if (!statfailed && (statbuf.st_mode & 0000111)) if (!statfailed && (statbuf.st_mode & 0000111))
return(qualify(fn)); return (qualify(fn));
else if (statfailed && errno != ENOENT && errno != ENOTDIR) { else if (statfailed && errno != ENOENT && errno != ENOTDIR) {
perror("find_path: stat"); perror("find_path: stat");
exit(1); exit(1);
} }
} }
return(NULL); return (NULL);
} }
@@ -160,35 +167,40 @@ char *qualify(n)
{ {
char *beg = NULL; /* begining of a path component */ char *beg = NULL; /* begining of a path component */
char *end; /* end of a path component */ char *end; /* end of a path component */
static char full[MAXPATHLEN+1]; /* the fully qualified name */ static char full[MAXPATHLEN + 1]; /* the fully qualified name */
char name[MAXPATHLEN+1]; /* local copy of n */ char name[MAXPATHLEN + 1]; /* local copy of n */
struct stat statbuf; /* for lstat() */ struct stat statbuf; /* for lstat() */
char *tmp; /* temporary pointer */ char *tmp; /* temporary pointer */
/* is it a bogus path? */ /*
* is it a bogus path?
*/
if (stat(n, &statbuf)) { if (stat(n, &statbuf)) {
if (errno == ENOENT) if (errno == ENOENT)
return(NULL); return (NULL);
else { else {
perror("qualify: stat"); perror("qualify: stat");
exit(1); exit(1);
} }
} }
/* if n is relative, fill full with working dir */ /*
* if n is relative, fill full with working dir
*/
if (*n != '/') { if (*n != '/') {
#ifdef USE_CWD #ifdef USE_CWD
if (!getcwd(full, (size_t)(MAXPATHLEN+1))) { if (!getcwd(full, (size_t) (MAXPATHLEN + 1))) {
#else #else
if (!getwd(full)) { if (!getwd(full)) {
#endif #endif
fprintf(stderr, "%s: Can't get working directory!\n", Argv[0]); (void) fprintf(stderr, "%s: Can't get working directory!\n",
Argv[0]);
exit(1); exit(1);
} }
} else } else
full[0] = '\0'; full[0] = '\0';
(void)strcpy(name, n); /* working copy... */ (void) strcpy(name, n); /* working copy... */
do { /* while (end) */ do { /* while (end) */
if (beg) if (beg)
@@ -196,14 +208,15 @@ char *qualify(n)
else else
beg = name; /* just starting out... */ beg = name; /* just starting out... */
/* find and terminate end of path component */ /*
* find and terminate end of path component
*/
if ((end = index(beg, '/'))) if ((end = index(beg, '/')))
*end = '\0'; *end = '\0';
if (beg == end) if (beg == end)
continue; continue;
else if (!strcmp(beg, ".")) else if (!strcmp(beg, ".")); /* ignore "." */
; /* ignore "." */
else if (!strcmp(beg, "..")) { else if (!strcmp(beg, "..")) {
if ((tmp = rindex(full, '/'))) if ((tmp = rindex(full, '/')))
*tmp = '\0'; *tmp = '\0';
@@ -212,11 +225,15 @@ char *qualify(n)
strcat(full, beg); /* copy in new component */ strcat(full, beg); /* copy in new component */
} }
/* if we used ../.. to go past the root dir just continue */ /*
* if we used ../.. to go past the root dir just continue
*/
if (!full[0]) if (!full[0])
continue; continue;
/* check for symbolic links */ /*
* check for symbolic links
*/
if (lstat(full, &statbuf)) { if (lstat(full, &statbuf)) {
perror("qualify: lstat"); perror("qualify: lstat");
exit(1); exit(1);
@@ -224,28 +241,26 @@ char *qualify(n)
if ((statbuf.st_mode & S_IFMT) == S_IFLNK) { if ((statbuf.st_mode & S_IFMT) == S_IFLNK) {
int linklen; /* length of link contents */ int linklen; /* length of link contents */
char newname[MAXPATHLEN+1]; /* temp storage to build new name */ char newname[MAXPATHLEN + 1]; /* temp storage to build new
* name */
linklen = readlink(full, newname, sizeof(newname)); linklen = readlink(full, newname, sizeof(newname));
newname[linklen] = '\0'; newname[linklen] = '\0';
/* check to make sure we don't go past MAXPATHLEN */ /* check to make sure we don't go past MAXPATHLEN */
++end; ++end;
if (end != (char *)1) { if (end != (char *) 1) {
if (linklen + strlen(end) >= MAXPATHLEN) { if (linklen + strlen(end) >= MAXPATHLEN) {
fprintf(stderr, "%s: path too long: %s/%s\n", Argv[0], (void )fprintf(stderr, "%s: path too long: %s/%s\n",
newname, end); Argv[0], newname, end);
exit(1); exit(1);
} }
strcat(newname, "/"); strcat(newname, "/");
strcat(newname, end); /* copy what's left of end */ strcat(newname, end); /* copy what's left of end */
} }
if (newname[0] == '/') /* reset full if necesary */ if (newname[0] == '/') /* reset full if necesary */
full[0] = '\0'; full[0] = '\0';
else else if ((tmp = rindex(full, '/'))) /* remove component from full */
if ((tmp = rindex(full, '/'))) /* remove component from full */
*tmp = '\0'; *tmp = '\0';
strcpy(name, newname); /* reset name with new path */ strcpy(name, newname); /* reset name with new path */
@@ -253,11 +268,13 @@ char *qualify(n)
} }
} while (end); } while (end);
/* if we resolved to "/" full[0] will be NULL */ /*
* if we resolved to "/" full[0] will be NULL
*/
if (!full[0]) if (!full[0])
strcpy(full, "/"); strcpy(full, "/");
return((char *)full); return ((char *) full);
} }
@@ -278,7 +295,7 @@ char *strdup(s1)
if ((s = (char *) malloc(strlen(s1) + 1)) == NULL) if ((s = (char *) malloc(strlen(s1) + 1)) == NULL)
return (NULL); return (NULL);
(void)strcpy(s, s1); (void) strcpy(s, s1);
return(s); return (s);
} }
#endif #endif

View File

@@ -33,7 +33,7 @@ static char sccsid[] = "@(#)getpass.c based on 5.3 (Berkeley) 9/22/88";
#include <stdio.h> #include <stdio.h>
char * char *
getpass(prompt) getpass(prompt)
char *prompt; char *prompt;
{ {
#if defined(sgi) #if defined(sgi)
@@ -55,47 +55,46 @@ getpass(prompt)
static char buf[PASSWD_LEN + 1]; static char buf[PASSWD_LEN + 1];
/* /*
* read and write to /dev/tty if possible; else read from * read and write to /dev/tty if possible; else read from stdin and write
* stdin and write to stderr. * to stderr.
*/ */
fd_tmp = open("/dev/tty", O_RDWR); fd_tmp = open("/dev/tty", O_RDWR);
if (fd_tmp < 0 || (outfp = fp = fdopen(fd_tmp, "r+")) == NULL) { if (fd_tmp < 0 || (outfp = fp = fdopen(fd_tmp, "r+")) == NULL) {
outfp = stderr; outfp = stderr;
fp = stdin; fp = stdin;
} }
#if defined(sgi) #if defined(sgi)
(void)ioctl(fileno(fp), TCGETA, &ttyb); (void) ioctl(fileno(fp), TCGETA, &ttyb);
svflagval = ttyb.c_lflag; svflagval = ttyb.c_lflag;
ttyb.c_lflag &= ~ECHO; ttyb.c_lflag &= ~ECHO;
omask = sigblock(sigmask(SIGINT)); omask = sigblock(sigmask(SIGINT));
(void)ioctl(fileno(fp), TCSETA, &ttyb); (void) ioctl(fileno(fp), TCSETA, &ttyb);
#else #else
(void)ioctl(fileno(fp), TIOCGETP, &ttyb); (void) ioctl(fileno(fp), TIOCGETP, &ttyb);
svflagval = ttyb.sg_flags; svflagval = ttyb.sg_flags;
ttyb.sg_flags &= ~ECHO; ttyb.sg_flags &= ~ECHO;
omask = sigblock(sigmask(SIGINT)); omask = sigblock(sigmask(SIGINT));
(void)ioctl(fileno(fp), TIOCSETP, &ttyb); (void) ioctl(fileno(fp), TIOCSETP, &ttyb);
#endif #endif
fprintf(outfp, "%s", prompt); (void) fprintf(outfp, "%s", prompt);
rewind(outfp); /* implied flush */ rewind(outfp); /* implied flush */
for (p = buf; (ch = getc(fp)) != EOF && ch != '\n';) for (p = buf; (ch = getc(fp)) != EOF && ch != '\n';)
if (p < buf + PASSWD_LEN) if (p < buf + PASSWD_LEN)
*p++ = ch; *p++ = ch;
*p = '\0'; *p = '\0';
(void)write(fileno(outfp), "\n", 1); (void) write(fileno(outfp), "\n", 1);
#if defined(sgi) #if defined(sgi)
ttyb.c_lflag = svflagval; ttyb.c_lflag = svflagval;
(void)ioctl(fileno(fp), TCSETA, &ttyb); (void) ioctl(fileno(fp), TCSETA, &ttyb);
#else #else
ttyb.sg_flags = svflagval; ttyb.sg_flags = svflagval;
(void)ioctl(fileno(fp), TIOCSETP, &ttyb); (void) ioctl(fileno(fp), TIOCSETP, &ttyb);
#endif #endif
(void)sigsetmask(omask); (void) sigsetmask(omask);
if (fp != stdin) if (fp != stdin)
(void)fclose(fp); (void) fclose(fp);
return(buf); return (buf);
} }
#endif #endif

314
logging.c
View File

@@ -49,7 +49,7 @@ static void send_mail();
static void reapchild(); static void reapchild();
static int appropriate(); static int appropriate();
static char logline[MAXLOGLEN+8]; static char logline[MAXLOGLEN + 8];
/********************************************************************** /**********************************************************************
* *
@@ -59,176 +59,180 @@ static char logline[MAXLOGLEN+8];
* syslogs the error or writes it to the log file * syslogs the error or writes it to the log file
*/ */
void log_error( code ) void log_error(code)
int code; int code;
{ {
char cwd[MAXPATHLEN+1]; char cwd[MAXPATHLEN + 1];
int argc; int argc;
char **argv; char **argv;
register char *p; register char *p;
register int count; register int count;
#ifndef SYSLOG #ifndef SYSLOG
register FILE *fp; register FILE *fp;
time_t now; time_t now;
#else #else
register int pri; /* syslog priority */ register int pri; /* syslog priority */
#endif #endif
/*
* there is no need to log the date and time twice if using syslog
/* there is no need to log the date and time twice if using syslog */ */
#ifndef SYSLOG #ifndef SYSLOG
now=time ( (time_t) 0 ); now = time((time_t) 0);
sprintf( logline, "%19.19s : %8.8s : ", ctime (&now), user ); (void) sprintf(logline, "%19.19s : %8.8s : ", ctime(&now), user);
#else #else
sprintf( logline, "%8.8s : ", user ); (void) sprintf(logline, "%8.8s : ", user);
#endif #endif
p = logline + strlen(logline); /* we need a pointer to the end of logline */ /*
* we need a pointer to the end of logline
*/
p = logline + strlen(logline);
/*
* so we know where we are...
*/
#ifdef USE_CWD #ifdef USE_CWD
getcwd(cwd, (size_t)(MAXPATHLEN+1)); /* so we know where we are... */ getcwd(cwd, (size_t) (MAXPATHLEN + 1));
#else #else
getwd(cwd); /* so we know where we are... */ getwd(cwd);
#endif #endif
switch ( code ) { switch (code) {
case ALL_SYSTEMS_GO: case ALL_SYSTEMS_GO:
sprintf ( p, "PWD=%s ; COMMAND=", cwd ); (void) sprintf(p, "PWD=%s ; COMMAND=", cwd);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_OK; pri = Syslog_priority_OK;
#endif #endif
break; break;
case VALIDATE_NO_USER: case VALIDATE_NO_USER:
sprintf ( p, "user NOT in sudoers ; PWD=%s ; COMMAND=", cwd ); (void) sprintf(p, "user NOT in sudoers ; PWD=%s ; COMMAND=", cwd);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case VALIDATE_NOT_OK: case VALIDATE_NOT_OK:
sprintf ( p, "command not allowed ; PWD=%s ; COMMAND=", cwd ); (void) sprintf(p, "command not allowed ; PWD=%s ; COMMAND=", cwd);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case VALIDATE_ERROR: case VALIDATE_ERROR:
sprintf ( p, "error in %s ; PWD=%s ; command: ", SUDOERS, cwd ); (void) sprintf(p, "error in %s ; PWD=%s ; command: ", SUDOERS, cwd);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case GLOBAL_NO_PW_ENT: case GLOBAL_NO_PW_ENT:
sprintf ( p, "There is no /etc/passwd entry for uid %d. ", uid ); (void) sprintf(p, "There is no /etc/passwd entry for uid %d. ",
uid);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case PASSWORD_NOT_CORRECT: case PASSWORD_NOT_CORRECT:
sprintf ( p, "%d incorrect passwords ; PWD=%s ; COMMAND=", (void) sprintf(p, "%d incorrect passwords ; PWD=%s ; COMMAND=",
TRIES_FOR_PASSWORD, cwd ); TRIES_FOR_PASSWORD, cwd);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case GLOBAL_NO_HOSTNAME: case GLOBAL_NO_HOSTNAME:
strcat ( p, "This machine does not have a hostname " ); strcat(p, "This machine does not have a hostname ");
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case NO_SUDOERS_FILE: case NO_SUDOERS_FILE:
switch ( errno ) { switch (errno) {
case ENOENT: case ENOENT:
sprintf ( p, "There is no %s file. ", SUDOERS ); (void) sprintf(p, "There is no %s file. ", SUDOERS);
break; break;
case EACCES: case EACCES:
sprintf ( p, "%s needs to run setuid root. ", Argv[0] ); (void) sprintf(p, "%s needs to run setuid root. ",
Argv[0]);
break; break;
default: default:
sprintf ( p, "There is a problem opening %s ", SUDOERS ); (void) sprintf(p, "There is a problem opening %s ",
SUDOERS);
break; break;
} }
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
case GLOBAL_HOST_UNREGISTERED: case GLOBAL_HOST_UNREGISTERED:
sprintf ( p, "gethostbyname() cannot find host %s ", host ); (void) sprintf(p, "gethostbyname() cannot find host %s ", host);
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
default: default:
strcat ( p, "found a wierd error : "); strcat(p, "found a wierd error : ");
#ifdef SYSLOG #ifdef SYSLOG
pri=Syslog_priority_NO; pri = Syslog_priority_NO;
#endif #endif
break; break;
} }
/* if this error is from load_globals() don't put argv in the message */ /*
if ( ! ( code & GLOBAL_PROBLEM ) ) { * if this error is from load_globals() don't put argv in the message
*/
if (!(code & GLOBAL_PROBLEM)) {
strcat ( logline, cmnd ); /* stuff the command into the logline */ strcat(logline, cmnd); /* stuff the command into the logline */
strcat ( logline, " "); strcat(logline, " ");
argc = Argc-2; argc = Argc - 2;
argv = Argv; argv++; argv = Argv;
argv++;
p = logline + strlen(logline); p = logline + strlen(logline);
count = (int)(logline + MAXLOGLEN - p); count = (int) (logline + MAXLOGLEN - p);
/* now stuff as much of the rest of the line as will fit */ /*
while ( count > 0 && argc-- ) { * now stuff as much of the rest of the line as will fit
strncpy ( p, *++argv, count ); */
strcat ( p, " "); while (count > 0 && argc--) {
p += 1 + (count < strlen(*argv) ? count : strlen(*argv) ); strncpy(p, *++argv, count);
count = (int)(logline + MAXLOGLEN - p); strcat(p, " ");
p += 1 + (count < strlen(*argv) ? count : strlen(*argv));
count = (int) (logline + MAXLOGLEN - p);
} }
if ( count <= 0 ) /* if the line is too long, */ if (count <= 0) /* if the line is too long, */
strcat ( p, " ... " ); /* add an elipsis to the end */ strcat(p, " ... "); /* add an elipsis to the end */
} }
if (appropriate(code))
if ( appropriate(code) )
send_mail(); send_mail();
#ifdef SYSLOG #ifdef SYSLOG
openlog(Syslog_ident, Syslog_options, Syslog_facility);
openlog ( Syslog_ident, Syslog_options, Syslog_facility ); syslog(pri, logline);
syslog ( pri, logline ); closelog();
closelog();
#else #else
if ((fp = fopen(LOGFILE, "a")) == NULL) {
if ( (fp = fopen ( LOGFILE, "a" )) == NULL ) { (void) sprintf(logline, "Can\'t open log file: %s", LOGFILE);
sprintf ( logline, "Can\'t open log file: %s", LOGFILE );
send_mail(); send_mail();
} else {
(void) fprintf(fp, "%s\n", logline);
(void) fclose(fp);
} }
else {
fprintf ( fp, "%s\n", logline );
(void) fclose (fp);
}
#endif #endif
} }
/********************************************************************** /**********************************************************************
* *
* send_mail() * send_mail()
@@ -237,80 +241,69 @@ else {
* *
*/ */
char *exec_argv[]= { "sendmail" , char *exec_argv[] = {"sendmail",
"-t" , "-t",
ALERTMAIL , ALERTMAIL,
(char *) NULL }; (char *) NULL};
static void send_mail() static void send_mail()
{ {
char *mailer=MAILER; char *mailer = MAILER;
char *subject=MAILSUBJECT; char *subject = MAILSUBJECT;
int fd[2]; int fd[2];
char buf[MAXLOGLEN+1024]; char buf[MAXLOGLEN + 1024];
if ( (mailer = find_path ( mailer )) == NULL ) { if ((mailer = find_path(mailer)) == NULL) {
fprintf (stderr, "%s not found\n", mailer ); (void) fprintf(stderr, "%s not found\n", mailer);
exit (1); exit(1);
} }
(void) signal(SIGCHLD, reapchild);
signal ( SIGCHLD, reapchild ); if (fork())
return;
if ( fork () ) return; /*
* we don't want any security problems ...
/* we don't want any security problems ... */ */
if ( setuid ( uid ) ) { if (setuid(uid)) {
perror("setuid(uid)"); perror("setuid(uid)");
exit(1); exit(1);
} }
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
signal ( SIGHUP, SIG_IGN ); if (pipe(fd)) {
signal ( SIGINT, SIG_IGN ); perror("send_mail: pipe");
signal ( SIGQUIT, SIG_IGN ); exit(1);
if ( pipe(fd) ) {
perror( "send_mail: pipe" );
exit ( 1 );
} }
(void) dup2(fd[0], 0);
(void) dup2(fd[1], 1);
(void) close(fd[0]);
(void) close(fd[1]);
(void) dup2 ( fd[0], 0 ); if (!fork()) { /* child */
(void) dup2 ( fd[1], 1 );
(void) close (fd[0]);
(void) close (fd[1]);
if ( ! fork () ) {
/* child parent */
(void) close(1); (void) close(1);
execv ( mailer, exec_argv ); execve(mailer, exec_argv, Envp);
/* this should not happen */ /* this should not happen */
perror( "execv"); perror("execve");
exit (1); exit(1);
} else { /* parent */
}
else {
(void) close(0); (void) close(0);
/* feed the data to sendmail */ /* feed the data to sendmail */
sprintf (buf, "To: %s\nSubject: %s\n\n%s\n\n", (void) sprintf(buf, "To: %s\nSubject: %s\n\n%s\n\n",
ALERTMAIL, subject, logline ); ALERTMAIL, subject, logline);
write ( 1, buf, strlen(buf)); write(1, buf, strlen(buf));
close ( 1 ); close(1);
exit ( 0 ); exit(0);
} }
} }
/**************************************************************** /****************************************************************
* *
* reapchild() * reapchild()
@@ -318,15 +311,13 @@ else {
* This function gets rid fo all the ugly zombies * This function gets rid fo all the ugly zombies
*/ */
static void reapchild () static void reapchild()
{ {
(void) wait ( NULL ); (void) wait(NULL);
} }
/********************************************************************** /**********************************************************************
* *
* inform_user () * inform_user ()
@@ -335,62 +326,57 @@ static void reapchild ()
* when an error occurs * when an error occurs
*/ */
void inform_user( code ) void inform_user(code)
int code; int code;
{ {
switch ( code ) { switch (code) {
case VALIDATE_NO_USER: case VALIDATE_NO_USER:
fprintf( stderr, (void) fprintf(stderr,
"%s is not in the sudoers file. This incident will be reported.\n\n", "%s is not in the sudoers file. This incident will be reported.\n\n",
user ); user);
break; break;
case VALIDATE_NOT_OK: case VALIDATE_NOT_OK:
fprintf( stderr, (void) fprintf(stderr,
"Sorry, user %s is not allowed to execute %s\n\n", "Sorry, user %s is not allowed to execute %s\n\n",
user, cmnd ); user, cmnd);
break; break;
case VALIDATE_ERROR: case VALIDATE_ERROR:
fprintf( stderr, (void) fprintf(stderr,
"Sorry, there is a fatal error in the sudoers file.\n\n" ); "Sorry, there is a fatal error in the sudoers file.\n\n");
break; break;
case GLOBAL_NO_PW_ENT: case GLOBAL_NO_PW_ENT:
fprintf ( stderr, (void) fprintf(stderr,
"Intruder Alert! You don\'t exist in the passwd file\n\n"); "Intruder Alert! You don\'t exist in the passwd file\n\n");
break; break;
case GLOBAL_NO_HOSTNAME: case GLOBAL_NO_HOSTNAME:
fprintf ( stderr, (void) fprintf(stderr,
"This machine does not have a hostname\n\n" ); "This machine does not have a hostname\n\n");
break; break;
case GLOBAL_HOST_UNREGISTERED: case GLOBAL_HOST_UNREGISTERED:
fprintf ( stderr, (void) fprintf(stderr,
"This machine is not available via gethostbyname()\n\n"); "This machine is not available via gethostbyname()\n\n");
break; break;
case PASSWORD_NOT_CORRECT: case PASSWORD_NOT_CORRECT:
fprintf ( stderr, "Password not entered correctly after %d tries\n\n", (void) fprintf(stderr, "Password not entered correctly after %d tries\n\n",
TRIES_FOR_PASSWORD ); TRIES_FOR_PASSWORD);
break; break;
default: default:
fprintf ( stderr, (void) fprintf(stderr,
"Something wierd happened.\n\n" ); "Something wierd happened.\n\n");
break; break;
} }
} }
/**************************************************************** /****************************************************************
* *
* appropriate() * appropriate()
@@ -398,14 +384,15 @@ switch ( code ) {
* This function determines whether to send mail or not... * This function determines whether to send mail or not...
*/ */
static int appropriate( code ) static int appropriate(code)
int code; int code;
{ {
switch ( code ) { switch (code) {
/* these will NOT send mail */
/*
* these will NOT send mail
*/
case VALIDATE_OK: case VALIDATE_OK:
case PASSWORD_NOT_CORRECT: case PASSWORD_NOT_CORRECT:
/* case ALL_SYSTEMS_GO: this is the same as OK */ /* case ALL_SYSTEMS_GO: this is the same as OK */
@@ -428,8 +415,9 @@ switch ( code ) {
#endif #endif
break; break;
/* these WILL send mail */ /*
* these WILL send mail
*/
case VALIDATE_ERROR: case VALIDATE_ERROR:
case NO_SUDOERS_FILE: case NO_SUDOERS_FILE:
default: default:

472
parse.c
View File

@@ -22,13 +22,15 @@
* 3959 Arbol CT (303) 447-8093 * 3959 Arbol CT (303) 447-8093
* Boulder, CO 80301-1752 * Boulder, CO 80301-1752
* *
******************************************************************************** **************************************************************************
* parse.c, sudo project *
* David R. Hieb * parse.c, sudo project
* March 18, 1991 * David R. Hieb
* * March 18, 1991
* routines to implement and maintain the parsing and list management. *
*******************************************************************************/ * routines to implement and maintain the parsing and list management.
*/
#include <stdio.h> #include <stdio.h>
#include <strings.h> #include <strings.h>
#include <ctype.h> #include <ctype.h>
@@ -37,7 +39,9 @@
#include "sudo.h" #include "sudo.h"
/* there are 3 main lists (User, Host_Alias, Cmnd_Alias) and 1 extra list */ /*
* there are 3 main lists (User, Host_Alias, Cmnd_Alias) and 1 extra list
*/
#define NUM_LISTS 3+1 #define NUM_LISTS 3+1
extern char *user, *host, *cmnd; extern char *user, *host, *cmnd;
@@ -49,90 +53,111 @@ int parse_error = FALSE, found_user = FALSE;
int next_type, num_host_alias = 0, num_cmnd_alias = 0; int next_type, num_host_alias = 0, num_cmnd_alias = 0;
LINK tmp_ptr, reset_ptr, save_ptr, list_ptr[NUM_LISTS]; LINK tmp_ptr, reset_ptr, save_ptr, list_ptr[NUM_LISTS];
/*******************************************************************************
* inserts a node into list 'list_num' and updates list_ptr[list_num] /*
*******************************************************************************/ * inserts a node into list 'list_num' and updates list_ptr[list_num]
*/
void insert_member(list_num, token_type, op_type, data_string) void insert_member(list_num, token_type, op_type, data_string)
int token_type, list_num; int token_type, list_num;
char op_type; char op_type;
char *data_string; char *data_string;
{ {
tmp_ptr = (LINK)malloc(sizeof(LIST)); tmp_ptr = (LINK) malloc(sizeof(LIST));
tmp_ptr->type = token_type; tmp_ptr -> type = token_type;
tmp_ptr->op = op_type; tmp_ptr -> op = op_type;
tmp_ptr->data = (char *)malloc(strlen(data_string)+1); tmp_ptr -> data = (char *) malloc(strlen(data_string) + 1);
strcpy(tmp_ptr->data, data_string); strcpy(tmp_ptr -> data, data_string);
tmp_ptr->next = (new_list[list_num] == TRUE) ? NULL : list_ptr[list_num]; tmp_ptr -> next = (new_list[list_num] == TRUE) ? NULL : list_ptr[list_num];
list_ptr[list_num] = list_ptr[EXTRA_LIST] = tmp_ptr; list_ptr[list_num] = list_ptr[EXTRA_LIST] = tmp_ptr;
} }
/*******************************************************************************
* diagnostic list printing utility that prints list 'list_num'
*******************************************************************************/
void print_list(list_num)
int list_num;
{
LINK tmptmp_ptr;
tmptmp_ptr = list_ptr[list_num];
while (list_ptr[list_num] != NULL) {
printf("type = %d, op = %c, data = %s\n", list_ptr[list_num]->type,
list_ptr[list_num]->op, list_ptr[list_num]->data);
tmp_ptr = list_ptr[list_num];
list_ptr[list_num] = tmp_ptr->next;
}
list_ptr[list_num] = tmptmp_ptr;
}
/*******************************************************************************
* delete list utility that deletes list 'list_num'
*******************************************************************************/
void delete_list(list_num)
int list_num;
{
while (list_ptr[list_num] != NULL) {
tmp_ptr = list_ptr[list_num];
list_ptr[list_num] = tmp_ptr->next;
/* free(tmp_ptr); */
}
}
/*******************************************************************************
* this routine is what the lex/yacc code calls to build the different lists.
* once the lists are all built, control eventually returns to validate().
*******************************************************************************/
int call_back(token_type, op_type, data_string)
int token_type;
char op_type;
char *data_string;
{
/* all nodes start out in the extra list since the node name is received last */
list_num = EXTRA_LIST;
/* /*
* diagnostic list printing utility that prints list 'list_num'
*/
void print_list(list_num)
int list_num;
{
LINK tmptmp_ptr;
tmptmp_ptr = list_ptr[list_num];
while (list_ptr[list_num] != NULL) {
(void) printf("type = %d, op = %c, data = %s\n",
list_ptr[list_num] -> type,
list_ptr[list_num] -> op, list_ptr[list_num] -> data);
tmp_ptr = list_ptr[list_num];
list_ptr[list_num] = tmp_ptr -> next;
}
list_ptr[list_num] = tmptmp_ptr;
}
/*
* delete list utility that deletes list 'list_num'
*/
void delete_list(list_num)
int list_num;
{
while (list_ptr[list_num] != NULL) {
tmp_ptr = list_ptr[list_num];
list_ptr[list_num] = tmp_ptr -> next;
/* free(tmp_ptr); */
}
}
/*
* this routine is what the lex/yacc code calls to build the different lists.
* once the lists are all built, control eventually returns to validate().
*/
int call_back(token_type, op_type, data_string)
int token_type;
char op_type;
char *data_string;
{
/*
* all nodes start out in the extra list since the node name
* is received last
*/
list_num = EXTRA_LIST;
/*
* if the last received node is TYPE1, then we can classify the list * if the last received node is TYPE1, then we can classify the list
* and effectively transfer the extra list to the correct list type. * and effectively transfer the extra list to the correct list type.
*/ */
if (token_type == TYPE1) { if (token_type == TYPE1) {
/* we have just build a "Host_Alias" list */ /*
* we have just build a "Host_Alias" list
*/
if (strcmp(data_string, "Host_Alias") == 0) { if (strcmp(data_string, "Host_Alias") == 0) {
list_num = HOST_LIST; list_num = HOST_LIST;
if (num_host_alias > 0) { if (num_host_alias > 0) {
reset_ptr->next = list_ptr[HOST_LIST]; reset_ptr -> next = list_ptr[HOST_LIST];
} }
num_host_alias++; num_host_alias++;
} }
/* we have just build a "Cmnd_Alias" list */ /*
* we have just build a "Cmnd_Alias" list
*/
else if (strcmp(data_string, "Cmnd_Alias") == 0) { else if (strcmp(data_string, "Cmnd_Alias") == 0) {
list_num = CMND_LIST; list_num = CMND_LIST;
if (num_cmnd_alias > 0) { if (num_cmnd_alias > 0) {
reset_ptr->next = list_ptr[CMND_LIST]; reset_ptr -> next = list_ptr[CMND_LIST];
} }
num_cmnd_alias++; num_cmnd_alias++;
} }
/* we have just build a "User" list */ /*
* we have just build a "User" list
*/
else { else {
list_num = USER_LIST; list_num = USER_LIST;
user_list_found = TRUE; user_list_found = TRUE;
@@ -141,265 +166,284 @@ if (token_type == TYPE1) {
new_list[list_num] = FALSE; new_list[list_num] = FALSE;
list_ptr[list_num] = list_ptr[EXTRA_LIST]; list_ptr[list_num] = list_ptr[EXTRA_LIST];
} }
/*
* actually link the new node into list 'list_num'
*/
insert_member(list_num, token_type, op_type, data_string);
/* actually link the new node into list 'list_num' */ if (new_list[list_num] == TRUE) {
insert_member(list_num, token_type, op_type, data_string);
if (new_list[list_num] == TRUE) {
reset_ptr = list_ptr[list_num]; reset_ptr = list_ptr[list_num];
new_list[list_num] = FALSE; new_list[list_num] = FALSE;
} }
/*
/*
* we process one user record at a time from the sudoers file. if we * we process one user record at a time from the sudoers file. if we
* find the user were looking for, we return to lex/yacc declaring * find the user were looking for, we return to lex/yacc declaring
* that we have done so. otherwise, we reset the user list, delete the * that we have done so. otherwise, we reset the user list, delete the
* nodes and start over again looking for the user. * nodes and start over again looking for the user.
*/ */
if (user_list_found == TRUE) { if (user_list_found == TRUE) {
if (list_ptr[list_num]->type == TYPE1 && if (list_ptr[list_num] -> type == TYPE1 &&
strcmp(list_ptr[list_num]->data, user) == 0) { strcmp(list_ptr[list_num] -> data, user) == 0) {
return(FOUND_USER); return (FOUND_USER);
} } else {
else {
new_list[list_num] = TRUE; new_list[list_num] = TRUE;
user_list_found = FALSE; user_list_found = FALSE;
delete_list(list_num); delete_list(list_num);
} }
} }
return(NOT_FOUND_USER); return (NOT_FOUND_USER);
} }
/*******************************************************************************
* this routine is called from cmnd_check() to resolve whether or not
* a user is permitted to perform a to-yet-be-determined command for /*
* a certain host name. * this routine is called from cmnd_check() to resolve whether or not
*******************************************************************************/ * a user is permitted to perform a to-yet-be-determined command for
* a certain host name.
*/
int host_type_ok() int host_type_ok()
{ {
/* check for the reserved keyword 'ALL'. if so, don't check the host name */ /*
if (strcmp(list_ptr[USER_LIST]->data, "ALL") == 0) { * check for the reserved keyword 'ALL'. if so, don't check the host name
return(TRUE); */
if (strcmp(list_ptr[USER_LIST] -> data, "ALL") == 0) {
return (TRUE);
} }
/* this case is the normal lowercase hostname */ /*
else if (isupper(list_ptr[USER_LIST]->data[0]) == FALSE) { * this case is the normal lowercase hostname
return(strcmp(list_ptr[USER_LIST]->data, host) == 0); */
else if (isupper(list_ptr[USER_LIST] -> data[0]) == FALSE) {
return (strcmp(list_ptr[USER_LIST] -> data, host) == 0);
} }
/* by now we have a Host_Alias that will have to be expanded */ /*
else { * by now we have a Host_Alias that will have to be expanded
*/
else {
save_ptr = list_ptr[HOST_LIST]; save_ptr = list_ptr[HOST_LIST];
while (list_ptr[HOST_LIST] != NULL) { while (list_ptr[HOST_LIST] != NULL) {
if ((list_ptr[HOST_LIST]->type == TYPE2) && if ((list_ptr[HOST_LIST] -> type == TYPE2) &&
(strcmp(list_ptr[HOST_LIST]->data, (strcmp(list_ptr[HOST_LIST] -> data,
list_ptr[USER_LIST]->data) == 0)) { list_ptr[USER_LIST] -> data) == 0)) {
next_type = list_ptr[HOST_LIST]->next->type; next_type = list_ptr[HOST_LIST] -> next -> type;
tmp_ptr = list_ptr[HOST_LIST]; tmp_ptr = list_ptr[HOST_LIST];
list_ptr[HOST_LIST] = tmp_ptr->next; list_ptr[HOST_LIST] = tmp_ptr -> next;
while (next_type == TYPE3) { while (next_type == TYPE3) {
if (strcmp(list_ptr[HOST_LIST]->data, host) == 0) { if (strcmp(list_ptr[HOST_LIST] -> data, host) == 0) {
list_ptr[HOST_LIST] = save_ptr; list_ptr[HOST_LIST] = save_ptr;
return(TRUE); return (TRUE);
} }
if (list_ptr[HOST_LIST]->next != NULL) { if (list_ptr[HOST_LIST] -> next != NULL) {
next_type = list_ptr[HOST_LIST]->next->type; next_type = list_ptr[HOST_LIST] -> next -> type;
tmp_ptr = list_ptr[HOST_LIST]; tmp_ptr = list_ptr[HOST_LIST];
list_ptr[HOST_LIST] = tmp_ptr->next; list_ptr[HOST_LIST] = tmp_ptr -> next;
} } else {
else {
next_type = ~TYPE3; next_type = ~TYPE3;
} }
} }
} } else {
else {
tmp_ptr = list_ptr[HOST_LIST]; tmp_ptr = list_ptr[HOST_LIST];
list_ptr[HOST_LIST] = tmp_ptr->next; list_ptr[HOST_LIST] = tmp_ptr -> next;
} }
} }
list_ptr[HOST_LIST] = save_ptr; list_ptr[HOST_LIST] = save_ptr;
return(FALSE); return (FALSE);
} }
} }
/*******************************************************************************
* this routine is called from cmnd_check() to resolve whether or not
* a user is permitted to perform a certain command on the already /*
* established host. * this routine is called from cmnd_check() to resolve whether or not
*******************************************************************************/ * a user is permitted to perform a certain command on the already
* established host.
*/
int cmnd_type_ok() int cmnd_type_ok()
{ {
/* check for the reserved keyword 'ALL'. */ /*
if (strcmp(list_ptr[USER_LIST]->data, "ALL") == 0) { * check for the reserved keyword 'ALL'.
*/
if (strcmp(list_ptr[USER_LIST] -> data, "ALL") == 0) {
/* if the command has an absolute path, let them do it */ /* if the command has an absolute path, let them do it */
if (cmnd[0] == '/') { if (cmnd[0] == '/') {
return(MATCH); return (MATCH);
} }
/* if the command does not have an absolute path, forget it */ /* if the command does not have an absolute path, forget it */
else { else {
return(NO_MATCH); return (NO_MATCH);
} }
} }
/* if the command has an absolute path, check it out */ /*
else if (list_ptr[USER_LIST]->data[0] == '/') { * if the command has an absolute path, check it out
/* op | data | return value */
*--------------------------------- else if (list_ptr[USER_LIST] -> data[0] == '/') {
/*
* op | data | return value
* ---------------------------------
* ' ' | No Match | return(NO_MATCH) * ' ' | No Match | return(NO_MATCH)
* '!' | No Match | return(NO_MATCH) * '!' | No Match | return(NO_MATCH)
* ' ' | A Match | return(MATCH) * ' ' | A Match | return(MATCH)
* '!' | A Match | return(QUIT_NOW) * '!' | A Match | return(QUIT_NOW)
* *
* these special cases are important in subtracting from the * these special cases are important in subtracting from the Universe
* Universe of commands in something like: * of commands in something like:
* user machine=ALL,!/bin/rm,!/etc/named ... * user machine=ALL,!/bin/rm,!/etc/named ...
*/ */
if (strcmp(list_ptr[USER_LIST]->data, cmnd) == 0) { if (strcmp(list_ptr[USER_LIST] -> data, cmnd) == 0) {
if (list_ptr[USER_LIST]->op == '!') { if (list_ptr[USER_LIST] -> op == '!') {
return(QUIT_NOW); return (QUIT_NOW);
} else {
return (MATCH);
} }
} else {
return (NO_MATCH);
}
}
/*
* by now we have a Cmnd_Alias that will have to be expanded
*/
else { else {
return(MATCH);
}
}
else {
return(NO_MATCH);
}
}
/* by now we have a Cmnd_Alias that will have to be expanded */
else {
save_ptr = list_ptr[CMND_LIST]; save_ptr = list_ptr[CMND_LIST];
while (list_ptr[CMND_LIST] != NULL) { while (list_ptr[CMND_LIST] != NULL) {
if ((list_ptr[CMND_LIST]->type == TYPE2) && if ((list_ptr[CMND_LIST] -> type == TYPE2) &&
(strcmp(list_ptr[CMND_LIST]->data, (strcmp(list_ptr[CMND_LIST] -> data,
list_ptr[USER_LIST]->data) == 0)) { list_ptr[USER_LIST] -> data) == 0)) {
next_type = list_ptr[CMND_LIST]->next->type; next_type = list_ptr[CMND_LIST] -> next -> type;
tmp_ptr = list_ptr[CMND_LIST]; tmp_ptr = list_ptr[CMND_LIST];
list_ptr[CMND_LIST] = tmp_ptr->next; list_ptr[CMND_LIST] = tmp_ptr -> next;
while (next_type == TYPE3) { while (next_type == TYPE3) {
if (strcmp(list_ptr[CMND_LIST]->data, cmnd) == 0) { if (strcmp(list_ptr[CMND_LIST] -> data, cmnd) == 0) {
if (list_ptr[USER_LIST]->op == '!') { if (list_ptr[USER_LIST] -> op == '!') {
list_ptr[CMND_LIST] = save_ptr; list_ptr[CMND_LIST] = save_ptr;
return(QUIT_NOW); return (QUIT_NOW);
} } else {
else {
list_ptr[CMND_LIST] = save_ptr; list_ptr[CMND_LIST] = save_ptr;
return(MATCH); return (MATCH);
} }
} }
if (list_ptr[CMND_LIST]->next != NULL) { if (list_ptr[CMND_LIST] -> next != NULL) {
next_type = list_ptr[CMND_LIST]->next->type; next_type = list_ptr[CMND_LIST] -> next -> type;
tmp_ptr = list_ptr[CMND_LIST]; tmp_ptr = list_ptr[CMND_LIST];
list_ptr[CMND_LIST] = tmp_ptr->next; list_ptr[CMND_LIST] = tmp_ptr -> next;
} } else {
else {
next_type = ~TYPE3; next_type = ~TYPE3;
} }
} }
} } else {
else {
tmp_ptr = list_ptr[CMND_LIST]; tmp_ptr = list_ptr[CMND_LIST];
list_ptr[CMND_LIST] = tmp_ptr->next; list_ptr[CMND_LIST] = tmp_ptr -> next;
} }
} }
list_ptr[CMND_LIST] = save_ptr; list_ptr[CMND_LIST] = save_ptr;
return(NO_MATCH); return (NO_MATCH);
} }
} }
/*******************************************************************************
* this routine is called from validate() after the call_back() routine
* has built all the possible lists. this routine steps thru the user list /*
* calling on host_type_ok() and cmnd_type_ok() trying to resolve whether * this routine is called from validate() after the call_back() routine
* or not the user will be able to execute the command on the host. * has built all the possible lists. this routine steps thru the user list
*******************************************************************************/ * calling on host_type_ok() and cmnd_type_ok() trying to resolve whether
* or not the user will be able to execute the command on the host.
*/
int cmnd_check() int cmnd_check()
{ {
int return_code; int return_code;
while (list_ptr[USER_LIST] != NULL) { while (list_ptr[USER_LIST] != NULL) {
if ((list_ptr[USER_LIST]->type == TYPE2) && host_type_ok()) { if ((list_ptr[USER_LIST] -> type == TYPE2) && host_type_ok()) {
next_type = list_ptr[USER_LIST]->next->type; next_type = list_ptr[USER_LIST] -> next -> type;
tmp_ptr = list_ptr[USER_LIST]; tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr->next; list_ptr[USER_LIST] = tmp_ptr -> next;
while (next_type == TYPE3) { while (next_type == TYPE3) {
return_code = cmnd_type_ok(); return_code = cmnd_type_ok();
if (return_code == MATCH) { if (return_code == MATCH) {
return(VALIDATE_OK); return (VALIDATE_OK);
} else if (return_code == QUIT_NOW) {
return (VALIDATE_NOT_OK);
} }
else if (return_code == QUIT_NOW) { if (list_ptr[USER_LIST] -> next != NULL) {
return(VALIDATE_NOT_OK); next_type = list_ptr[USER_LIST] -> next -> type;
}
if (list_ptr[USER_LIST]->next != NULL) {
next_type = list_ptr[USER_LIST]->next->type;
tmp_ptr = list_ptr[USER_LIST]; tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr->next; list_ptr[USER_LIST] = tmp_ptr -> next;
} } else {
else {
next_type = ~TYPE3; next_type = ~TYPE3;
} }
} }
} } else {
else {
tmp_ptr = list_ptr[USER_LIST]; tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr->next; list_ptr[USER_LIST] = tmp_ptr -> next;
} }
} }
return(VALIDATE_NOT_OK); return (VALIDATE_NOT_OK);
} }
/*******************************************************************************
* this routine is called from the sudo.c module and tries to validate
* the user, host and command triplet.
*******************************************************************************/
int validate()
{
FILE *sudoers_fp;
int i, return_code;
if ((sudoers_fp = fopen(SUDOERS, "r")) == NULL ) {
perror(SUDOERS);
log_error( NO_SUDOERS_FILE );
exit(1);
}
yyin = sudoers_fp;
yyout = stdout;
for (i = 0; i < NUM_LISTS; i++)
new_list[i] = TRUE;
/* /*
* this routine is called from the sudo.c module and tries to validate
* the user, host and command triplet.
*/
int validate()
{
FILE *sudoers_fp;
int i, return_code;
if ((sudoers_fp = fopen(SUDOERS, "r")) == NULL) {
perror(SUDOERS);
log_error(NO_SUDOERS_FILE);
exit(1);
}
yyin = sudoers_fp;
yyout = stdout;
for (i = 0; i < NUM_LISTS; i++)
new_list[i] = TRUE;
/*
* yyparse() returns with one of 3 values: 0) yyparse() worked fine; * yyparse() returns with one of 3 values: 0) yyparse() worked fine;
* 1) yyparse() failed; FOUND_USER) the user was found and yyparse() * 1) yyparse() failed; FOUND_USER) the user was found and yyparse()
* was returned from prematurely. * was returned from prematurely.
*/ */
return_code = yyparse(); return_code = yyparse();
/* don't need to keep this open... */ /*
(void) fclose (sudoers_fp); * don't need to keep this open...
*/
(void) fclose(sudoers_fp);
/* if a parsing error occurred, set return_code accordingly */ /*
if (parse_error == TRUE) { * if a parsing error occurred, set return_code accordingly
*/
if (parse_error == TRUE) {
return_code = PARSE_ERROR; return_code = PARSE_ERROR;
} }
/*
/* if the user was not found, set the return_code accordingly */ * if the user was not found, set the return_code accordingly
if (found_user == FALSE) { */
if (found_user == FALSE) {
return_code = NOT_FOUND_USER; return_code = NOT_FOUND_USER;
} }
/*
/* handle the 3 cases individually &*/ * handle the 3 cases individually
switch(return_code) { */
switch (return_code) {
case FOUND_USER: case FOUND_USER:
return_code = cmnd_check(); return_code = cmnd_check();
delete_list(USER_LIST); delete_list(USER_LIST);
delete_list(HOST_LIST); delete_list(HOST_LIST);
delete_list(CMND_LIST); delete_list(CMND_LIST);
return(return_code); return (return_code);
break; break;
case NOT_FOUND_USER: case NOT_FOUND_USER:
return(VALIDATE_NO_USER); return (VALIDATE_NO_USER);
break; break;
case PARSE_ERROR: case PARSE_ERROR:
return(VALIDATE_ERROR); return (VALIDATE_ERROR);
break; break;
} }
} }

189
sudo.c
View File

@@ -78,45 +78,50 @@ uid_t uid;
*/ */
main(argc, argv, envp) main(argc, argv, envp)
int argc; char **argv; char **envp; int argc;
char **argv;
char **envp;
{ {
static void usage(); static void usage();
int rtn; int rtn;
Argv=argv; Argv = argv;
Argc=argc; Argc = argc;
/* if nothing is passed, we don't need to do anything... */ /*
if ( argc < 2 ) usage(); * if nothing is passed, we don't need to do anything...
*/
if (argc < 2)
usage();
/* close all file descriptors to make sure we have a nice /*
* close all file descriptors to make sure we have a nice
* clean slate from which to work. * clean slate from which to work.
*/ */
for ( rtn = getdtablesize() - 1 ; rtn > 3; rtn -- ) for (rtn = getdtablesize() - 1; rtn > 3; rtn--)
(void)close(rtn); (void) close(rtn);
load_globals(); /* load the user host cmnd and uid variables */ load_globals(); /* load the user host cmnd and uid variables */
clean_envp(envp); /* build Envp based on envp (w/o LD_*) */ clean_envp(envp); /* build Envp based on envp (w/o LD_*) */
if ( setuid(0) ) { if (setuid(0)) {
perror("setuid(0)"); perror("setuid(0)");
exit(1); exit(1);
} }
rtn=validate(); rtn = validate();
if ( setruid(uid) ) { if (setruid(uid)) {
#ifndef _AIX #ifndef _AIX
perror("setruid(uid)"); perror("setruid(uid)");
exit(1); exit(1);
#endif #endif
} }
switch (rtn) {
switch ( rtn ) {
case VALIDATE_OK: case VALIDATE_OK:
check_user(); check_user();
log_error( ALL_SYSTEMS_GO ); log_error(ALL_SYSTEMS_GO);
if ( setuid(0) ) { if (setuid(0)) {
perror("setuid(0)"); perror("setuid(0)");
exit(1); exit(1);
} }
@@ -128,24 +133,24 @@ switch ( rtn ) {
case VALIDATE_NOT_OK: case VALIDATE_NOT_OK:
case VALIDATE_ERROR: case VALIDATE_ERROR:
default: default:
log_error ( rtn ); log_error(rtn);
if ( setuid ( uid ) ) { if (setuid(uid)) {
perror("setuid(uid)"); perror("setuid(uid)");
exit(1); exit(1);
} }
inform_user ( rtn ); inform_user(rtn);
exit (1); exit(1);
break; break;
} }
return(-1); /* If we get here it's an error (execve failed) */ /*
* If we get here it's an error (execve failed)
*/
return (-1);
} }
/********************************************************************** /**********************************************************************
* *
* load_globals() * load_globals()
@@ -156,69 +161,72 @@ switch ( rtn ) {
void load_globals() void load_globals()
{ {
struct passwd *pw_ent; struct passwd *pw_ent;
struct hostent *h_ent; struct hostent *h_ent;
char path[MAXPATHLEN+1]; char path[MAXPATHLEN + 1];
char *p; char *p;
if ( (user=malloc(9)) == NULL ) { if ((user = malloc(9)) == NULL) {
perror ("malloc"); perror("malloc");
exit (1); exit(1);
} }
if ( (host=malloc(MAXHOSTNAMELEN+1)) == NULL ) { if ((host = malloc(MAXHOSTNAMELEN + 1)) == NULL) {
perror ("malloc"); perror("malloc");
exit (1); exit(1);
} }
uid = getuid(); /* we need to tuck this away for safe keeping */
uid = getuid(); /* we need to tuck this away for safe keeping */
/* loading the cmnd global variable from argv[1] */ /*
* loading the cmnd global variable from argv[1]
strncpy(path, Argv[1], MAXPATHLEN)[MAXPATHLEN] = 0; */
cmnd = find_path ( path ); /* get the absolute path */ strncpy(path, Argv[1], MAXPATHLEN)[MAXPATHLEN] = 0;
if ( cmnd == NULL ) { cmnd = find_path(path); /* get the absolute path */
fprintf ( stderr, "%s: %s: command not found\n", Argv[0], Argv[1] ); if (cmnd == NULL) {
exit (1); (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0], Argv[1]);
exit(1);
} }
cmnd = strdup ( cmnd ); cmnd = strdup(cmnd);
#ifdef NO_ROOT_SUDO #ifdef NO_ROOT_SUDO
if ( uid == 0 ) { if (uid == 0) {
fprintf(stderr, "You are already root, you don\'t need to use sudo.\n"); (void) fprintf(stderr, "You are already root, you don\'t need to use sudo.\n");
exit (1); exit(1);
} }
#endif #endif
/* loading the user global variable from the passwd file */ /*
* loading the user global variable from the passwd file
if ( (pw_ent = getpwuid( uid )) == NULL ) { */
sprintf ( user, "%u", uid ); if ((pw_ent = getpwuid(uid)) == NULL) {
log_error( GLOBAL_NO_PW_ENT ); (void) sprintf(user, "%u", uid);
inform_user ( GLOBAL_NO_PW_ENT ); log_error(GLOBAL_NO_PW_ENT);
exit (1); inform_user(GLOBAL_NO_PW_ENT);
exit(1);
} }
strncpy ( user, pw_ent -> pw_name, 8 ) [8] = '\0'; strncpy(user, pw_ent -> pw_name, 8)[8] = '\0';
/* loading the host global variable from gethostname() & gethostbyname() */ /*
* loading the host global variable from gethostname() & gethostbyname()
if (( gethostname ( host, MAXHOSTNAMELEN ))) { */
strcpy ( host, "amnesiac" ); if ((gethostname(host, MAXHOSTNAMELEN))) {
log_error ( GLOBAL_NO_HOSTNAME ); strcpy(host, "amnesiac");
inform_user ( GLOBAL_NO_HOSTNAME ); log_error(GLOBAL_NO_HOSTNAME);
} inform_user(GLOBAL_NO_HOSTNAME);
else { } else {
if ( ( h_ent = gethostbyname ( host) ) == NULL ) if ((h_ent = gethostbyname(host)) == NULL)
log_error ( GLOBAL_HOST_UNREGISTERED ); log_error(GLOBAL_HOST_UNREGISTERED);
else else
strcpy ( host, h_ent -> h_name ); strcpy(host, h_ent -> h_name);
/* We don't want to return the fully quallified name all the time... */
/*
* We don't want to return the fully quallified name all the time...
*/
#ifndef FQDN #ifndef FQDN
if ( (p = index ( host, '.' )) ) *p='\0'; if ((p = index(host, '.')))
*p = '\0';
#endif #endif
} }
@@ -226,7 +234,6 @@ else {
/********************************************************************** /**********************************************************************
* *
* usage() * usage()
@@ -236,13 +243,12 @@ else {
static void usage() static void usage()
{ {
fprintf( stderr, "usage: %s command\n", *Argv); (void) fprintf(stderr, "usage: %s command\n", *Argv);
exit (1); exit(1);
} }
/********************************************************************** /**********************************************************************
* *
* clean_envp() * clean_envp()
@@ -252,26 +258,27 @@ exit (1);
*/ */
void clean_envp(envp) void clean_envp(envp)
char **envp; char **envp;
{ {
int envlen; int envlen;
char ** tenvp; char **tenvp;
for ( envlen=0; envp[envlen]; envlen++ ) for (envlen = 0; envp[envlen]; envlen++); /* noop */
; /* noop */ ++envlen;
++envlen;
Envp = (char **) malloc ( sizeof (char **) * envlen ); Envp = (char **) malloc(sizeof(char **) * envlen);
if ( Envp == NULL ) { if (Envp == NULL) {
perror ("clean_envp: malloc"); perror("clean_envp: malloc");
exit (1); exit(1);
} }
/* omit all LD_* environmental vars */ /*
for ( tenvp=Envp; *envp; envp++ ) * omit all LD_* environmental vars
if ( strncmp ("LD_", *envp, 3) ) */
for (tenvp = Envp; *envp; envp++)
if (strncmp("LD_", *envp, 3))
*tenvp++ = *envp; *tenvp++ = *envp;
*tenvp = NULL; *tenvp = NULL;
} }

41
sudo.h
View File

@@ -120,20 +120,19 @@
#define MAXHOSTNAMELEN 64 #define MAXHOSTNAMELEN 64
#endif #endif
/* 48 chars is not enough */
#define MAXCOMMANDLENGTH MAXPATHLEN #define MAXCOMMANDLENGTH MAXPATHLEN
typedef union { typedef union {
int int_val; int int_val;
char char_val[MAXCOMMANDLENGTH]; char char_val[MAXCOMMANDLENGTH];
} YYSTYPE; } YYSTYPE;
typedef struct list { typedef struct list {
int type; int type;
char op; char op;
char *data; char *data;
struct list *next; struct list *next;
} LIST, *LINK; } LIST, *LINK;
#ifndef hpux #ifndef hpux
YYSTYPE yylval, yyval; YYSTYPE yylval, yyval;
@@ -141,10 +140,10 @@ YYSTYPE yylval, yyval;
YYSTYPE yylval; YYSTYPE yylval;
#endif #endif
/*
* SYSLOG should be defined in the makefile
*/
#ifdef SYSLOG /* SYSLOG should be defined in the makefile */ #ifdef SYSLOG
#include <syslog.h> #include <syslog.h>
#ifndef Syslog_ident #ifndef Syslog_ident
#define Syslog_ident "sudo" #define Syslog_ident "sudo"
@@ -171,12 +170,16 @@ YYSTYPE yylval;
#endif /* LOGFILE */ #endif /* LOGFILE */
#endif /* SYSLOG */ #endif /* SYSLOG */
/* Maximum number of characters to log per entry. */ /*
#ifndef MAXLOGLEN /* The syslogger will log this much, after that, */ * Maximum number of characters to log per entry.
#define MAXLOGLEN 990 /* it truncates the log line. We need this here */ * The syslogger will log this much, after that,
#endif /* to make sure that we get ellipses when the log */ * it truncates the log line. We need this here
/* line is longer than 990 characters. */ * to make sure that we get ellipses when the log
* line is longer than 990 characters.
*/
#ifndef MAXLOGLEN
#define MAXLOGLEN 990
#endif
#define VALIDATE_OK 0x00 #define VALIDATE_OK 0x00
#define VALIDATE_NO_USER 0x01 #define VALIDATE_NO_USER 0x01
@@ -226,6 +229,7 @@ void load_globals();
void log_error(); void log_error();
void inform_user(); void inform_user();
void check_user(); void check_user();
void clean_envp();
int validate(); int validate();
/* Most of these variables are declared in main() so they don't need /* Most of these variables are declared in main() so they don't need
@@ -240,16 +244,19 @@ extern uid_t uid;
extern char *host; extern char *host;
extern char *user; extern char *user;
extern char *cmnd; extern char *cmnd;
extern char **Argv;
extern int Argc; extern int Argc;
extern char **Argv;
extern char **Envp;
#endif #endif
extern int errno; extern int errno;
/* This is to placate hpux */ /*
* This is to placate hpux
*/
#ifdef hpux #ifdef hpux
#define setruid(__RUID) (setresuid((uid_t)(__RUID), (uid_t) -1, (uid_t) -1)) #define setruid(__RUID) (setresuid((uid_t)(__RUID), (uid_t) -1, (uid_t) -1))
#define getdtablesize() (sysconf(_SC_OPEN_MAX)) #define getdtablesize() (sysconf(_SC_OPEN_MAX))
#ifndef USE_CWD #ifndef USE_CWD
#define USE_CWD #define USE_CWD
#endif #endif /* USE_CWD */
#endif #endif /* hpux */