[comp.windows.x] X workstation lock program

milliken@BFLY-VAX.BBN.COM.UUCP (03/31/87)

Name:
  xsecure - secure a workstation from malicious fingers

Synopsis:
  xsecure [password]

Description:
  This program provides a means of locking up a workstation without
  logging out.  It also runs a screen-saver while active.

  xsecure gobbles all keyboard and mouse events until the password is
  typed to it, whereupon it exits.  The password defaults to the user's
  login password.  (The optional command line password is for the benefit
  of those who are incurably paranoid about equines in Asia Minor.)

  xsecure fills the screen with black and bounces a small cursor
  around while running.  The user's screen will be restored when xsecure
  exits.

Bugs:
  The password must be typed on a line by itself.

  You can lock up someone else's machine if you can display to them.
  (No X Cookie Monsters, please!)

  The cursor will have to be fixed on machines which can't handle a
  32x32 cursor.

------------------------- Tear along dotted line --------------------------
/* secure a SUN console under X */

/*	Walter Milliken			(milliken@bbn.com)
	BBN Advanced Computers, Inc.
	10 Fawcett St.
	Cambridge, MA 02238				*/

#include <stdio.h>
#include <pwd.h>
#include <X/Xlib.h>

char * crypt();

#define lckcurs_width 32
#define lckcurs_height 32
#define lckcurs_x_hot 16
#define lckcurs_y_hot 20
static short lckcurs_bits[] = {
   0x0000, 0x0000, 0xe000, 0x0007,
   0xf800, 0x001f, 0xfc00, 0x003f,
   0x3e00, 0x007c, 0x0f00, 0x00f0,
   0x0700, 0x00e0, 0x0380, 0x01c0,
   0x0380, 0x01c0, 0x0380, 0x01c0,
   0x01c0, 0x0380, 0x01c0, 0x0380,
   0x01c0, 0x0380, 0x01c0, 0x0380,
   0x0008, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0xc000, 0x0003,
   0xe000, 0x0007, 0xf000, 0x000f,
   0xf000, 0x000f, 0xf000, 0x000f,
   0xe000, 0x0007, 0xc000, 0x0003,
   0xc000, 0x0003, 0xc000, 0x0003,
   0xc000, 0x0003, 0xc000, 0x0003,
   0x0000, 0x0000, 0x0000, 0x0000,
   0x0008, 0x1000, 0x0000, 0x0000};

#define lckmask_width 32
#define lckmask_height 32
static short lckmask_bits[] = {
   0xe000, 0x0007, 0xf800, 0x001f,
   0xfc00, 0x003f, 0xfe00, 0x007f,
   0xff00, 0x00ff, 0x3f80, 0x01fc,
   0x0f80, 0x01f0, 0x07c0, 0x03e0,
   0x07c0, 0x03e0, 0x07c0, 0x03e0,
   0x03e0, 0x07c0, 0x03e0, 0x07c0,
   0x03e0, 0x07c0, 0x03f0, 0x0fc0,
   0xfff0, 0x0fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff0, 0x0fff, 0x0000, 0x0000};


struct passwd * pw;

Display * dsp;
OpaqueFrame frame;
Window w;
Cursor mycursor;

XEvent evt;
XKeyPressedEvent * kpevt;


ReadXString(s, slen)
char * s;
int slen;
{
    int bp;
    char c;
    int n;
    char * keystr;


    bp = 0;
    c = 'x';
    while (c != '\r') {
	if (XPending() == 0) {
	    XWarpMouse(w, (random() % (DisplayWidth()-64))+32,
		       (random() % (DisplayHeight()-64))+32);
	    sleep(2);
	    }
	else {
	    XNextEvent(&evt);
	    if (evt.type == KeyPressed) {
		keystr = XLookupMapping(kpevt, &n);
		if (n>0) {
		    c = keystr[0];
		    if (c == '\r') s[bp] = '\0';
		    else s[bp] = c;
		    if (bp < slen-1) bp++;
		    }
		}
	    else ; /* discard other events */
	    }
	}
}


