wht@n4hgf.Mt-Park.GA.US (Warren Tucker) (01/17/91)
Submitted-by: wht@n4hgf.Mt-Park.GA.US (Warren Tucker) Posting-number: Volume 16, Issue 80 Archive-name: nogetty/part01 Properly used, nogetty allows one to start execution of a turnkey application on a particular SCO UNIX V multiscreen from inittab immediately entry upon a run level. All login and password validation are bypassed. DANGER WILL ROBINSON! Misuse of this program can compromise the security of your system. Carefully read the README and thr source file header for nogetty.c before use. #!/bin/sh # This is nogetty_1.0, a shell archive (shar 3.46) # made 01/16/1991 19:05 UTC by wht@n4hgf # Source directory /u1/src/nogetty # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1181 -rw-r--r-- README # 2552 -rw-r--r-- dumpwtmp.c # 14014 -rw-r--r-- nogetty.c # # ============= README ============== if test -f 'README' -a X"$1" != X"-c"; then echo 'x - skipping README (File already exists)' else echo 'x - extracting README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && XNOGETTY 1.00 - wht@n4hgf.Mt-Park.GA.US - Mon Jan 14 07:28:00 EST 1991 X--------------------------------------------------------------------- X XProperly used, nogetty allows one to start execution of a turnkey Xapplication on a particular SCO UNIX V multiscreen from inittab Ximmediately entry upon a run level. All login and password Xvalidation are bypassed. X XDANGER WILL ROBINSON! Misuse of this program can compromise the Xsecurity of your system. Carefully read the source file header Xfor nogetty.c before use. X XAlso provided is dumpwtmp.c, a program which displays utmp Xand wtmp in exhaustive detail. X XI almost always provide a Makefile. But not this time. While Xyou are typing, think again whether this is a program you want Xto use or not. X XTo compile, Xcc -O -o nogetty nogetty.c Xcc -O -o dumpwtmp dumpwtmp.c X X(oh all right, 'make nogetty dumpwtmp' will probably do it too) X XTo install: Xmv nogetty /etc/nogetty Xchown bin /etc/getty Xchgrp bin /etc/getty Xchmod 100 /etc/nogetty X XThen, an inittab entry like: X Xc05:2:respawn:/etc/nogetty turnkey tty05 bake_turkey X Xwill continously respawn a process on tty05 with username 'turnkey' Xand run program or shell script 'bake_turkey' X SHAR_EOF chmod 0644 README || echo 'restore of README failed' Wc_c="`wc -c < 'README'`" test 1181 -eq "$Wc_c" || echo 'README: original size 1181, current size' "$Wc_c" fi # ============= dumpwtmp.c ============== if test -f 'dumpwtmp.c' -a X"$1" != X"-c"; then echo 'x - skipping dumpwtmp.c (File already exists)' else echo 'x - extracting dumpwtmp.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'dumpwtmp.c' && X/* CHK=0xC327 */ X/*+----------------------------------------------------------------------- X dumpwtmp.c -- dump /usr/adm/wtmp and /etc/utmp X X Defined functions: X display_utmp(ut) X main(argc,argv,envp) X ut_type_text(ut_type) X X------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:01-14-1991-05:01-wht@n4hgf-beef up */ X X#include <stdio.h> X#include <fcntl.h> X#include <ctype.h> X#include <sys/types.h> X#include <utmp.h> X Xextern char *ctime(); X X/*+------------------------------------------------------------------------- X ut_type_text(ut_type) X--------------------------------------------------------------------------*/ Xchar * Xut_type_text(ut_type) Xushort ut_type; X{ Xstatic char errant[32]; X X switch(ut_type) X { X case EMPTY: return("EMPTY"); X case RUN_LVL: return("RUN_LVL"); X case BOOT_TIME: return("BOOT_TIME"); X case OLD_TIME: return("OLD_TIME"); X case NEW_TIME: return("NEW_TIME"); X case INIT_PROCESS: return("INIT_PROCESS"); X case LOGIN_PROCESS: return("LOGIN_PROCESS"); X case USER_PROCESS: return("USER_PROCESS"); X case DEAD_PROCESS: return("DEAD_PROCESS"); X case ACCOUNTING: return("ACCOUNTING"); X default: X sprintf(errant,"type=%u",ut_type); X return(errant); X } X X} /* end of ut_type_text */ X X/*+------------------------------------------------------------------------- X display_utmp(ut) X--------------------------------------------------------------------------*/ Xdisplay_utmp(ut) Xstruct utmp *ut; X{ X printf("%-8.8s ",ut->ut_user); /* User login name */ X printf("%-4.4s ",ut->ut_id); /* /etc/lines id(usually line #) */ X printf("%-12.12s ",ut->ut_line); /* device name (console, lnxx) */ X printf("%05d ",ut->ut_pid); /* process id */ X printf("%s\n",ut_type_text(ut->ut_type)); /* type of entry */ X printf(" term=%03d exit=%03d time=%s", X ut->ut_exit.e_termination,ut->ut_exit.e_exit, X ctime(&ut->ut_time)); X X} /* end of display_utmp */ X Xmain(argc,argv,envp) Xint argc; Xchar **argv; Xchar **envp; X{ Xstruct utmp ut; Xregister int ufd; Xint local = 0; Xint all = 0; X X printf("------------ %s -------------------------\n",UTMP_FILE); X if((ufd = open(UTMP_FILE,O_RDONLY,755)) < 0) X { X perror(UTMP_FILE); X exit(1); X } X while(read(ufd,&ut,sizeof(ut)) > 0) X display_utmp(&ut); X close(ufd); X X printf("------------ %s -------------------------\n",WTMP_FILE); X if((ufd = open(WTMP_FILE,O_RDONLY,755)) < 0) X { X perror(WTMP_FILE); X exit(1); X } X while(read(ufd,&ut,sizeof(ut)) > 0) X display_utmp(&ut); X close(ufd); X X exit(0); X} X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of dumpwtmp.c */ SHAR_EOF chmod 0644 dumpwtmp.c || echo 'restore of dumpwtmp.c failed' Wc_c="`wc -c < 'dumpwtmp.c'`" test 2552 -eq "$Wc_c" || echo 'dumpwtmp.c: original size 2552, current size' "$Wc_c" fi # ============= nogetty.c ============== if test -f 'nogetty.c' -a X"$1" != X"-c"; then echo 'x - skipping nogetty.c (File already exists)' else echo 'x - extracting nogetty.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'nogetty.c' && X/* CHK=0xB514 */ Xchar *revision = "@(#)nogetty 1.00 wht@n4hgf"; X/*+------------------------------------------------------------------------- X nogetty.c - bypass getty (nasty) on SCO and perhaps other S5R3 X wht@n4hgf.Mt-Park.GA.US X XProperly used, nogetty allows one to start execution of a turnkey Xapplication on a particular MULTISCREEN (see below) from inittab Ximmediately entry upon a run level. All login and password Xvalidation are bypassed. X XRun as root: X/etc/nogetty usrname tty [command [arg ...]] X XDANGER WILL ROBINSON! X---------------------- XBecause this violates Rules and Regulations of the C2 Brown Shirt XPreservation League, I feel I must deviate from my usual lack of Xverbiage. The is no 'F' TCB classification, but this program Xwarrants creation of one. X X1. Misuse of this program can compromise the security of your system. X X2. Making this program setuid to root WILL completely and fully X and probably PERMANENTLY compromise the slightest precepts of X security on your system (System->Configure->Security->Drown). X X3. No attempt is made to set the LUID. The ultimate ramifications X are unknown, but the immediate effects are to bypass much of X the C2 ParanoidWare. X X4. Not only is there no warranty or guarantee on this software, X but I don't want to even hear any of the horror stories possibly X resulting from the casual use of this software. X XNOT ME! I DIDN'T DO IT X---------------------- XNogetty is provided on an as-is basis. In no account will Warren Tucker Xor any other individual or entity be held accountable or liable for Xany direct or indirect consequences arising from the use of this Xsoftware. X XTTY INITIALIZATION X------------------ X1. ISIG is purposefully omitted from the initial tty setup so that XRUBOUT (SIGINT) processing may not abort the started application. XYou may wish to reenable it by use of 'stty isig'. Be aware that Xsome applications when started may of their own accord enable XSIGINT processing either directly or through the invocation of Xother processes. X X2. A 'mesg n' is simulated by chmod 0600 of the terminal device. X X3. The tty is always initialized to 9600 baud, no parity, one stop bit. X X4. Otherwise, the tty is initialized pretty much as getty/login would. X XSUITABLE APPLICATIONS X--------------------- XApplications started with nogetty that fork other processes Xshould receive particular attention with respect to security. XThe ability of a child process to executing a shell is of obvious Xconcern, but bear in mind that starting programs like vi can be a Xproblem since THEY have a shell capability. Of course, since you Xare the god of your system, it is up to YOU to decide what is Xbest for your child and behave as you feel best. X XAPPLICATION ENVIRONMENT X----------------------- XThe preferred (/etc/passwd) shell for <username> is started as Xa login shell (i.e., .login will be executed if the shell is csh). X XTo allow for login processing to differentiate between normal Xand nogetty startups, nogetty adds an environment variable X NOGETTY=/dev/ttyxx X XThe single <command> is executed, whereupon nogetty exits. X XUTMP, INITTAB, WHO, ENABLE/DISABLE X---------------------------------- XUtmp and wtmp are properly updated per the ad-hoc SCO usage of Xutmp's ut_id. The ut_id field of the utmp entry for a *multiscreen* Xis comprised of a 'c' followed by the last two (numeric) characters Xof the tty id. Use of nogetty to start an application on a Xnon-multiscreen will require analysis of the ut_id format and Xuse of the '-i' switch. X XIf you handle this little bit, then you should be able to Xuse all the standard features of inittab, who and enable/disable. XOtherwise, erroneous utmp entries will be generated, adversely Xaffecting these control and status functions. X XLOG FILE: /etc/nogetty.log X-------------------------- XError logging is done in /etc/nogetty.log. It grows forever unless Xyou do something about it. X X Defined functions: X add_to_argv(arg) X add_to_env(env) X adjust_env(buf) X fatal_news(buf,detail) X get_TZ_HZ() X main(argc,argv) X smart_fork() X X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:01-14-1991-01:19-wht@n4hgf-creation */ X X#include <stdio.h> X#undef NULL X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/wait.h> X#include <sys/param.h> X#include <sys/errno.h> X#include <ctype.h> X#include <signal.h> X#include <termio.h> X#include <string.h> X#include <memory.h> X#include <malloc.h> X#include <fcntl.h> X#include <time.h> X#include <pwd.h> X#include <utmp.h> X X#define MAX_NEWENV 64 Xchar *new_environ[MAX_NEWENV] = {(char *)0}; Xchar **new_environ_add_ptr = new_environ; Xint new_environ_count = 0; X X#define MAX_NEWARGV (NCARGS) Xchar new_argv[MAX_NEWARGV] = {0}; Xint new_argv_count = 0; X Xchar *ttydev = (char *)0; Xchar *usrname = (char *)0; Xchar *cmd = (char *)0; X X/*+------------------------------------------------------------------------- X fatal_news(buf,detail) - write fatal error message to log file and die X Xsleep for 10 secs so a repeating error won't make init rattle the Xworld respawning us X--------------------------------------------------------------------------*/ Xvoid Xfatal_news(buf,detail) Xchar *buf; Xchar *detail; X{ X int fd = open("/etc/nogetty.log",O_CREAT|O_WRONLY|O_CREAT,0644); X X if(fd >= 0) X { X write(fd,buf,strlen(buf)); X if(detail && *detail && (strlen(detail) < 128)) X { X write(fd," [",2); X write(fd,detail,strlen(detail)); X write(fd,"]",1); X } X write(fd,"\n",1); X close(fd); X } X X sleep(10); X _exit(255); X X} /* end of fatal_news */ X X/*+------------------------------------------------------------------------- X add_to_env(env) X--------------------------------------------------------------------------*/ Xvoid Xadd_to_env(env) Xchar *env; X{ X char *item = malloc(strlen(env) + 1); X X if(!item) X fatal_news("nogetty: memory alloc failed",ttydev); X strcpy(item,env); X if(new_environ_count >= (MAX_NEWENV - 1)) X fatal_news("nogetty: too many environment variables",ttydev); X *new_environ_add_ptr++ = item; X new_environ_count++; X X} /* end of add_to_env */ X X/*+------------------------------------------------------------------------- X adjust_env(buf) - get rid of coments or space/tab X--------------------------------------------------------------------------*/ Xvoid Xadjust_env(buf) Xchar *buf; X{ X char *cptr; X X if(cptr = strchr(buf,'#')) X *cptr = 0; X if(cptr = strchr(buf,' ')) X *cptr = 0; X if(cptr = strchr(buf,'\t')) X *cptr = 0; X X} /* end of adjust_env */ X X/*+------------------------------------------------------------------------- X get_TZ_HZ() - get TZ and HZ from /etc/TIMEZONE X Xfailing to find either, fake it somehow X--------------------------------------------------------------------------*/ Xvoid Xget_TZ_HZ() X{ X int itmp; X char buf[128]; X char *cptr; X FILE *fp = fopen("/etc/TIMEZONE","r"); X int found_tz = 0; X int found_hz = 0; X char *getenv(); X X if(fp) X { X while(fgets(buf,sizeof(buf),fp)) X { X if((itmp = strlen(buf)) && (buf[itmp - 1] == '\n')) X buf[itmp - 1] = 0; X if(!strncmp(buf,"HZ=",3)) X { X adjust_env(buf); X add_to_env(buf); X found_hz = 1; X } X else if(!strncmp(buf,"TZ=",3)) X { X adjust_env(buf); X add_to_env(buf); X found_tz = 1; X } X } X fclose(fp); X } X X if(!found_tz) X { X if(cptr = getenv("TZ")) X { X sprintf(buf,"TZ=%s",cptr); X add_to_env(buf); X } X else X add_to_env("TZ=EST5EDT"); X } X if(!found_hz) X { X if(cptr = getenv("HZ")) X { X sprintf(buf,"HZ=%s",cptr); X add_to_env(buf); X } X else X { X sprintf(buf,"HZ=%d",HZ); X add_to_env(buf); X } X } X X} /* end of get_TZ_HZ */ X X/*+------------------------------------------------------------------------- X add_to_argv(arg) X--------------------------------------------------------------------------*/ Xvoid Xadd_to_argv(arg) Xchar *arg; X{ Xregister len = strlen(arg); X X if(new_argv_count + len + 1 >= sizeof(new_argv)) X fatal_news("nogetty: argv too long",ttydev); X if(new_argv_count) X { X strcat(new_argv," "); X new_argv_count++; X } X strcat(new_argv,arg); X new_argv_count += len; X X} /* end of add_to_argv */ X X/*+------------------------------------------------------------------------- X smart_fork() X--------------------------------------------------------------------------*/ Xint Xsmart_fork() X{ X register int count = 5; X register int pid; X X while(count--) X { X if((pid = fork()) >= 0) X return(pid); X if(count) X sleep(2); X } X return(-1); X} /* end of smart_fork */ X X/*+------------------------------------------------------------------------- X main(argc,argv) X--------------------------------------------------------------------------*/ Xmain(argc,argv) Xint argc; Xchar **argv; X{ X int itmp; X int fd0,fd1,fd2,fdwtmp; X int child; X int wait_status; X struct termio tio; X struct stat st; X struct passwd *pw; X struct utmp ut; X struct utmp *utptr; X char s128[128]; X char ttydev2[64]; X char *cptr; X char *ut_id_override = (char *)0; X int errflg = 0; X extern char *optarg; X extern int optind; X X while((itmp = getopt(argc,argv,"i:")) != -1) X { X switch(itmp) X { X case 'i': X ut_id_override = optarg; X break; X case '?': X errflg++; X } X } X if(errflg || ((argc - optind) < 2)) X { X fatal_news("nogetty: invalid invocation","usage"); X exit(1); X } X X usrname = argv[optind]; X ttydev = argv[optind + 1]; X cmd = argv[optind + 2]; X strcpy(ttydev2,"/dev/"); X strcat(ttydev2,ttydev); X X pw = getpwnam(usrname); X endpwent(); X if(!pw) X fatal_news("nogetty: cannot get password table entry",usrname); X X get_TZ_HZ(); X X for(fd0 = 0; fd0 < NOFILES_MAX; fd0++) /* close every conceivable file */ X close(fd0); X X#ifdef TRY_THIS X if((itmp = smart_fork()) < 0) X fatal_news("nogetty: cannot fork",ttydev); X else if(itmp) /* parent */ X _exit(0); X#endif X X setpgrp(); X X if((fd0 = open(ttydev2,O_RDWR,0)) < 0) X fatal_news("nogetty: cannot open fd 0",ttydev2); X if((fd1 = dup(fd0)) < 0) X fatal_news("nogetty: cannot dup fd 1",ttydev2); X if((fd2 = dup(fd0)) < 0) X fatal_news("nogetty: cannot dup fd 2",ttydev2); X X if(stat(ttydev2,&st)) X fatal_news("nogetty: cannot stat tty",ttydev2); X chown(ttydev2,pw->pw_uid,st.st_gid); X chmod(ttydev2,0600); X X ioctl(fd0,TCGETA,(char *)&tio); X tio.c_iflag = BRKINT | IGNPAR | ICRNL | IXON | IXANY; X tio.c_oflag = OPOST | ONLCR; X tio.c_cflag = CREAD | HUPCL | B9600 | CS8 | B9600; X tio.c_lflag = ICANON | ECHO | ECHOK; X tio.c_cc[VINTR] = 0x7F; X tio.c_cc[VQUIT] = 0x1C; X tio.c_cc[VERASE] = 0x08; X tio.c_cc[VKILL] = 0x15; X tio.c_cc[VEOF] = 0x04; X tio.c_cc[VEOL] = 0x0D; X tio.c_cc[VEOL2] = 0x0A; X tio.c_cc[VSWTCH] = 0x00; X ioctl(fd0,TCSETA,(char *)&tio); X X /* X * set up utmp entry X */ X X setutent(); X ut.ut_type = LOGIN_PROCESS; X if(ut_id_override) X strncpy(ut.ut_id,ut_id_override,sizeof(ut.ut_line)); X else X { X strcpy(ut.ut_id,"c"); X strncat(ut.ut_id,ttydev + strlen(ttydev) - 2,sizeof(ut.ut_line) - 1); X } X strncpy(ut.ut_line,ttydev,sizeof(ut.ut_line)); X getutid(&ut); X ut.ut_type = USER_PROCESS; X ut.ut_exit.e_termination = 0; X ut.ut_exit.e_exit = 0; X strncpy(ut.ut_user,pw->pw_name,sizeof(ut.ut_user)); X strncpy(ut.ut_line,ttydev,sizeof(ut.ut_line)); X if(ut_id_override) X strncpy(ut.ut_id,ut_id_override,sizeof(ut.ut_line)); X else X { X strcpy(ut.ut_id,"c"); X strncat(ut.ut_id,ttydev + strlen(ttydev) - 2,sizeof(ut.ut_line) - 1); X } X ut.ut_pid = getpid(); X time(&ut.ut_time); X pututline(&ut); X endutent(); X X /* X * now be a good camper and update wtmp X */ X X if((fdwtmp = open(WTMP_FILE,O_WRONLY | O_APPEND)) >= 0) X { X strncpy(ut.ut_user,"nogetty",sizeof(ut.ut_user)); X ut.ut_type = INIT_PROCESS; X write(fdwtmp,&ut,sizeof(ut)); X ut.ut_type = USER_PROCESS; X strncpy(ut.ut_user,pw->pw_name,sizeof(ut.ut_user)); X write(fdwtmp,&ut,sizeof(ut)); X close(fdwtmp); X } X X sprintf(s128,"LOGNAME=%s",pw->pw_name); X add_to_env(s128); X sprintf(s128,"HOME=%s",pw->pw_dir); X add_to_env(s128); X sprintf(s128,"PATH=/bin:/usr/bin:/usr/lbin:/usr/dbin:/usr/bin/X11:%s/bin", X pw->pw_dir); X add_to_env(s128); X sprintf(s128,"MAIL=/usr/spool/mail/%s",pw->pw_name); X add_to_env(s128); X sprintf(s128,"SHELL=%s",pw->pw_shell); X add_to_env(s128); X sprintf(s128,"NOGETTY=%s",ttydev); /* NOGETTY = /dev/ttyxx */ X add_to_env(s128); X add_to_env("TERM=ansi"); X X /* X * build new argv X */ X for(itmp = optind + 2; itmp < argc; itmp++) X add_to_argv(argv[itmp]); X X /* X * fork and start fireworks X */ X if((child = smart_fork()) < 0) X fatal_news("nogetty: cannot fork",ttydev); X else if(!child) /* child */ X { X /* X * become the specified user (and his group) X */ X setgid(pw->pw_gid); X setuid(pw->pw_uid); X chdir(pw->pw_dir); X X /* X * exec the command line argument in the user's favorite shell X */ X if(cptr = strrchr(pw->pw_shell,'/')) X sprintf(s128,"-%s",cptr + 1); X else X strcpy(s128,"-"); X execle(pw->pw_shell,s128,"-v","-c",new_argv,(char *)0,new_environ); X fatal_news("nogetty: execute failed",cmd); X /* NOTREACHED*/ X } X X /* X * parent just waits for child (shell term) X */ X waitpid(child,&wait_status,0); X X /* X * update utmp entry and write new wtmp entry X */ X setutent(); X ut.ut_type = USER_PROCESS; X if(ut_id_override) X strncpy(ut.ut_id,ut_id_override,sizeof(ut.ut_line)); X else X { X strcpy(ut.ut_id,"c"); X strncat(ut.ut_id,ttydev + strlen(ttydev) - 2,sizeof(ut.ut_line) - 1); X } X utptr = getutid(&ut); X if(utptr && (utptr->ut_pid == getpid())) X { X utptr->ut_type = DEAD_PROCESS; X strncpy(ut.ut_user,pw->pw_name,sizeof(ut.ut_user)); X utptr->ut_exit.e_termination = WTERMSIG(wait_status); X utptr->ut_exit.e_exit = WEXITSTATUS(wait_status); X time(&utptr->ut_time); X pututline(utptr); X if((fdwtmp = open(WTMP_FILE,O_WRONLY | O_APPEND)) >= 0) X { X write(fdwtmp,utptr,sizeof(struct utmp)); X close(fdwtmp); X } X } X else X { X ut.ut_type = DEAD_PROCESS; X strncpy(ut.ut_user,pw->pw_name,sizeof(ut.ut_user)); X ut.ut_exit.e_termination = WTERMSIG(wait_status); X ut.ut_exit.e_exit = WEXITSTATUS(wait_status); X time(&ut.ut_time); X if((fdwtmp = open(WTMP_FILE,O_WRONLY | O_APPEND)) >= 0) X { X write(fdwtmp,utptr,sizeof(struct utmp)); X close(fdwtmp); X } X } X endutent(); X X _exit(0); X X} /* end of main */ X X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of nogetty.c */ SHAR_EOF chmod 0644 nogetty.c || echo 'restore of nogetty.c failed' Wc_c="`wc -c < 'nogetty.c'`" test 14014 -eq "$Wc_c" || echo 'nogetty.c: original size 14014, current size' "$Wc_c" fi exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.