[net.sources] Lock your terminal for lunch

cim1@pyuxv.UUCP (G. Bogatko) (09/06/85)

# Munch, Munch 

#This is a great way to lock up your terminal without having to log off.

trap 'echo "PISS OFF"' 1 2 3 6 15
clear
echo "

I won't work now.  My massa has gon 'way.  Don't even try.

"
stty -echo
while true
do
	read ans
	case $ans in

# rewrite this line -- replace 'password' with YOUR password

	password)	clear

			stty echo
			exit ;;
	*)		echo "PISS OFF";;
	esac
done

#from Rob Fair and George Bogatko

mjs@sfmag.UUCP (M.J.Shannon) (09/07/85)

> #This is a great way to lock up your terminal without having to log off.
> 
> trap 'echo "PISS OFF"' 1 2 3 6 15
[ lots of shell program elided -mjs ]
> #from Rob Fair and George Bogatko

There are only 2 problems with this approach, one minor, the other fatal.
The minor one is that the password is kept in clear text.  This can probably
be dealt with effectively with appropriate permissions on the file (like
0700).  The fatal one is that since the shell is interpreting this file, a
bad-guy at the terminal can generate either interrupt or quit signals faster
than the shell can react (re-catch them).  Possibly using something like
	trap '' 1 2 3 6 15
may prevent the shell's need to react (but verify it before you use it!).
The real answer to the security problem is to never, NEVER, *NEVER* leave
your terminal unattended when you're logged in.
-- 
	Marty Shannon
UUCP:	ihnp4!attunix!mjs
Phone:	+1 (201) 522 6063
Disclaimer: I speak for no one.

levy@ttrdc.UUCP (Daniel R. Levy) (09/08/85)

In article <131@pyuxv.UUCP>, cim1@pyuxv.UUCP (G. Bogatko) writes:
># Munch, Munch
>#This is a great way to lock up your terminal without having to log off.
>trap 'echo "PISS OFF"' 1 2 3 6 15
>clear
>echo "
>
>I won't work now.  My massa has gon 'way.  Don't even try.
>
>"
>stty -echo
>while true
>do
>	read ans
>	case $ans in
># rewrite this line -- replace 'password' with YOUR password
>	password)	clear
>			stty echo
>			exit ;;
>	*)		echo "PISS OFF";;
>	esac
>done
>#from Rob Fair and George Bogatko

O.K. I'm game.

I tried this, then held the DELETE key down.
Results?

PISS OFF
PISS OFF
PISPISS OP
PISPPP$
$
$
$

The system was a 3B20S running Unix 5.2, under the Bourne shell.
-- 
 -------------------------------    Disclaimer:  The views contained herein are
|       dan levy | yvel nad      |  my own and are not at all those of my em-
|         an engihacker @        |  ployer, my pets, my plants, my boss, or the
| at&t computer systems division |  s.a. of any computer upon which I may hack.
|        skokie, illinois        |
 --------------------------------   Path: ..!ihnp4!ttrdc!levy
                                      or: ..!ihnp4!iheds!ttbcad!levy

cim1@pyuxv.UUCP (G. Bogatko) (09/08/85)

