Initial revision
This commit is contained in:
276
check.c
Normal file
276
check.c
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* sudo version 1.1 allows users to execute commands as root
|
||||||
|
* Copyright (C) 1991 The Root Group, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 1, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
* If you make modifications to the source, we would be happy to have
|
||||||
|
* them to include in future releases. Feel free to send them to:
|
||||||
|
* Jeff Nieusma nieusma@rootgroup.com
|
||||||
|
* 3959 Arbol CT (303) 447-8093
|
||||||
|
* Boulder, CO 80301-1752
|
||||||
|
*
|
||||||
|
*******************************************************************
|
||||||
|
*
|
||||||
|
* check.c
|
||||||
|
*
|
||||||
|
* check_user() only returns if the user's timestamp file
|
||||||
|
* is current or if they enter a correct password.
|
||||||
|
*
|
||||||
|
* Jeff Nieusma Thu Mar 21 22:39:07 MST 1991
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include "sudo.h"
|
||||||
|
|
||||||
|
char *getpass();
|
||||||
|
|
||||||
|
static int check_timestamp();
|
||||||
|
static void check_passwd();
|
||||||
|
static void update_timestamp();
|
||||||
|
static void reminder();
|
||||||
|
static char *timestampfile_p;
|
||||||
|
|
||||||
|
static int timedir_is_good;
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
*
|
||||||
|
* check_user()
|
||||||
|
*
|
||||||
|
* This function only returns if the user can successfully
|
||||||
|
* verify who s/he is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void check_user()
|
||||||
|
{
|
||||||
|
register int rtn;
|
||||||
|
|
||||||
|
umask ( 077 ); /* make sure the timestamp files are private */
|
||||||
|
|
||||||
|
if ( setuid (0) ) { /* have to be root to see timestamps */
|
||||||
|
perror("setuid(0)");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
rtn = check_timestamp();
|
||||||
|
if ( setruid (uid) ) { /* don't want to be root longer than necessary */
|
||||||
|
#ifndef _AIX
|
||||||
|
perror("setruid(uid)");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rtn && uid ) /* if timestamp is not current... */
|
||||||
|
check_passwd();
|
||||||
|
|
||||||
|
if ( setuid (0) ) { /* have to be root to play with timestamps */
|
||||||
|
perror("setuid(0)");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
update_timestamp();
|
||||||
|
if ( setruid (uid) ) { /* don't want to be root longer than necessary */
|
||||||
|
#ifndef _AIX
|
||||||
|
perror("setruid(uid)");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
umask ( 022 ); /* want a real umask to exec() the command */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
*
|
||||||
|
* check_timestamp()
|
||||||
|
*
|
||||||
|
* this function checks the timestamp file. If it is within
|
||||||
|
* TIMEOUT minutes, no password will be required
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int check_timestamp()
|
||||||
|
{
|
||||||
|
static char timestampfile[MAXPATHLEN+1];
|
||||||
|
register char *p;
|
||||||
|
struct stat statbuf;
|
||||||
|
register int timestamp_is_old = -1;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
|
||||||
|
sprintf ( timestampfile, "%s/%s", TIMEDIR, user );
|
||||||
|
timestampfile_p = timestampfile;
|
||||||
|
|
||||||
|
timedir_is_good = 1; /* now there's an assumption for ya... */
|
||||||
|
|
||||||
|
|
||||||
|
/* walk through the path one directory at a time */
|
||||||
|
|
||||||
|
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;
|
||||||
|
*p='/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( timedir_is_good ) { /* if all the directories are stat()able */
|
||||||
|
if ( stat(timestampfile, &statbuf) ) { /* does the file exist? */
|
||||||
|
if ( uid ) reminder(); /* if not, do the reminder */
|
||||||
|
timestamp_is_old=1; /* and return (1) */
|
||||||
|
}
|
||||||
|
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) */
|
||||||
|
else
|
||||||
|
timestamp_is_old = 1; /* else make 'em enter password */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 {
|
||||||
|
timedir_is_good = 1; /* TIMEDIR now exists */
|
||||||
|
reminder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (timestamp_is_old);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
*
|
||||||
|
* update_timestamp()
|
||||||
|
*
|
||||||
|
* This function changes the timestamp to now
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void update_timestamp()
|
||||||
|
{
|
||||||
|
register int fd;
|
||||||
|
|
||||||
|
if ( timedir_is_good ) {
|
||||||
|
unlink ( timestampfile_p );
|
||||||
|
if (( fd = open (timestampfile_p, O_WRONLY|O_CREAT|O_TRUNC, 0600 )) < 0 )
|
||||||
|
perror( "update_timestamp: open" );
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
*
|
||||||
|
* check_passwd()
|
||||||
|
*
|
||||||
|
* This function grabs the user's password and checks with
|
||||||
|
* the password in /etc/passwd
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void check_passwd()
|
||||||
|
{
|
||||||
|
char *crypt();
|
||||||
|
struct passwd *pw_ent;
|
||||||
|
char *encrypted; /* this comes from /etc/passwd */
|
||||||
|
char *pass; /* this is what gets entered */
|
||||||
|
register int counter=TRIES_FOR_PASSWORD;
|
||||||
|
|
||||||
|
|
||||||
|
if ( (pw_ent = getpwuid( uid )) == NULL ) {
|
||||||
|
sprintf ( user, "%u", uid );
|
||||||
|
log_error( GLOBAL_NO_PW_ENT );
|
||||||
|
inform_user ( GLOBAL_NO_PW_ENT );
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypted = pw_ent -> pw_passwd;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
*
|
||||||
|
* reminder()
|
||||||
|
*
|
||||||
|
* this function just prints the the reminder message
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void reminder()
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef SHORT_MESSAGE
|
||||||
|
fprintf(stderr,"\n%s\n%s\n\n%s\n%s\n\n",
|
||||||
|
#else
|
||||||
|
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 comes with ABSOLUTELY NO WARRANTY. This is free software,",
|
||||||
|
" and you are welcome to redistribute it under certain conditions.",
|
||||||
|
#endif
|
||||||
|
|
||||||
|
"We trust you have received the usual lecture from the local Systems",
|
||||||
|
"Administrator. It usually boils down to these two things:",
|
||||||
|
|
||||||
|
" #1) Respect the privacy of others.",
|
||||||
|
" #2) Think before you type."
|
||||||
|
);
|
||||||
|
}
|
440
logging.c
Normal file
440
logging.c
Normal file
@@ -0,0 +1,440 @@
|
|||||||
|
/*
|
||||||
|
* sudo version 1.1 allows users to execute commands as root
|
||||||
|
* Copyright (C) 1991 The Root Group, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 1, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
* If you make modifications to the source, we would be happy to have
|
||||||
|
* them to include in future releases. Feel free to send them to:
|
||||||
|
* Jeff Nieusma nieusma@rootgroup.com
|
||||||
|
* 3959 Arbol CT (303) 447-8093
|
||||||
|
* Boulder, CO 80301-1752
|
||||||
|
*
|
||||||
|
****************************************************************
|
||||||
|
*
|
||||||
|
* logging.c
|
||||||
|
*
|
||||||
|
* this file supports the general logging facilities
|
||||||
|
* if you want to change any error messages, this is probably
|
||||||
|
* the place to be...
|
||||||
|
*
|
||||||
|
* Jeff Nieusma Thu Mar 21 23:39:04 MST 1991
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include "sudo.h"
|
||||||
|
|
||||||
|
void log_error();
|
||||||
|
void readchild();
|
||||||
|
static void send_mail();
|
||||||
|
static void reapchild();
|
||||||
|
static int appropriate();
|
||||||
|
|
||||||
|
static char logline[MAXLOGLEN+8];
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* log_error()
|
||||||
|
*
|
||||||
|
* This function attempts to deliver mail to ALERTMAIL and either
|
||||||
|
* syslogs the error or writes it to the log file
|
||||||
|
*/
|
||||||
|
|
||||||
|
void log_error( code )
|
||||||
|
int code;
|
||||||
|
{
|
||||||
|
char cwd[MAXPATHLEN+1];
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
register char *p;
|
||||||
|
register int count;
|
||||||
|
#ifndef SYSLOG
|
||||||
|
register FILE *fp;
|
||||||
|
time_t now;
|
||||||
|
#else
|
||||||
|
register int pri; /* syslog priority */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* there is no need to log the date and time twice if using syslog */
|
||||||
|
|
||||||
|
#ifndef SYSLOG
|
||||||
|
now=time ( (time_t) 0 );
|
||||||
|
sprintf( logline, "%19.19s : %8.8s : ", ctime (&now), user );
|
||||||
|
#else
|
||||||
|
sprintf( logline, "%8.8s : ", user );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p = logline + strlen(logline); /* we need a pointer to the end of logline */
|
||||||
|
#ifdef hpux
|
||||||
|
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);
|
||||||
|
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 ) {
|
||||||
|
sprintf ( logline, "Can\'t open log file: %s", LOGFILE );
|
||||||
|
send_mail();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf ( fp, "%s\n", logline );
|
||||||
|
(void) fclose (fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* send_mail()
|
||||||
|
*
|
||||||
|
* This function attempts to mail to ALERTMAIL about the sudo error
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *exec_argv[]= { "sendmail" ,
|
||||||
|
"-t" ,
|
||||||
|
ALERTMAIL ,
|
||||||
|
(char *) NULL };
|
||||||
|
|
||||||
|
|
||||||
|
static void send_mail()
|
||||||
|
{
|
||||||
|
char *mailer=MAILER;
|
||||||
|
char *subject=MAILSUBJECT;
|
||||||
|
int fd[2];
|
||||||
|
char buf[MAXLOGLEN+1024];
|
||||||
|
|
||||||
|
if ( (mailer = find_path ( mailer )) == NULL ) {
|
||||||
|
fprintf (stderr, "%s not found\n", mailer );
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal ( SIGCHLD, reapchild );
|
||||||
|
|
||||||
|
if ( fork () ) return;
|
||||||
|
|
||||||
|
/* we don't want any security problems ... */
|
||||||
|
if ( setuid ( uid ) ) {
|
||||||
|
perror("setuid(uid)");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal ( SIGHUP, SIG_IGN );
|
||||||
|
signal ( SIGINT, SIG_IGN );
|
||||||
|
signal ( SIGQUIT, SIG_IGN );
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
if ( ! fork () ) {
|
||||||
|
|
||||||
|
|
||||||
|
/* child parent */
|
||||||
|
|
||||||
|
(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()
|
||||||
|
*
|
||||||
|
* This function gets rid fo all the ugly zombies
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void reapchild ()
|
||||||
|
{
|
||||||
|
(void) wait ( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* inform_user ()
|
||||||
|
*
|
||||||
|
* This function lets the user know what is happening
|
||||||
|
* when an error occurs
|
||||||
|
*/
|
||||||
|
|
||||||
|
void inform_user( code )
|
||||||
|
int code;
|
||||||
|
{
|
||||||
|
|
||||||
|
switch ( code ) {
|
||||||
|
|
||||||
|
case VALIDATE_NO_USER:
|
||||||
|
fprintf( stderr,
|
||||||
|
"%s is not in the sudoers file. This incident will be reported.\n\n",
|
||||||
|
user );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALIDATE_NOT_OK:
|
||||||
|
fprintf( stderr,
|
||||||
|
"Sorry, user %s is not allowed to execute %s\n\n",
|
||||||
|
user, cmnd );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALIDATE_ERROR:
|
||||||
|
fprintf( stderr,
|
||||||
|
"Sorry, there is a fatal error in the sudoers file.\n\n" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLOBAL_NO_PW_ENT:
|
||||||
|
fprintf ( stderr,
|
||||||
|
"Intruder Alert! You don\'t exist in the passwd file\n\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLOBAL_NO_HOSTNAME:
|
||||||
|
fprintf ( stderr,
|
||||||
|
"This machine does not have a hostname\n\n" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLOBAL_HOST_UNREGISTERED:
|
||||||
|
fprintf ( stderr,
|
||||||
|
"This machine is not available via gethostbyname()\n\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PASSWORD_NOT_CORRECT:
|
||||||
|
fprintf ( stderr, "Password not entered correctly after %d tries\n\n",
|
||||||
|
TRIES_FOR_PASSWORD );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf ( stderr,
|
||||||
|
"Something wierd happened.\n\n" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
*
|
||||||
|
* appropriate()
|
||||||
|
*
|
||||||
|
* This function determines whether to send mail or not...
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int appropriate( code )
|
||||||
|
int code;
|
||||||
|
{
|
||||||
|
|
||||||
|
switch ( code ) {
|
||||||
|
|
||||||
|
/* these will NOT send mail */
|
||||||
|
|
||||||
|
case VALIDATE_OK:
|
||||||
|
case PASSWORD_NOT_CORRECT:
|
||||||
|
/* case ALL_SYSTEMS_GO: this is the same as OK */
|
||||||
|
return (0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALIDATE_NO_USER:
|
||||||
|
#ifdef SEND_MAIL_WHEN_NO_USER
|
||||||
|
return (1);
|
||||||
|
#else
|
||||||
|
return (0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VALIDATE_NOT_OK:
|
||||||
|
#ifdef SEND_MAIL_WHEN_NOT_OK
|
||||||
|
return (1);
|
||||||
|
#else
|
||||||
|
return (0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* these WILL send mail */
|
||||||
|
|
||||||
|
case VALIDATE_ERROR:
|
||||||
|
case NO_SUDOERS_FILE:
|
||||||
|
default:
|
||||||
|
return (1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
405
parse.c
Normal file
405
parse.c
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
* sudo version 1.1 allows users to execute commands as root
|
||||||
|
* Copyright (C) 1991 The Root Group, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 1, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
* If you make modifications to the source, we would be happy to have
|
||||||
|
* them to include in future releases. Feel free to send them to:
|
||||||
|
* Jeff Nieusma nieusma@rootgroup.com
|
||||||
|
* 3959 Arbol CT (303) 447-8093
|
||||||
|
* Boulder, CO 80301-1752
|
||||||
|
*
|
||||||
|
********************************************************************************
|
||||||
|
* parse.c, sudo project
|
||||||
|
* David R. Hieb
|
||||||
|
* March 18, 1991
|
||||||
|
*
|
||||||
|
* routines to implement and maintain the parsing and list management.
|
||||||
|
*******************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "sudo.h"
|
||||||
|
|
||||||
|
/* there are 3 main lists (User, Host_Alias, Cmnd_Alias) and 1 extra list */
|
||||||
|
#define NUM_LISTS 3+1
|
||||||
|
|
||||||
|
extern char *user, *host, *cmnd;
|
||||||
|
extern FILE *yyin, *yyout;
|
||||||
|
|
||||||
|
int user_list_found = FALSE;
|
||||||
|
int list_num, new_list[NUM_LISTS];
|
||||||
|
int parse_error = FALSE, found_user = FALSE;
|
||||||
|
int next_type, num_host_alias = 0, num_cmnd_alias = 0;
|
||||||
|
LINK tmp_ptr, reset_ptr, save_ptr, list_ptr[NUM_LISTS];
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* inserts a node into list 'list_num' and updates list_ptr[list_num]
|
||||||
|
*******************************************************************************/
|
||||||
|
void insert_member(list_num, token_type, op_type, data_string)
|
||||||
|
int token_type, list_num;
|
||||||
|
char op_type;
|
||||||
|
char *data_string;
|
||||||
|
{
|
||||||
|
tmp_ptr = (LINK)malloc(sizeof(LIST));
|
||||||
|
tmp_ptr->type = token_type;
|
||||||
|
tmp_ptr->op = op_type;
|
||||||
|
tmp_ptr->data = (char *)malloc(strlen(data_string)+1);
|
||||||
|
strcpy(tmp_ptr->data, data_string);
|
||||||
|
tmp_ptr->next = (new_list[list_num] == TRUE) ? NULL : list_ptr[list_num];
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if the last received node is TYPE1, then we can classify the list
|
||||||
|
* and effectively transfer the extra list to the correct list type.
|
||||||
|
*/
|
||||||
|
if (token_type == TYPE1) {
|
||||||
|
/* we have just build a "Host_Alias" list */
|
||||||
|
if (strcmp(data_string, "Host_Alias") == 0) {
|
||||||
|
list_num = HOST_LIST;
|
||||||
|
if (num_host_alias > 0) {
|
||||||
|
reset_ptr->next = list_ptr[HOST_LIST];
|
||||||
|
}
|
||||||
|
num_host_alias++;
|
||||||
|
}
|
||||||
|
/* we have just build a "Cmnd_Alias" list */
|
||||||
|
else if (strcmp(data_string, "Cmnd_Alias") == 0) {
|
||||||
|
list_num = CMND_LIST;
|
||||||
|
if (num_cmnd_alias > 0) {
|
||||||
|
reset_ptr->next = list_ptr[CMND_LIST];
|
||||||
|
}
|
||||||
|
num_cmnd_alias++;
|
||||||
|
}
|
||||||
|
/* we have just build a "User" 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);
|
||||||
|
|
||||||
|
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
|
||||||
|
* 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
|
||||||
|
* nodes and start over again looking for the user.
|
||||||
|
*/
|
||||||
|
if (user_list_found == TRUE) {
|
||||||
|
if (list_ptr[list_num]->type == TYPE1 &&
|
||||||
|
strcmp(list_ptr[list_num]->data, user) == 0) {
|
||||||
|
return(FOUND_USER);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new_list[list_num] = TRUE;
|
||||||
|
user_list_found = FALSE;
|
||||||
|
delete_list(list_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*******************************************************************************/
|
||||||
|
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) {
|
||||||
|
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 (list_ptr[USER_LIST]->op == '!') {
|
||||||
|
return(QUIT_NOW);
|
||||||
|
}
|
||||||
|
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];
|
||||||
|
while (list_ptr[CMND_LIST] != NULL) {
|
||||||
|
if ((list_ptr[CMND_LIST]->type == TYPE2) &&
|
||||||
|
(strcmp(list_ptr[CMND_LIST]->data,
|
||||||
|
list_ptr[USER_LIST]->data) == 0)) {
|
||||||
|
next_type = list_ptr[CMND_LIST]->next->type;
|
||||||
|
tmp_ptr = list_ptr[CMND_LIST];
|
||||||
|
list_ptr[CMND_LIST] = tmp_ptr->next;
|
||||||
|
while (next_type == TYPE3) {
|
||||||
|
if (strcmp(list_ptr[CMND_LIST]->data, cmnd) == 0) {
|
||||||
|
if (list_ptr[USER_LIST]->op == '!') {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user