main(argc, argv)
int argc;
char * argv[];
{
    char geometry[40];
    char buf[200];
    char * pass;
    char cryptpass[20];
    char * s;
    int n;
    int i;
    int done;


    pw = getpwuid(getuid());
    if (argc == 1) pass = pw->pw_passwd;
    else if (argc == 2) {
	pass = crypt(argv[1], pw->pw_passwd);
	strcpy(cryptpass, pass);
	pass = cryptpass;
	}
    else {
	fprintf(stderr, "usage: %s [<lock password>]\n", argv[0]);
	exit(1);
	}

    kpevt = (XKeyPressedEvent *) &evt;
    dsp = XOpenDisplay(NULL);
    mycursor = XCreateCursor(lckcurs_width, lckcurs_height, lckcurs_bits,
			     lckmask_bits, lckcurs_x_hot, lckcurs_y_hot,
			     BlackPixel, WhitePixel, GXcopy);
    frame.bdrwidth = 0;
    frame.border = BlackPixmap;
    frame.background = BlackPixmap;
    sprintf(geometry, "%dx%d+0+0", DisplayWidth(), DisplayHeight());
    w = XCreate(argv[0], argv[0], geometry, "", &frame, 10, 10);

    XSelectInput(w, KeyPressed);
    XMapWindow(w);
    XFocusKeyboard(w);
    XGrabMouse(w, mycursor, -1);

    do {
	ReadXString(buf, 200);
	s = crypt(buf, pw->pw_passwd);
	} while (! (strcmp(s, pass) == 0));

    XUngrabMouse();
    XFocusKeyboard(RootWindow);
    XDestroyWindow(w);
    XFlush();
}

thomas@spline.UUCP (04/03/87)

This program is not very secure if you use the command line password.
Someone need only log into your machine and do a 'ps', and presto!
they have your password.  Better to require typing it to the program
upon startup.  This can fix one of the bugs: other people being able
to lock your screen.  If you require the user to type the password upon
startup, then he/she will know what it is and will be able to get out.

=Spencer   ({ihnp4,decvax}!utah-cs!thomas, thomas@cs.utah.edu)

jonah@uwocsd.UUCP.UUCP (04/04/87)

The following is a slightly more secure version of a program recently
posted by Walter Milliken.  Unfortunately, it was all too easy for a
knowledgeable user to subvert the original version.  The following is
more robust in that it tries to recover from malicious tampering with
the window environment.
---
Jeff Lee,  Research Associate,  Department of Computer Science
The University of Western Ontario,  London Canada, N6A 5B7
jonah@uwocsd.UWO.CDN, jonah@uwocsd.UUCP, decvax!utzoo!deepthot!jonah
------------------------------Tear Here-----------------------------
: To unbundle, sh this file
echo xsecure.1 1>&2
cat >xsecure.1 <<'--End of xsecure.1--'
TH XSECURE 1 "2 April 1987" "X Version 10"
SH NAME
xsecure - secure a workstation from malicious fingers
SH SYNOPSIS
B xsecure
[password]
SH DESCRIPTION
This program provides a means of locking up a workstation without
logging out.  It also runs as a screen-saver while active.
PP
B xsecure
gobbles all keyboard and mouse events until the password is
typed to it, whereupon it exits.  The password defaults to the user's
login password.  (The optional command line password is for the benefit
of those who are incurably paranoid about equines in Asia Minor.)
PP
B xsecure
fills the screen with black and bounces a small cursor
around while running.  The user's screen will be restored when xsecure
exits.
SH BUGS
The password must be typed on a line by itself.
PP
You can lock up someone else's machine if you can display to them.
(No X Cookie Monsters, please!)
PP
The cursor will have to be fixed on machines which can't handle a
32x32 cursor.
PP
It is possible to interfere with the
B xsecure
window remotely.
On the other hand, it is reasonably secure in a non-hostile
evnironment.
--End of xsecure.1--
echo xsecure.c 1>&2
cat >xsecure.c <<'--End of xsecure.c--'
/* secure a SUN console under X */

/*      Walter Milliken                 (milliken@bbn.com)
        BBN Advanced Computers, Inc.
        10 Fawcett St.
        Cambridge, MA 02238

   modified for paranoids by:
        Jeff Lee,                       (jonah@uwocsd.UUCP)
        Department of Computer Science
        The University of Western Ontario,
        London Canada, N6A 5B7
*/

#include <stdio.h>
#include <pwd.h>
#include <X/Xlib.h>

char * crypt();
char geometry[40];

#define lckcurs_width 32
#define lckcurs_height 32
#define lckcurs_x_hot 16
#define lckcurs_y_hot 20
static short lckcurs_bits[] = {
   0x0000, 0x0000, 0xe000, 0x0007,
   0xf800, 0x001f, 0xfc00, 0x003f,
   0x3e00, 0x007c, 0x0f00, 0x00f0,
   0x0700, 0x00e0, 0x0380, 0x01c0,
   0x0380, 0x01c0, 0x0380, 0x01c0,
   0x01c0, 0x0380, 0x01c0, 0x0380,
   0x01c0, 0x0380, 0x01c0, 0x0380,
   0x0008, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0xc000, 0x0003,
   0xe000, 0x0007, 0xf000, 0x000f,
   0xf000, 0x000f, 0xf000, 0x000f,
   0xe000, 0x0007, 0xc000, 0x0003,
   0xc000, 0x0003, 0xc000, 0x0003,
   0xc000, 0x0003, 0xc000, 0x0003,
   0x0000, 0x0000, 0x0000, 0x0000,
   0x0008, 0x1000, 0x0000, 0x0000};