munch munch

	Alright, alright, so don`t use your CURRENT password. 

ravi@mcnc.UUCP (Ravi Subrahmanyan) (09/09/85)

[shlurp....]

And what does one do about a control-Z for csh users?
I'd really like to know if that can be worked around..

mike@erix.UUCP (Mike Williams) (09/10/85)

We use this one.

/* Lock a terminal which is not in use. Give own password to unlock */
#include <signal.h>
#include <stdio.h>
#include <pwd.h>

#define BELL    007

struct  passwd *getpwuid();


main()
{
	int t;
	char *pass;
	char    pwbuf[10];
	char *getpass();
	char    *strcpy();
	char    *crypt();
	char    *pw;
	register struct passwd *pwd;

	/* get password entry */
	pwd = getpwuid(getuid());

	/* signal handling */
	for (t = 1; t <= 26; t++)
		signal(t, SIG_IGN);
	/* Process will die if HUP is received - good for modem lines!   */
		signal(SIGHUP,SIG_DFL);


	/* loop here to wait for correct password */
	while (1) {
		strcpy(pwbuf, getpass("Password:"));
		pw = crypt(pwbuf, pwd->pw_passwd);
		if(strcmp(pw, pwd->pw_passwd) == 0) exit(0);
		putchar(BELL);
		fflush(stdout);
	}
}

addw@root44.UUCP (Alain Williams) (09/12/85)

If you are worried, how about logging out ?
(Or are we only interested in complicated solutions ?)
-- 
	Alain Williams,
	Root Computers Ltd, London, England.
	<UK-net>!{hrc63|qmc-cs|edai|kcl-cs|ukc|glasgow|ist|jmccfr|west44
		ubu|rlvd|pmllab|stc}!root44!addw
	{unisoft|deccra}!root44!addw
	root44!{rootcl|rootis}!addw

davy@pur-ee.UUCP (Dave Curry) (09/13/85)

Here's the program I've been using for several years now to lock
terminals... as far as I can tell, it is uninterruptible.  On 4.2BSD
systems, you may want to change the signal calls to sigvec calls to
avoid the extra time spent in the library routines, but I haven't
found it to be necessary.

This program was designed primarily for public terminal rooms, thus
the timeout.  We used to have problems with people walking off and
forgetting they had one of these running, effectively locking the
terminal until a super-user could be found.  If you don't like the
idea of a timeout, set it to something huge.

Note also that since only the first argument is looked at, you can
run this as "gone 10 - went to the coffee machine" or whatever, for
the benefit of those who want to "ps" your terminal.

--Dave Curry

/*---------------------------- CUT HERE ----------------------------*/

/*
 * gone - terminal hold program which permits limited command execution.
 *
 * Usage: gone [maxtime]
 *
 * This program locks up a terminal for maxtime minutes (default DEFTIME).
 * In order to prevent "infinite" locks, maxtime is limited to no more
 * than MAXTIME minutes.  In order to prevent the terminal from being
 * entirely useless, the commands listed in the "valcoms" array may be
 * executed from within the program.  Note that we only do "simple"
 * execution, i.e., just exec the arguments as typed.
 *
 * When executed, the user is prompted for a password which will be used
 * to release the terminal.  The terminal is then locked until BREAK is
 * pressed, at which time the user is prompted for the password to
 * release the terminal.  The terminal will only be released if the
 * password is typed correctly.
 *
 * BUG: if you run this from a subshell of the c-shell, then the
 * autologout code will only terminate you down to the parent shell,
 * rather than logging you off all the way.  This is because we kill by
 * process group, and the parent shell is not in this process group.
 * Note also that if you run csh, background jobs will not be killed.
 *
 * David A. Curry
 * Purdue Engineering Computer Network
 * {decvax, ihnp4, ucbvax}!pur-ee!davy
 * davy@purdue-ecn.arpa
 *
 */
#include <sys/time.h>
#include <signal.h>
#include <setjmp.h>
#include <sgtty.h>
#include <stdio.h>

#define DEFTIME	15			/* default time until logout	*/
#define MAXTIME 30			/* maximum time until logout	*/

/*
 * List of commands which we will allow to be executed from within
 * the program.  Don't put anything "dangerous" in here.
 */
char *valcoms[] = {
	"date",
	"f",
	"finger",
	"lpc",
	"lpq",
	"lprm",
	"name",
	"tty",
	"uid",
	"wh",
	"when",
	"where",
	"who",
	0,
};

char *getpass(), *handler(), *asctime(), *ctime();
struct tm *gmtime();

jmp_buf env;
char password[32];

int logtime;				/* amount of secs to hold for	*/
int pid, ppid, proid;			/* process id's of all processes*/
long lontime, lofftime;			/* start and finish times	*/

main(argc, argv)
int argc;
char **argv;
{
	char *a;
	int i, first;
	char c, command[1024];
	char stdoutbuf[BUFSIZ];

	setbuf(stdout, stdoutbuf);
	
	first = 0;

	if (argc > 1) {
		logtime = atoi(argv[1]);

		if (logtime < 5)
			logtime = 5;
	}
	else {
		logtime = DEFTIME;
	}

	if (logtime > MAXTIME)
		logtime = MAXTIME;

	logtime *= 60;			/* convert minutes to seconds 	*/

	time(&lontime);			/* get the starting time      	*/


	/*
	 * Don't permit running from non-ttys.
	 */
	if (nottty())
		exit(1);

	signal(SIGTSTP, SIG_IGN);

	/*
	 * Get the locking password.
	 */
	a = getpass("Password: ");
	strcpy(password, a);
	
	a = getpass("Retype: ");

	if (strcmp(password, a) != 0) {
		printf("Abort - passwords do not match\n");
		exit(1);
	}

	ppid = getppid();		/* get shell's process id	*/
	proid = getpid();		/* get this process id		*/

	while ((pid = fork()) < 0) {
		printf("Cannot fork -- retrying...\n");
		fflush(stdout);
		sleep(5);
	}

	if (pid == 0) {			/* we're in the fork		*/
		/*
		 * Ignore all signals.
		 */
		for (i=0; i < NSIG; i++)
			signal(i, SIG_IGN);

		signal(SIGALRM, SIG_DFL);

		sleep(logtime - 120);

		printf("\nTimeout in 2 minutes\n");
		fflush(stdout);
		sleep(60);

		printf("\nTimeout in 60 seconds\n");
		fflush(stdout);
		sleep(60);

		printf("\nTerminal timeout\n");
		fflush(stdout);

		kill(ppid, SIGKILL);		/* kill the shell */
		kill(proid, SIGKILL);		/* kill the first gone */

		exit(0);			/* die */
	}

	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);

	setjmp(env);			/* we come back to here each time */

	signal(SIGINT, handler);

	/*
	 * Clear the screen.  Stupidly, we assume ^L or ^Z
	 * will clear it.
	 */
	printf("\014\032");

	/*
	 * Print the info about how long we're holding for.
	 */
	if (first == 0) {
		printf("%d min. hold initialized at ", logtime/60);
		printf("%8.8s\n", (ctime(&lontime)+11));
		first = 1;
	}

	/*
	 * Print an in-use message.
	 */
	inuse();

	/*
	 * Loop, looking like a shell.
	 */
loop:	printf("$ ");
	fflush(stdout);
	*command = NULL;
	
	if (gets(command) == NULL) {
		clearerr(stdin);
		printf("\n");
		goto loop;
	}

	if ((*command != '\n') && (*command != NULL))
		runcom(command);

	signal(SIGINT, handler);
	goto loop;
}

/*
 * runcom - run the command.
 */
runcom(command)
char *command;
{
	char *args[32];
	char com[1024];
	register int i, j;

	strcpy(com, command);

	j = 0;
	args[j++] = com;

	/*
	 * Split up the arguments.
	 */
	for (i=0; com[i] != NULL; i++) {
		if (com[i] == ' ') {
			com[i++] = NULL;
			
			if (j < 24)
				args[j++] = (com+i);
		}
	}

	args[j] = NULL;

	/*
	 * If it's not legal, don't run the command.
	 */
	if (lookup(args[0]) < 0) {
		printf("That command is not permitted from this shell.\n");
		return;
	}

	execute(command, args);
}

/*
 * lookup - look up the command in the valid commands list.
 */
lookup(name)
char *name;
{
	int i;

	for (i=0; valcoms[i] != NULL; i++) {
		if (!strcmp(name, valcoms[i]))
			return(1);
	}

	return(-1);
}

/*
 * execute - execute the command.
 */
execute(command, args)
char *command;
char **args;
{
	int zid;

	while ((zid = fork()) < 0) {
		printf("Cannot fork -- retrying...\n");
		fflush(stdout);
		sleep(5);
	}

	/*
	 * The child tries the exec; if this fails,
	 * we bag it and use system.
	 */
	if (zid == 0) {
		execvp(args[0], args);

		system(command);
	}

	while (wait((int *)0) != zid)
		;
}

/*
 * handler - handle interrupts.
 */
char *handler()
{
	char *attempt;
	long ttime;

	signal(SIGINT, SIG_IGN);
	signal(SIGALRM, SIG_IGN);

	/*
	 * Get the password.
	 */
	printf("\n");
	fflush(stdout);
	attempt = getpass("Password: ");

	/*
	 * If valid, release the terminal.
	 */
	if (strcmp(attempt, password) == 0) {
		kill(pid, SIGKILL);		/* kill the child */

		time(&lofftime);

		ttime = lofftime - lontime;

		printf("Gone for: %5.5s\n\n", (asctime(gmtime(&ttime))+14));
		exit(0);
	}
	else {
		signal(SIGALRM, SIG_DFL);
		longjmp(env);
		return;
	}
}

/*
 * inuse - print the in use banner.
 */
inuse()
{
	printf("\n\n\n\n\n\n\n\n");
	printf("\t\t   XXXXX  XX    X        X    X  XXXXX  XXXXX\n");
	printf("\t\t     X    X X   X        X    X  X      X    \n");
	printf("\t\t     X    X  X  X        X    X  XXXXX  XXX  \n");
	printf("\t\t     X    X   X X        X    X      X  X    \n");
	printf("\t\t   XXXXX  X    XX        XXXXXX  XXXXX  XXXXX\n");
}

/*
 * nottty - return 1 if this isn't a tty.
 */
nottty()
{
	signal(SIGTSTP, SIG_IGN);

	if (isatty(2) == 0) {
		printf("Cannot run gone without a tty.\n");
		fflush(stdout);
		return(1);
	}

	return(0);
}

huisjes@ark.UUCP (Michiel Huisjes) (09/17/85)

-- 

			Michiel Huisjes.  (huisjes@ark.UUCP)
			{seismo|decvax|philabs}!mcvax!vu44!ark!huisjes

andrew@sask.UUCP (Derek Andrew) (09/21/85)

#include <signal.h>
main(){
        char key[64];
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
        strncpy(key, getpass("Key: "),sizeof key);
        while(strcmp(key, getpass("Key: "))) ;
}

cwj@csadfa.oz (09/23/85)

Here is a reasonably safe way to lock your terminal for lunch,
for `csh' users.

