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

235
check.c
View File

@@ -20,7 +20,7 @@
* them to include in future releases. Feel free to send them to: * them to include in future releases. Feel free to send them to:
* Jeff Nieusma nieusma@rootgroup.com * Jeff Nieusma nieusma@rootgroup.com
* 3959 Arbol CT (303) 447-8093 * 3959 Arbol CT (303) 447-8093
* Boulder, CO 80301-1752 * Boulder, CO 80301-1752
* *
******************************************************************* *******************************************************************
* *
@@ -46,13 +46,13 @@
char *getpass(); char *getpass();
static int check_timestamp(); static int check_timestamp();
static void check_passwd(); static void check_passwd();
static void update_timestamp(); static void update_timestamp();
static void reminder(); static void reminder();
static char *timestampfile_p; static char *timestampfile_p;
static int timedir_is_good; static int timedir_is_good;
/******************************************************************** /********************************************************************
@@ -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... */
check_passwd();
if ( rtn && uid ) /* if timestamp is not current... */ if (setuid(0)) { /* have to be root to play with timestamps */
check_passwd(); perror("setuid(0)");
exit(1);
if ( setuid (0) ) { /* have to be root to play with timestamps */
perror("setuid(0)");
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++='/' ) { timedir_is_good = 0;
*p='\0'; *p = '/';
if ( stat(timestampfile,&statbuf) < 0) { break;
if ( strcmp ( timestampfile, TIMEDIR ))
fprintf ( stderr, "Cannot stat() %s\n", timestampfile );
timedir_is_good = 0;
*p='/';
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 */
timestamp_is_old = 0; /* if file is recent, return(0) */ now = time((time_t *) NULL);
else if (now - statbuf.st_mtime < 60 * TIMEOUT)
timestamp_is_old = 1; /* else make 'em enter password */ timestamp_is_old = 0; /* if file is recent, return(0) */
else
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 {
timestamp_is_old = 1; /* user has to enter password */
if ( mkdir (TIMEDIR, 0700 ) ) { /* make the TIMEDIR directory */
perror("check_timestamp: mkdir");
timedir_is_good = 0;
}
else { else {
timedir_is_good = 1; /* TIMEDIR now exists */ timestamp_is_old = 1; /* user has to enter password */
reminder(); if (mkdir(TIMEDIR, 0700)) { /* make the TIMEDIR directory */
perror("check_timestamp: mkdir");
timedir_is_good = 0;
} else {
timedir_is_good = 1;/* TIMEDIR now exists */
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) {
(void) sprintf(user, "%u", uid);
log_error(GLOBAL_NO_PW_ENT);
inform_user(GLOBAL_NO_PW_ENT);
exit(1);
}
encrypted = pw_ent -> pw_passwd;
if ( (pw_ent = getpwuid( uid )) == NULL ) { /*
sprintf ( user, "%u", uid ); * you get TRIES_FOR_PASSWORD times to guess your password
log_error( GLOBAL_NO_PW_ENT ); */
inform_user ( GLOBAL_NO_PW_ENT ); while (counter > 0) {
exit (1); pass = getpass("Password:");
if (*pass == (char) NULL)
exit(0);
if (!strcmp(encrypted, crypt(pass, encrypted)))
return; /* if the passwd is correct return() */
--counter; /* otherwise, try again */
(void) fprintf(stderr, "%s\n", INCORRECT_PASSWORD);
} }
encrypted = pw_ent -> pw_passwd; log_error(PASSWORD_NOT_CORRECT);
inform_user(PASSWORD_NOT_CORRECT);
/* you get TRIES_FOR_PASSWORD times to guess your password */
while ( counter > 0 ) {
pass = getpass ( "Password:" );
if ( *pass == (char)NULL ) exit(0);
if ( !strcmp(encrypted, crypt(pass,encrypted)))
return; /* if the passwd is correct return() */
-- counter; /* otherwise, try again */
fprintf ( stderr, "%s\n", INCORRECT_PASSWORD );
}
log_error( 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

@@ -20,7 +20,7 @@
* them to include in future releases. Feel free to send them to: * them to include in future releases. Feel free to send them to:
* Jeff Nieusma nieusma@rootgroup.com * Jeff Nieusma nieusma@rootgroup.com
* 3959 Arbol CT (303) 447-8093 * 3959 Arbol CT (303) 447-8093
* Boulder, CO 80301-1752 * Boulder, CO 80301-1752
* *
******************************************************************* *******************************************************************
* *
@@ -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
*/ */
@@ -74,25 +73,29 @@ extern char *getwd();
char *find_path(file) char *find_path(file)
char *file; char *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);
} }
@@ -156,108 +163,118 @@ char *find_path(file)
*/ */
char *qualify(n) char *qualify(n)
char *n; /* name to make fully qualified */ char *n; /* name to make fully qualified */
{ {
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)
beg = end + 1; /* skip past the NULL */ beg = end + 1; /* skip past the NULL */
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';
} else { } else {
strcat(full, "/"); strcat(full, "/");
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);
} }
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 */
beg = NULL; /* since we have a new name */ beg = NULL; /* since we have a new name */
} }
} 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

