Listing 1: sudo.c
/*
** sudo.c
*/
/*
** Configurable constants
*/
#define SECURE_PATH "/bin:/usr/bin:/etc"
#define USERFILE "/usr/local/adm/sudoers"
#define LOGFILE "/usr/local/adm/sudolog"
#define TIMEDIR "/usr/local/adm/sudocheck/"
#define TIME 5 /* minutes */
#define SUDO_COP "root@localhost"
/*
** To install create the directories in the SECURE_PATH
** and TIMEDIR and the files USERFILE and LOGFILE.
** Set the owner of these files to root and the permissions
** to og-rw. Change the owner to root for the sudo program
** and set the permissions to 4111 (--s--x--x).
*/
#define BUFSIZE 256
#define SUCCESS 1
#define FAILED -1
#define CONFIG_ERR "Configuration error. " \
"Contact your security manager."
#define CONFIG_SUB "Invalid sudo configuration!"
#define SUID_ERR "Set UID bit not set."
#define STAT_ERR "Couldn't stat user file"
#define OWNER_ERR "User file not owned by root"
#define PERM_ERR "Invalid permissions on user file"
#define OPEN_ERR "Couldn't open user file"
#define USER_ERR "You are not set up to execute " \
"sudo on this machine."
#define USER_SUB "SECURITY** Invalid sudo user!"
#include <ctype.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
char *getpass();
char *crypt();
FILE *check_config(user)
char *user;
{
struct stat statb;
FILE *fp;
if ((setuid(0)) < 0) /* no setuid */
mail(CONFIG_SUB,user,SUID_ERR,CONFIG_ERR);
if (stat(USERFILE, &statb)) /* couldn't stat */
mail(CONFIG_SUB,user,STAT_ERR,CONFIG_ERR);
if (statb.st_uid != 0) /* must be owned by root */
mail(CONFIG_SUB,user,OWNER_ERR,CONFIG_ERR);
if (statb.st_mode & 044) /* should be og-rw */
mail(CONFIG_SUB,user,PERM_ERR,CONFIG_ERR);
if ((fp = fopen(USERFILE, "r")) == 0) /* open err */
mail(CONFIG_SUB,user,OPEN_ERR,CONFIG_ERR);
return(fp);
}
char *get_command_list(fp, name, password)
FILE *fp;
char *name;
char *password;
{
char buffer[BUFSIZ];
while ((fgets(buffer,BUFSIZ,fp)) != NULL)
{
if(buffer[0] == '#') continue; /* skip remarks */
if((strncmp(buffer,name,strlen(name))) == 0)
if (get_password(name,password))
return(buffer); /* valid user */
else
return(NULL); /* invalid password */
}
return(NULL); /* invalid user */
}
int get_password(name, password)
char *name;
char *password;
{
char fname[200];
char *paswd;
char *encrypted;
struct stat stab;
sprintf (fname, "%s/%s",TIMEDIR,name);
if (stat(fname, &stab) == 0)
{
if ((time(NULL) - stab.st_mtime) < (TIME * 60))
{
create_file(fname);
return (SUCCESS);
}
}
paswd = getpass("Password:");
encrypted = crypt(paswd,password);
if (strcmp(password, encrypted))
{
fprintf (stderr,"Password incorrect\n");
return(FAILED);
}
fflush (stderr);
fflush (stdout);
create_file(fname);
return (SUCCESS);
}
create_file(file)
char *file; /* filename to be created */
{
int descrip;
long timep[2];
if ((descrip = open(file, O_TRUNC|O_CREAT|O_WRONLY,
0700)) > 0)
{
close (descrip);
timep[0] = timep[1] = time(0);
utime (file, timep);
}
}
int checkdoer (dp, ap)
char *dp;
char *ap;
{
char *cp0, *cp1;
int not_flag = 0;
cp0 = dp;
while (isalnum (*cp0)) cp0++; /* skip past user */
while (*cp0) /* search until end of line */
{
while (isspace (*cp0)) cp0++; /* skip to cmd */
if (strncmp (cp0, "not",3) == 0) not_flag = 1;
if (strncmp (cp0, "all",3) == 0) return (success);
cp1 = cp0;
/* find end of this entry */
while (*cp1 != '\n' && !isspace(*cp1)) cp1++;
if (strncmp (cp0,ap,strlen(ap)) == 0)
{
cp1 = '\0';
if (not_flag) return(FAILED);
else return(SUCCESS);
}
/* move pointer past and keep looking */
while (!isspace (*cp0) && *cp0 != '\n') cp0++;
if (*cp0 == '\n') break; /* if EOL then fail */
else continue;
}
if (not_flag) return(SUCCESS);
else return(FAILED);
}
char *log(username, info, argc, argv)
char *username;
char *info;
int argc;
char **argv;
{
FILE *fp;
long now;
char ret_st[BUFSIZ];
if ((fp = fopen(LOGFILE,"a")) == NULL)
mail("WARNING sudo can't open logfile.",username,
LOGFILE,"");
now = time((long*) 0);
fprintf (fp, "%20.20s :", ctime(&now));
fprintf (fp, "%10.10s", info);
fprintf (fp, "%9.9s :",username);
while (argc--)
{
fprintf (fp, "%s ",*argv++);
sprintf (ret_st, "%s ",*argv++);
}
fprintf (fp,"\n");
(void) fclose (fp);
return(ret_st);
}
mail(subject,user,text,err_msg)
char *subject;
char *user;
char *text;
char *err_msg;
{
char hostname[MAXHOSTNAMELEN];
FILE *fd;
FILE *popen();
char cmd[80];
firsthostname (hostname, MAXHOSTNAMELEN);
(void) sprintf (cmd,"/usr/bin/mailx -s \"%s\" %s ",
subject,SUDO_COP);
if ((fd = popen (cmd, "w")) == NULL) return;
(void) fputs(text, fd);
(void) fputs ("\n\nThought you might want to know.",
fd);
(void) pclose(fd);
fprintf(stderr,"%s %s",err_msg,"\n");
exit(1);
}
firsthostname(n,l)
char *n;
int l;
{
(void) gethostname(n,l); /* get full hostname */
n[l-1] = 0; /* make sure null terminated */
if (n = strchr(n, '.')) *n = 0; /* put null on '.'*/
}
main(argc,argv)
int argc;
char **argv;
{
FILE *userfile;
struct passwd *user;
int uid;
char *valid_cmds;
char *progname;
char *cmd_line;
progname = argv[0];
if (argc < 2)
{
fprintf(stderr, "usage: %s cmd\n", progname);
exit(1);
}
uid = getuid();
user = getpwuid(uid);
userfile = check_config(user);
if ((valid_cmds = get_command_list(userfile,
user->pw_name,user->pw_passwd)) != NULL)
{
argv++, argc--;
if (checkdoer(valid_cmds,*argv) != FAILED)
{
putenv("PATH=" SECURE_PATH);
putenv("SHELL=/bin/false");
(void) log(user->pw_name,"",argc,argv);
execvp(*argv, argv); /* then do it */
perror(*argv);
}
else
{
(void) log(user->pw_name,"FAIL ",argc, argv);
fprintf(stderr,"%s: You are not set up to "
"execute %s with sudo on this machine.\n",
progname,*argv);
exit(1);
}
}
else
{
cmd_line = log(user->pw_name,"FAIL ",argc, argv);
mail(USER_SUB,user->pw_name,cmd_line,USER_ERR);
}
}
/* End of File */
|