It is immune to holding down the interrupt key,
and immune to attempts to suspend the program (^z),
because it grabs and ignores the former and has nullified the latter.
BUT it is still vulnerable to QUIT (^\) - and I don't know why!
("onintr -" is supposed to ignore all interrupts)

----------------------------------------------------------
#!/bin/csh
# lock terminal until password received
echo "TERMINAL LOCKED"
stty -echo susp '' dsusp ''
onintr -
while ("$< x" != 'YOUR_PASSWORD x')
  echo 'Please ---- ---, Chris is at lunch'
  echo -n '% '
end

# restore the terminal to a normal state
stty echo susp '^z' dsusp '^y'
----------------------------------------------------------

cwj@csadfa.oz (09/24/85)

1. onintr is only supposed to catch interrupts, not quits, so it is not
surprising that QUIT still kills the lockout program.

2. to fix this:   stty quit '' (initially)
and               stty quit '^\' (restoration)

alexis@reed.UUCP (Alexis Dimitriadis) (09/26/85)

In article <3291@pur-ee.UUCP> davy@pur-ee.UUCP (Dave Curry) writes:
> 
> Here's the program I've been using for several years now to lock
> terminals... as far as I can tell, it is uninterruptible.

  To my knowledge, at least on BSD systems, there is no such thing as