@@ -24,7 +24,7 @@
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getpass.c based on 5.3 (Berkeley) 9/22/88"; static char sccsid[] = "@(#)getpass.c based on 5.3 (Berkeley) 9/22/88";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include <fcntl.h> #include <fcntl.h>
#include <sgtty.h> #include <sgtty.h>
@@ -33,69 +33,68 @@ 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)
struct termio ttyb; struct termio ttyb;
#else #else
struct sgttyb ttyb; struct sgttyb ttyb;
#endif #endif
register int ch; register int ch;
register char *p; register char *p;
FILE *fp, *outfp; FILE *fp, *outfp;
long omask; long omask;
int fd_tmp; int fd_tmp;
#if defined(sgi) #if defined(sgi)
tcflag_t svflagval; tcflag_t svflagval;
#else #else
int svflagval; int svflagval;
#endif #endif
#define PASSWD_LEN 8 #define PASSWD_LEN 8
static char buf[PASSWD_LEN + 1]; static char buf[PASSWD_LEN + 1];
/*
* read and write to /dev/tty if possible; else read from
* stdin and write to stderr.
*/
fd_tmp = open("/dev/tty", O_RDWR);
if (fd_tmp < 0 || (outfp = fp = fdopen(fd_tmp, "r+")) == NULL) {
outfp = stderr;
fp = stdin;
}
/*
* read and write to /dev/tty if possible; else read from stdin and write
* to stderr.
*/
fd_tmp = open("/dev/tty", O_RDWR);
if (fd_tmp < 0 || (outfp = fp = fdopen(fd_tmp, "r+")) == NULL) {
outfp = stderr;
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

520
logging.c
View File

@@ -20,7 +20,7 @@
* them to include in future releases. Feel free to send them to: * them to include in future releases. Feel free to send them to:
* Jeff Nieusma nieusma@rootgroup.com * Jeff Nieusma nieusma@rootgroup.com
* 3959 Arbol CT (303) 447-8093 * 3959 Arbol CT (303) 447-8093
* Boulder, CO 80301-1752 * Boulder, CO 80301-1752
* *
**************************************************************** ****************************************************************
* *
@@ -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,173 +59,177 @@ 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 ); (void) sprintf(logline, "%19.19s : %8.8s : ", ctime(&now), user);
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 */ /*
#ifdef USE_CWD * we need a pointer to the end of logline
getcwd(cwd, (size_t)(MAXPATHLEN+1)); /* so we know where we are... */ */
#else
getwd(cwd); /* so we know where we are... */
#endif
switch ( code ) {
case ALL_SYSTEMS_GO:
sprintf ( p, "PWD=%s ; COMMAND=", cwd );
#ifdef SYSLOG
pri=Syslog_priority_OK;
#endif
break;
case VALIDATE_NO_USER:
sprintf ( p, "user NOT in sudoers ; PWD=%s ; COMMAND=", cwd );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case VALIDATE_NOT_OK:
sprintf ( p, "command not allowed ; PWD=%s ; COMMAND=", cwd );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case VALIDATE_ERROR:
sprintf ( p, "error in %s ; PWD=%s ; command: ", SUDOERS, cwd );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case GLOBAL_NO_PW_ENT:
sprintf ( p, "There is no /etc/passwd entry for uid %d. ", uid );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case PASSWORD_NOT_CORRECT:
sprintf ( p, "%d incorrect passwords ; PWD=%s ; COMMAND=",
TRIES_FOR_PASSWORD, cwd );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case GLOBAL_NO_HOSTNAME:
strcat ( p, "This machine does not have a hostname " );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case NO_SUDOERS_FILE:
switch ( errno ) {
case ENOENT:
sprintf ( p, "There is no %s file. ", SUDOERS );
break;
case EACCES:
sprintf ( p, "%s needs to run setuid root. ", Argv[0] );
break;
default:
sprintf ( p, "There is a problem opening %s ", SUDOERS );
break;
}
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
case GLOBAL_HOST_UNREGISTERED:
sprintf ( p, "gethostbyname() cannot find host %s ", host );
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
default:
strcat ( p, "found a wierd error : ");
#ifdef SYSLOG
pri=Syslog_priority_NO;
#endif
break;
}
/* 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, " ");
argc = Argc-2;
argv = Argv; argv++;
p = logline + strlen(logline); p = logline + strlen(logline);
count = (int)(logline + MAXLOGLEN - p);
/* now stuff as much of the rest of the line as will fit */
while ( count > 0 && argc-- ) {
strncpy ( p, *++argv, count );
strcat ( p, " ");
p += 1 + (count < strlen(*argv) ? count : strlen(*argv) );
count = (int)(logline + MAXLOGLEN - p);
}
if ( count <= 0 ) /* if the line is too long, */
strcat ( p, " ... " ); /* add an elipsis to the end */
}
if ( appropriate(code) )
send_mail();
#ifdef SYSLOG
openlog ( Syslog_ident, Syslog_options, Syslog_facility );
syslog ( pri, logline );
closelog();
/*
* so we know where we are...
*/
#ifdef USE_CWD
getcwd(cwd, (size_t) (MAXPATHLEN + 1));
#else #else
getwd(cwd);
if ( (fp = fopen ( LOGFILE, "a" )) == NULL ) {
sprintf ( logline, "Can\'t open log file: %s", LOGFILE );
send_mail();
}
else {
fprintf ( fp, "%s\n", logline );
(void) fclose (fp);
}
#endif #endif
} switch (code) {
case ALL_SYSTEMS_GO:
(void) sprintf(p, "PWD=%s ; COMMAND=", cwd);
#ifdef SYSLOG
pri = Syslog_priority_OK;
#endif
break;
case VALIDATE_NO_USER:
(void) sprintf(p, "user NOT in sudoers ; PWD=%s ; COMMAND=", cwd);
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case VALIDATE_NOT_OK:
(void) sprintf(p, "command not allowed ; PWD=%s ; COMMAND=", cwd);
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case VALIDATE_ERROR:
(void) sprintf(p, "error in %s ; PWD=%s ; command: ", SUDOERS, cwd);
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case GLOBAL_NO_PW_ENT:
(void) sprintf(p, "There is no /etc/passwd entry for uid %d. ",
uid);
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case PASSWORD_NOT_CORRECT:
(void) sprintf(p, "%d incorrect passwords ; PWD=%s ; COMMAND=",
TRIES_FOR_PASSWORD, cwd);
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case GLOBAL_NO_HOSTNAME:
strcat(p, "This machine does not have a hostname ");
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case NO_SUDOERS_FILE:
switch (errno) {
case ENOENT:
(void) sprintf(p, "There is no %s file. ", SUDOERS);
break;
case EACCES:
(void) sprintf(p, "%s needs to run setuid root. ",
Argv[0]);
break;
default:
(void) sprintf(p, "There is a problem opening %s ",
SUDOERS);
break;
}
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
case GLOBAL_HOST_UNREGISTERED:
(void) sprintf(p, "gethostbyname() cannot find host %s ", host);
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
default:
strcat(p, "found a wierd error : ");
#ifdef SYSLOG
pri = Syslog_priority_NO;
#endif
break;
}
/*
* 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, " ");
argc = Argc - 2;
argv = Argv;
argv++;
p = logline + strlen(logline);
count = (int) (logline + MAXLOGLEN - p);
/*
* now stuff as much of the rest of the line as will fit
*/
while (count > 0 && argc--) {
strncpy(p, *++argv, count);
strcat(p, " ");
p += 1 + (count < strlen(*argv) ? count : strlen(*argv));
count = (int) (logline + MAXLOGLEN - p);
}
if (count <= 0) /* if the line is too long, */
strcat(p, " ... "); /* add an elipsis to the end */
}
if (appropriate(code))
send_mail();
#ifdef SYSLOG
openlog(Syslog_ident, Syslog_options, Syslog_facility);
syslog(pri, logline);
closelog();
#else
if ((fp = fopen(LOGFILE, "a")) == NULL) {
(void) sprintf(logline, "Can\'t open log file: %s", LOGFILE);
send_mail();
} else {
(void) fprintf(fp, "%s\n", logline);
(void) fclose(fp);
}
#endif
}
@@ -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(1);
(void) close (fd[0]); execve(mailer, exec_argv, Envp);
(void) close (fd[1]);
if ( ! fork () ) { /* this should not happen */
perror("execve");
exit(1);
} else { /* parent */
(void) close(0);
/* feed the data to sendmail */
(void) sprintf(buf, "To: %s\nSubject: %s\n\n%s\n\n",
ALERTMAIL, subject, logline);
write(1, buf, strlen(buf));
close(1);
/* child parent */ exit(0);
(void) close(1);
execv ( mailer, exec_argv );
/* this should not happen */
perror( "execv");
exit (1);
} }
else {
(void) close(0);
/* feed the data to sendmail */
sprintf (buf, "To: %s\nSubject: %s\n\n%s\n\n",
ALERTMAIL, subject, logline );
write ( 1, buf, strlen(buf));
close ( 1 );
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:
(void) fprintf(stderr,
"%s is not in the sudoers file. This incident will be reported.\n\n",
user);
break;
case VALIDATE_NO_USER: case VALIDATE_NOT_OK:
fprintf( stderr, (void) fprintf(stderr,
"%s is not in the sudoers file. This incident will be reported.\n\n", "Sorry, user %s is not allowed to execute %s\n\n",
user ); user, cmnd);
break; break;
case VALIDATE_NOT_OK: case VALIDATE_ERROR:
fprintf( stderr, (void) fprintf(stderr,
"Sorry, user %s is not allowed to execute %s\n\n", "Sorry, there is a fatal error in the sudoers file.\n\n");
user, cmnd ); break;
break;
case VALIDATE_ERROR:
fprintf( stderr,
"Sorry, there is a fatal error in the sudoers file.\n\n" );
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:
fprintf ( stderr,
"Something wierd happened.\n\n" );
break;
default:
(void) fprintf(stderr,
"Something wierd happened.\n\n");
break;
} }
} }
/**************************************************************** /****************************************************************
* *
* appropriate() * appropriate()
@@ -398,18 +384,19 @@ 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 */
return (0); return (0);
break; break;
case VALIDATE_NO_USER: case VALIDATE_NO_USER:
@@ -428,9 +415,10 @@ 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:
return (1); return (1);

