Cover V01, I04
Article
Figure 1
Listing 1

nov92.tar


Listing 1: sukill.c

/* ================================================= */
/*
sukill.c
Steve Isaacson

make it set-uid root
chown root filename
chmod 4755 filename
*/
/* ================================================= */

#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>

extern int errno;
extern char *sys_errlist[];
void log_user_info(), log_date(), plog();

#define MAX_BUF  200
#define MAX_LINE 100
#define MAX_PID  100
/* no pid less than MAX_PID may be killed */

char *fn_log   = "/usr/lib/sukill/sukill.log";
char *fn_deny  = "/usr/lib/sukill/sukill.deny";
char *fn_allow = "/usr/lib/sukill/sukill.allow";

main (argc, argv)
int argc;
char *argv[];
{
FILE *fp_log;
int i, pid, uid, signal=SIGTERM, arg_start=1;
char buf[MAX_BUF], tempbuf[MAX_BUF];
char *username, *getlogin();

if ( argc == 1 ) {
fprintf ( stderr,
"usage: %s [ -signo ] pid ...\n", argv[0] );
exit(1);
}

if ((username = getlogin()) == NULL) {
fprintf(stderr, "Who are you?\n");
exit(1);
}

/* is the user denied? */
if ( fexist(fn_deny) ) {
if ( in_file (username, fn_deny) ) {
fprintf(stderr, "permission denied\n");
exit(1);
}
}

/* is the user allowed? */
if ( fexist(fn_allow) ) {

if ( ! in_file(username, fn_allow) ) {
fprintf(stderr, "no permission\n");

exit(1);
}
}

/* open the log file */
if ( (fp_log=fopen( fn_log, "a")) == NULL ) {
fprintf ( stderr,
"Error reading file (%s)\n", fn_log );
exit(1);
}

/* record user name and command-line arguments */
fprintf(fp_log, "\n%s: ", username);
for ( i = 0; i < argc; i++ )
fprintf(fp_log, "%s ", argv[i]);
fprintf(fp_log, "\n");

log_date(fp_log);
log_user_info(fp_log);

/* was a kill signal specified? */

if ( argv[1][0] == '-' ) {
arg_start=2;
signal=atoi(&argv[1][1]);
}

/* loop through the pids on the command-line */
for ( i=arg_start; i < argc; i++ ) {

if ( (pid=atoi(argv[i])) < MAX_PID ) {
fprintf(stderr,
"bad PID number: %d\n", pid);
fprintf(fp_log, "bad PID number: %d\n", pid);
continue;
}

/* log the info before the fatal blow */
plog(fp_log, pid);

if ( kill(pid, signal) != 0 ) {
perror ("kill");
fprintf(fp_log, "errno %d: %s\n",
errno, sys_errlist[errno]);
}
}
fclose(fp_log);
exit(0);
}

/* ================================================= */

void log_date(fp)
FILE *fp;
{
time_t now;

if (time(&now)==01)
fprintf(fp,"time not available\n");
else
fprintf(fp,"%s", ctime(&now));
}

/* ================================================= */

void log_user_info(fp)
FILE *fp;
{
char *ph="HOME", *pn="NAME", *cwd;

fprintf(fp, "getlogin=%s uid=%d gid= gid=%d ",
getlogin(), getuid(), getgid());

fprintf(fp, "euid=%d egid=%d cuserid=%s\n",
geteuid(), getegid(), cuserid(NULL));

fprintf(fp,"cwd=%s\n", getcwd((char *)NULL, 64));
fprintf(fp,"$%s=%s ", ph, getenv(ph));
fprintf(fp,"$%s=%s\n", pn, getenv(pn));
}

/* ================================================= */
/* write pid info to log file using a pipe. the ps   */
/* flags may need to be changed to suit the local    */
/* version of ps.  If working with many different    */
/* versions, this could also be moved to a           */
/* configuration file so that you're not forced to   */
/* use the compiler to change an argument.           */

void plog(fp, pid)
FILE *fp;
int pid;
{
char cmd[50], buf[MAX_BUF];
FILE *ptr;

/* get verbose information about this pid */
sprintf(cmd, "/bin/ps -lfp %d", pid);

if ((ptr=popen(cmd, "r")) != NULL)
while(fgets(buf, sizeof(buf), ptr) != NULL)
fprintf(fp, "%s ",buf);
pclose(ptr);
}

/* ================================================= */
/* return true if string is in file.  one logname    */
/* per line.                                         */

int in_file(pstr, pfname)
char *pstr, *pfname;
{
int ret_status=0;
FILE *fp;
char line[MAX_LINE];

if ( (fp=fopen(pfname, "r")) == NULL )
return(ret_status);

while ( fgets(line, MAX_LINE, fp) != NULL ) {
if ( memcmp (line, pstr, strlen(pstr))==0 ) {
ret_status=1;
break;
}
}

fclose(fp);
return(ret_status);
}

/* ================================================= */
/* return true if file exists                        */

int fexist(pfname)
char *pfname;
{
struct stat sbuf;
return ( stat(pfname, &sbuf) == 0 );
}

/* ================================================= */
/* End of File */