an uninterruptible lock.  There are things you can do that help, but
none of the lock programs that I have seen posted do them.  If you really
want to be safe, log out when you go away.
  
  I will reply to postings from `root' if those lock programs seem secure
to you.  Much as I dislike locks (tying up a hard-to-get terminal while
the user is having his coffee strikes me as objectionable), I will not 
make those loopholes general knowledge.

PS. Followups will go to net.unix.
-- 
_______________________________________________
  As soon as I get a full time job, the opinions expressed above
will attach themselves to my employer, who will never be rid of
them again.
				alexis @ reed
    {decvax,ihnp4,ucbcad,uw-beaver}!tektronix!reed.UUCP

joeh@dartvax.UUCP (Joe Hill ) (09/27/85)

Lock is nice, unfortunatly here at Dart we connect to the network
then to whatever system, typing '@' kicks you off and throws you
back to the net no matter whats happening. Kissing your session
good bye. Here is a version of lock i have found to work well.
 



 
 ---------- cut here ----------
 #################################################################
 #                                                               #
 #                                                               #
 #                      THIS CRT IS SUFFERING                    #
 #                      FROM NO-WORKA-PHOBIA!                    #
 #                                                               #
 #                                                               #
 #                     (Its a Terminal disease)                  #
 #################################################################
 -------- cut here, also, and stick on your terminal ----------