684
parse.c
View File

@@ -20,15 +20,17 @@
* them to include in future releases. Feel free to send them to: * them to include in future releases. Feel free to send them to:
* Jeff Nieusma nieusma@rootgroup.com * Jeff Nieusma nieusma@rootgroup.com
* 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,357 +53,397 @@ 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'
*******************************************************************************/ /*
* diagnostic list printing utility that prints list 'list_num'
*/
void print_list(list_num) void print_list(list_num)
int list_num; int list_num;
{ {
LINK tmptmp_ptr; LINK tmptmp_ptr;
tmptmp_ptr = list_ptr[list_num]; tmptmp_ptr = list_ptr[list_num];
while (list_ptr[list_num] != NULL) { while (list_ptr[list_num] != NULL) {
printf("type = %d, op = %c, data = %s\n", list_ptr[list_num]->type, (void) printf("type = %d, op = %c, data = %s\n",
list_ptr[list_num]->op, list_ptr[list_num]->data); list_ptr[list_num] -> type,
tmp_ptr = list_ptr[list_num]; list_ptr[list_num] -> op, list_ptr[list_num] -> data);
list_ptr[list_num] = tmp_ptr->next; tmp_ptr = list_ptr[list_num];
list_ptr[list_num] = tmp_ptr -> next;
} }
list_ptr[list_num] = tmptmp_ptr; list_ptr[list_num] = tmptmp_ptr;
} }
/*******************************************************************************
* delete list utility that deletes list 'list_num'
*******************************************************************************/ /*
* delete list utility that deletes list 'list_num'
*/
void delete_list(list_num) void delete_list(list_num)
int list_num; int list_num;
{ {
while (list_ptr[list_num] != NULL) { while (list_ptr[list_num] != NULL) {
tmp_ptr = list_ptr[list_num]; tmp_ptr = list_ptr[list_num];
list_ptr[list_num] = tmp_ptr->next; list_ptr[list_num] = tmp_ptr -> next;
/* free(tmp_ptr); */ /* 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(). /*
*******************************************************************************/ * 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 call_back(token_type, op_type, data_string)
int token_type; int token_type;
char op_type; char op_type;
char *data_string; char *data_string;
{ {
/* all nodes start out in the extra list since the node name is received last */ /*
list_num = EXTRA_LIST; * 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 */ /*
if (strcmp(data_string, "Host_Alias") == 0) { * we have just build a "Host_Alias" list
list_num = HOST_LIST; */
if (num_host_alias > 0) { if (strcmp(data_string, "Host_Alias") == 0) {
reset_ptr->next = list_ptr[HOST_LIST]; list_num = HOST_LIST;
} if (num_host_alias > 0) {
num_host_alias++; reset_ptr -> next = list_ptr[HOST_LIST];
} }
/* we have just build a "Cmnd_Alias" list */ num_host_alias++;
else if (strcmp(data_string, "Cmnd_Alias") == 0) { }
list_num = CMND_LIST; /*
if (num_cmnd_alias > 0) { * we have just build a "Cmnd_Alias" list
reset_ptr->next = list_ptr[CMND_LIST]; */
} else if (strcmp(data_string, "Cmnd_Alias") == 0) {
num_cmnd_alias++; list_num = CMND_LIST;
} if (num_cmnd_alias > 0) {
/* we have just build a "User" list */ reset_ptr -> next = list_ptr[CMND_LIST];
else { }
list_num = USER_LIST; num_cmnd_alias++;
user_list_found = TRUE; }
} /*
new_list[EXTRA_LIST] = TRUE; * we have just build a "User" list
new_list[list_num] = FALSE; */
list_ptr[list_num] = list_ptr[EXTRA_LIST]; else {
list_num = USER_LIST;
user_list_found = TRUE;
}
new_list[EXTRA_LIST] = TRUE;
new_list[list_num] = FALSE;
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); reset_ptr = list_ptr[list_num];
new_list[list_num] = FALSE;
if (new_list[list_num] == TRUE) {
reset_ptr = list_ptr[list_num];
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 {
} new_list[list_num] = TRUE;
else { user_list_found = FALSE;
new_list[list_num] = TRUE; delete_list(list_num);
user_list_found = FALSE; }
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);
}
/* this case is the normal lowercase hostname */
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 {
save_ptr = list_ptr[HOST_LIST];
while (list_ptr[HOST_LIST] != NULL) {
if ((list_ptr[HOST_LIST]->type == TYPE2) &&
(strcmp(list_ptr[HOST_LIST]->data,
list_ptr[USER_LIST]->data) == 0)) {
next_type = list_ptr[HOST_LIST]->next->type;
tmp_ptr = list_ptr[HOST_LIST];
list_ptr[HOST_LIST] = tmp_ptr->next;
while (next_type == TYPE3) {
if (strcmp(list_ptr[HOST_LIST]->data, host) == 0) {
list_ptr[HOST_LIST] = save_ptr;
return(TRUE);
}
if (list_ptr[HOST_LIST]->next != NULL) {
next_type = list_ptr[HOST_LIST]->next->type;
tmp_ptr = list_ptr[HOST_LIST];
list_ptr[HOST_LIST] = tmp_ptr->next;
}
else {
next_type = ~TYPE3;
}
}
}
else {
tmp_ptr = list_ptr[HOST_LIST];
list_ptr[HOST_LIST] = tmp_ptr->next;
}
}
list_ptr[HOST_LIST] = save_ptr;
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.
*******************************************************************************/
int cmnd_type_ok()
{
/* 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 (cmnd[0] == '/') {
return(MATCH);
}
/* if the command does not have an absolute path, forget it */
else {
return(NO_MATCH);
}
}
/* if the command has an absolute path, check it out */
else if (list_ptr[USER_LIST]->data[0] == '/') {
/* op | data | return value
*---------------------------------
* ' ' | No Match | return(NO_MATCH)
* '!' | No Match | return(NO_MATCH)
* ' ' | A Match | return(MATCH)
* '!' | A Match | return(QUIT_NOW)
*
* these special cases are important in subtracting from the
* Universe of commands in something like:
* user machine=ALL,!/bin/rm,!/etc/named ...
*/ */
if (strcmp(list_ptr[USER_LIST]->data, cmnd) == 0) { if (strcmp(list_ptr[USER_LIST] -> data, "ALL") == 0) {
if (list_ptr[USER_LIST]->op == '!') { return (TRUE);
return(QUIT_NOW);
}
else {
return(MATCH);
}
}
else {
return(NO_MATCH);
}
} }
/* by now we have a Cmnd_Alias that will have to be expanded */ /*
else { * this case is the normal lowercase hostname
save_ptr = list_ptr[CMND_LIST]; */
while (list_ptr[CMND_LIST] != NULL) { else if (isupper(list_ptr[USER_LIST] -> data[0]) == FALSE) {
if ((list_ptr[CMND_LIST]->type == TYPE2) && return (strcmp(list_ptr[USER_LIST] -> data, host) == 0);
(strcmp(list_ptr[CMND_LIST]->data, }
list_ptr[USER_LIST]->data) == 0)) { /*
next_type = list_ptr[CMND_LIST]->next->type; * by now we have a Host_Alias that will have to be expanded
tmp_ptr = list_ptr[CMND_LIST]; */
list_ptr[CMND_LIST] = tmp_ptr->next; else {
while (next_type == TYPE3) { save_ptr = list_ptr[HOST_LIST];
if (strcmp(list_ptr[CMND_LIST]->data, cmnd) == 0) { while (list_ptr[HOST_LIST] != NULL) {
if (list_ptr[USER_LIST]->op == '!') { if ((list_ptr[HOST_LIST] -> type == TYPE2) &&
list_ptr[CMND_LIST] = save_ptr; (strcmp(list_ptr[HOST_LIST] -> data,
return(QUIT_NOW); list_ptr[USER_LIST] -> data) == 0)) {
} next_type = list_ptr[HOST_LIST] -> next -> type;
else { tmp_ptr = list_ptr[HOST_LIST];
list_ptr[CMND_LIST] = save_ptr; list_ptr[HOST_LIST] = tmp_ptr -> next;
return(MATCH); while (next_type == TYPE3) {
} if (strcmp(list_ptr[HOST_LIST] -> data, host) == 0) {
} list_ptr[HOST_LIST] = save_ptr;
if (list_ptr[CMND_LIST]->next != NULL) { return (TRUE);
next_type = list_ptr[CMND_LIST]->next->type; }
tmp_ptr = list_ptr[CMND_LIST]; if (list_ptr[HOST_LIST] -> next != NULL) {
list_ptr[CMND_LIST] = tmp_ptr->next; next_type = list_ptr[HOST_LIST] -> next -> type;
} tmp_ptr = list_ptr[HOST_LIST];
else { list_ptr[HOST_LIST] = tmp_ptr -> next;
next_type = ~TYPE3; } else {
} next_type = ~TYPE3;
} }
} }
else { } else {
tmp_ptr = list_ptr[CMND_LIST]; tmp_ptr = list_ptr[HOST_LIST];
list_ptr[CMND_LIST] = tmp_ptr->next; list_ptr[HOST_LIST] = tmp_ptr -> next;
} }
} }
list_ptr[CMND_LIST] = save_ptr; list_ptr[HOST_LIST] = save_ptr;
return(NO_MATCH); return (FALSE);
} }
} }
/*******************************************************************************
* 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
* or not the user will be able to execute the command on the host.
*******************************************************************************/
int cmnd_check()
{
int return_code;
while (list_ptr[USER_LIST] != NULL) {
if ((list_ptr[USER_LIST]->type == TYPE2) && host_type_ok()) {
next_type = list_ptr[USER_LIST]->next->type;
tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr->next;
while (next_type == TYPE3) {
return_code = cmnd_type_ok();
if (return_code == MATCH) {
return(VALIDATE_OK);
}
else if (return_code == QUIT_NOW) {
return(VALIDATE_NOT_OK);
}
if (list_ptr[USER_LIST]->next != NULL) {
next_type = list_ptr[USER_LIST]->next->type;
tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr->next;
}
else {
next_type = ~TYPE3;
}
}
}
else {
tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr->next;
}
}
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;
/* /*
* yyparse() returns with one of 3 values: 0) yyparse() worked fine; * this routine is called from cmnd_check() to resolve whether or not
* 1) yyparse() failed; FOUND_USER) the user was found and yyparse() * a user is permitted to perform a certain command on the already
* was returned from prematurely. * established host.
*/ */
return_code = yyparse();
/* don't need to keep this open... */ int cmnd_type_ok()
(void) fclose (sudoers_fp); {
/*
/* if a parsing error occurred, set return_code accordingly */ * check for the reserved keyword 'ALL'.
if (parse_error == TRUE) { */
return_code = PARSE_ERROR; if (strcmp(list_ptr[USER_LIST] -> data, "ALL") == 0) {
/* if the command has an absolute path, let them do it */
if (cmnd[0] == '/') {
return (MATCH);
}
/* if the command does not have an absolute path, forget it */
else {
return (NO_MATCH);
}
} }
/*
/* if the user was not found, set the return_code accordingly */ * if the command has an absolute path, check it out
if (found_user == FALSE) { */
return_code = NOT_FOUND_USER; else if (list_ptr[USER_LIST] -> data[0] == '/') {
/*
* op | data | return value
* ---------------------------------
* ' ' | No Match | return(NO_MATCH)
* '!' | No Match | return(NO_MATCH)
* ' ' | A Match | return(MATCH)
* '!' | A Match | return(QUIT_NOW)
*
* these special cases are important in subtracting from the Universe
* of commands in something like:
* user machine=ALL,!/bin/rm,!/etc/named ...
*/
if (strcmp(list_ptr[USER_LIST] -> data, cmnd) == 0) {
if (list_ptr[USER_LIST] -> op == '!') {
return (QUIT_NOW);
} else {
return (MATCH);
}
} else {
return (NO_MATCH);
}
} }
/*
/* handle the 3 cases individually &*/ * by now we have a Cmnd_Alias that will have to be expanded
switch(return_code) { */
case FOUND_USER: else {
return_code = cmnd_check(); save_ptr = list_ptr[CMND_LIST];
delete_list(USER_LIST); while (list_ptr[CMND_LIST] != NULL) {
delete_list(HOST_LIST); if ((list_ptr[CMND_LIST] -> type == TYPE2) &&
delete_list(CMND_LIST); (strcmp(list_ptr[CMND_LIST] -> data,
return(return_code); list_ptr[USER_LIST] -> data) == 0)) {
break; next_type = list_ptr[CMND_LIST] -> next -> type;
case NOT_FOUND_USER: tmp_ptr = list_ptr[CMND_LIST];
return(VALIDATE_NO_USER); list_ptr[CMND_LIST] = tmp_ptr -> next;
break; while (next_type == TYPE3) {
case PARSE_ERROR: if (strcmp(list_ptr[CMND_LIST] -> data, cmnd) == 0) {
return(VALIDATE_ERROR); if (list_ptr[USER_LIST] -> op == '!') {
break; list_ptr[CMND_LIST] = save_ptr;
return (QUIT_NOW);
} else {
list_ptr[CMND_LIST] = save_ptr;
return (MATCH);
}
}
if (list_ptr[CMND_LIST] -> next != NULL) {
next_type = list_ptr[CMND_LIST] -> next -> type;
tmp_ptr = list_ptr[CMND_LIST];
list_ptr[CMND_LIST] = tmp_ptr -> next;
} else {
next_type = ~TYPE3;
}
}
} else {
tmp_ptr = list_ptr[CMND_LIST];
list_ptr[CMND_LIST] = tmp_ptr -> next;
}
}
list_ptr[CMND_LIST] = save_ptr;
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
* or not the user will be able to execute the command on the host.
*/
int cmnd_check()
{
int return_code;
while (list_ptr[USER_LIST] != NULL) {
if ((list_ptr[USER_LIST] -> type == TYPE2) && host_type_ok()) {
next_type = list_ptr[USER_LIST] -> next -> type;
tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr -> next;
while (next_type == TYPE3) {
return_code = cmnd_type_ok();
if (return_code == MATCH) {
return (VALIDATE_OK);
} else if (return_code == QUIT_NOW) {
return (VALIDATE_NOT_OK);
}
if (list_ptr[USER_LIST] -> next != NULL) {
next_type = list_ptr[USER_LIST] -> next -> type;
tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr -> next;
} else {
next_type = ~TYPE3;
}
}
} else {
tmp_ptr = list_ptr[USER_LIST];
list_ptr[USER_LIST] = tmp_ptr -> next;
}
}
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;
/*
* yyparse() returns with one of 3 values: 0) yyparse() worked fine;
* 1) yyparse() failed; FOUND_USER) the user was found and yyparse()
* was returned from prematurely.
*/
return_code = yyparse();
/*
* don't need to keep this open...
*/
(void) fclose(sudoers_fp);
/*
* if a parsing error occurred, set return_code accordingly
*/
if (parse_error == TRUE) {
return_code = PARSE_ERROR;
}
/*
* if the user was not found, set the return_code accordingly
*/
if (found_user == FALSE) {
return_code = NOT_FOUND_USER;
}
/*
* handle the 3 cases individually
*/
switch (return_code) {
case FOUND_USER:
return_code = cmnd_check();
delete_list(USER_LIST);
delete_list(HOST_LIST);
delete_list(CMND_LIST);
return (return_code);
break;
case NOT_FOUND_USER:
return (VALIDATE_NO_USER);
break;
case PARSE_ERROR:
return (VALIDATE_ERROR);
break;
} }
} }

239
sudo.c
View File

@@ -20,7 +20,7 @@
* them to include in future releases. Feel free to send them to: * them to include in future releases. Feel free to send them to:
* Jeff Nieusma nieusma@rootgroup.com * Jeff Nieusma nieusma@rootgroup.com
* 3959 Arbol CT (303) 447-8093 * 3959 Arbol CT (303) 447-8093
* Boulder, CO 80301-1752 * Boulder, CO 80301-1752
* *
************************************************************************** **************************************************************************
* *
@@ -56,7 +56,7 @@
#include "sudo.h" #include "sudo.h"
extern char *malloc(); extern char *malloc();
int Argc; int Argc;
char **Argv; char **Argv;
char **Envp; char **Envp;
char *host; char *host;
@@ -78,74 +78,79 @@ 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 /*
* clean slate from which to work. * close all file descriptors to make sure we have a nice
*/ * clean slate from which to work.
for ( rtn = getdtablesize() - 1 ; rtn > 3; rtn -- ) */
(void)close(rtn); for (rtn = getdtablesize() - 1; rtn > 3; 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);
} }
execve(cmnd, &Argv[1], Envp); execve(cmnd, &Argv[1], Envp);
perror(cmnd); perror(cmnd);
break; break;
case VALIDATE_NO_USER: case VALIDATE_NO_USER:
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) ) */
*tenvp++ = *envp; for (tenvp = Envp; *envp; envp++)
if (strncmp("LD_", *envp, 3))
*tenvp = NULL; *tenvp++ = *envp;
*tenvp = NULL;
} }