#define lckmask_width 32
#define lckmask_height 32
static short lckmask_bits[] = {
   0xe000, 0x0007, 0xf800, 0x001f,
   0xfc00, 0x003f, 0xfe00, 0x007f,
   0xff00, 0x00ff, 0x3f80, 0x01fc,
   0x0f80, 0x01f0, 0x07c0, 0x03e0,
   0x07c0, 0x03e0, 0x07c0, 0x03e0,
   0x03e0, 0x07c0, 0x03e0, 0x07c0,
   0x03e0, 0x07c0, 0x03f0, 0x0fc0,
   0xfff0, 0x0fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff8, 0x1fff, 0xfff8, 0x1fff,
   0xfff0, 0x0fff, 0x0000, 0x0000};


struct passwd * pw;

Display * dsp;
OpaqueFrame frame;
Window w;
Cursor mycursor;

XEvent evt;
XKeyPressedEvent * kpevt;


ReadXString(s, slen)
char * s;
int slen;
{
    int bp;
    char c;
    int n;
    char * keystr;
    WindowInfo info;


    bp = 0;
    c = 'x';
    while (c != 'r') {
        if (XPending() == 0) {
            /* speaking of paranoid, lets make sure no one is playing around */
            if (XQueryWindow(w,&info)) {
                /* make sure that the window still covers the screen */
                XConfigureWindow(w,0,0,DisplayWidth(),DisplayHeight());
                XMapWindow(w);
            }
            else {
                /* the window died(?) so make a new one */
                w = XCreate("xsecure","xsecure",geometry,"",&frame,10,10);
                XSelectInput(w, KeyPressed);
                XMapWindow(w);
            }
            XWarpMouse(w, (random() % (DisplayWidth()-64))+32,
                       (random() % (DisplayHeight()-64))+32);
            /* make sure we are still getting keyboard and mouse events */
            XFocusKeyboard(w);
            XGrabMouse(w, mycursor, -1);
            sleep(2);
            }
        else {
            XNextEvent(&evt);
            if (evt.type == KeyPressed) {
                keystr = XLookupMapping(kpevt, &n);
                if (n>0) {
                    c = keystr[0];
                    if (c == 'r') s[bp] = '0';
                    else s[bp] = c;
                    if (bp < slen-1) bp++;
                    }
                }
            else ; /* discard other events */
            }
        }
}


main(argc, argv)
int argc;
char * argv[];
{
    char buf[200];
    char * pass;
    char cryptpass[20];
    char * s;
    int n;
    int i;
    int done;


    pw = getpwuid(getuid());
    if (argc == 1) pass = pw->pw_passwd;
    else if (argc == 2) {
        pass = crypt(argv[1], pw->pw_passwd);
        strcpy(cryptpass, pass);
        pass = cryptpass;
        }
    else {
        fprintf(stderr, "usage: %s [<lock password>]n", argv[0]);
        exit(1);
        }

    kpevt = (XKeyPressedEvent *) &evt;
    dsp = XOpenDisplay(NULL);
    mycursor = XCreateCursor(lckcurs_width, lckcurs_height, lckcurs_bits,
                             lckmask_bits, lckcurs_x_hot, lckcurs_y_hot,
                             BlackPixel, WhitePixel, GXcopy);
    frame.bdrwidth = 0;
    frame.border = BlackPixmap;
    frame.background = BlackPixmap;
    sprintf(geometry, "%dx%d+0+0", DisplayWidth(), DisplayHeight());
    w = XCreate(argv[0], argv[0], geometry, "", &frame, 10, 10);

    XSelectInput(w, KeyPressed);
    XMapWindow(w);
    XFocusKeyboard(w);
    XGrabMouse(w, mycursor, -1);

    do {
        ReadXString(buf, 200);
        s = crypt(buf, pw->pw_passwd);
        } while (! (strcmp(s, pass) == 0));

    XUngrabMouse();
    XFocusKeyboard(RootWindow);
    XDestroyWindow(w);
    XFlush();
}

--End of xsecure.c--