87
sudo.h
View File

@@ -24,27 +24,27 @@
*/ */
/* The following macros can be defined when compiling /* The following macros can be defined when compiling
FQDN - if you have fully qualified hostnames FQDN - if you have fully qualified hostnames
in your SUDOERS files in your SUDOERS files
SYSLOG - if you want to use syslog instead SYSLOG - if you want to use syslog instead
of a log file of a log file
( This is a nice feature. You can ( This is a nice feature. You can
collect all you sudo logs at a collect all you sudo logs at a
central host. The default is for central host. The default is for
sudo to log at the local2 facility. ) sudo to log at the local2 facility. )
SEND_MAIL_WHEN_NOT_OK - if you want a message sent to ALERTMAIL SEND_MAIL_WHEN_NOT_OK - if you want a message sent to ALERTMAIL
when the user is in the SUDOERS but when the user is in the SUDOERS but
does not have permission to execute does not have permission to execute
the command entered the command entered
( This can be used at paranoid sites ) ( This can be used at paranoid sites )
SEND_MAIL_WHEN_NO_USER - if you want a message sent to ALERTMAIL SEND_MAIL_WHEN_NO_USER - if you want a message sent to ALERTMAIL
when the user is not in the SUDOERS file when the user is not in the SUDOERS file
( This is generally the case ) ( This is generally the case )
BROKEN_GETPASS - if your os has a broken version of getpass() BROKEN_GETPASS - if your os has a broken version of getpass()
sysV and variants are suspect. Test by sysV and variants are suspect. Test by
doing an rsh host "sudo echo hi" when doing an rsh host "sudo echo hi" when
@@ -56,33 +56,33 @@
rsh hostname "sudo whoami" and see if getpass rsh hostname "sudo whoami" and see if getpass
will read from stdin as well as /dev/tty. will read from stdin as well as /dev/tty.
If not, define BROKEN_GETPASS. If not, define BROKEN_GETPASS.
USE_CWD - if your os has getcwd() and not getwd() USE_CWD - if your os has getcwd() and not getwd()
you should define this (done automatically you should define this (done automatically
for hpux) for hpux)
NEED_STRDUP - if your os lacks strdup(3) you need to NEED_STRDUP - if your os lacks strdup(3) you need to
define this define this
SHORT_MESSAGE - if you don't want a copyright notice when SHORT_MESSAGE - if you don't want a copyright notice when
someone runs sudo for the first time someone runs sudo for the first time
*/ */
#ifndef TIMEDIR #ifndef TIMEDIR
#define TIMEDIR "/tmp/.odus" #define TIMEDIR "/tmp/.odus"
#endif #endif
#ifndef TIMEOUT #ifndef TIMEOUT
#define TIMEOUT 5 #define TIMEOUT 5
#endif #endif
#ifndef TRIES_FOR_PASSWORD #ifndef TRIES_FOR_PASSWORD
#define TRIES_FOR_PASSWORD 3 #define TRIES_FOR_PASSWORD 3
#endif #endif
#ifndef INCORRECT_PASSWORD #ifndef INCORRECT_PASSWORD
#define INCORRECT_PASSWORD "Sorry, try again." #define INCORRECT_PASSWORD "Sorry, try again."
#endif #endif
/* /*
@@ -93,47 +93,46 @@
*/ */
#ifndef MAILER #ifndef MAILER
#define MAILER "/usr/lib/sendmail" #define MAILER "/usr/lib/sendmail"
#endif #endif
#ifndef MAILSUBJECT #ifndef MAILSUBJECT
#define MAILSUBJECT "*** SECURITY information ***" #define MAILSUBJECT "*** SECURITY information ***"
#endif #endif
#ifndef ALERTMAIL #ifndef ALERTMAIL
#define ALERTMAIL "root" #define ALERTMAIL "root"
#endif #endif
#ifndef SUDOERS #ifndef SUDOERS
#define SUDOERS "/etc/sudoers" #define SUDOERS "/etc/sudoers"
#endif #endif
#ifndef TMPSUDOERS #ifndef TMPSUDOERS
#define TMPSUDOERS "/etc/stmp" #define TMPSUDOERS "/etc/stmp"
#endif #endif
#ifndef EDITOR #ifndef EDITOR
#define EDITOR "/usr/ucb/vi" #define EDITOR "/usr/ucb/vi"
#endif #endif
#ifndef MAXHOSTNAMELEN #ifndef MAXHOSTNAMELEN
#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"
@@ -158,7 +157,7 @@ YYSTYPE yylval;
#ifndef Syslog_priority_OK #ifndef Syslog_priority_OK
#define Syslog_priority_OK LOG_NOTICE #define Syslog_priority_OK LOG_NOTICE
#endif #endif
#ifndef Syslog_priority_NO #ifndef Syslog_priority_NO
#define Syslog_priority_NO LOG_ALERT #define Syslog_priority_NO LOG_ALERT
#endif #endif
#else #else
@@ -167,16 +166,20 @@ YYSTYPE yylval;
#define LOGFILE "/var/adm/sudo.log" #define LOGFILE "/var/adm/sudo.log"
#else #else
#define LOGFILE "/usr/adm/sudo.log" #define LOGFILE "/usr/adm/sudo.log"
#endif /* /var vs. /usr */ #endif /* /var vs. /usr */
#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, */
#define MAXLOGLEN 990 /* it truncates the log line. We need this here */
#endif /* to make sure that we get ellipses when the log */
/* line is longer than 990 characters. */
/*
* Maximum number of characters to log per entry.
* The syslogger will log this much, after that,
* it truncates the log line. We need this here
* 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 int Argc;
extern char **Argv; extern char **Argv;
extern int Argc; 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 */