home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3292
/
locktty.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-06
|
7KB
|
305 lines
/* locktty - lock terminal
* version 1.1
*
* compile with cc -o locktty locktty.c -lcurses -ltermcap
* Usage: locktty [ -p ]
*
* locktty puts the terminal into raw mode, clears the screen, and
* prompts the user for a password. Entered passwords are crypted and
* checked against a crypted password in a file in the users' home
* directory (~/.lockpasswd). If the correct password is given, the
* terminal is set into normal state again. If not, a messgae is
* given, and after some time a new password is read.
* If the file ~/.lockpasswd does not exist, the user is prompted for
* a password twice before the screen is locked. This password is
* crypted and stored in ~/.lockpasswd.
* The encrypted password in ~/.lockpasswd can be changed by invoking
* locktty with the -p option.
*
* Please send corrections, improvements, and flames to
* nickel@cs.tu-berlin.de (Juergen Nickelsen)
*/
#include <curses.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <pwd.h>
#define true 1
#define false 0
#define SIZE 1024 /* maximum size for password */
#define PFILE ".lockpasswd" /* name of password file */
#define MAXPATHLEN 4096 /* this should exceed the real value
* on nearly all machines */
#define CLEN 14 /* enough for the crypted pwd's */
#define SALTC \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"
/* characters that may appear in the salt */
int
uid, /* userid */
fail_count = -1; /* number of failed unlock attempts */
struct passwd
*pw_entry; /* passwd file entry */
char
*progname, /* the name of the game */
newc[CLEN + 1], /* entered pwd (crypted) */
oldc[CLEN + 1], /* old pwd (crypted) */
pfilnam[MAXPATHLEN], /* name of password file */
hostname[20], /* hostname */
prompt[40] ; /* unlock prompt */
extern int errno ;
extern char *getenv(), *crypt() ;
main(argc, argv)
int argc ;
char **argv ;
{
char
tmpl[SIZE+1], /* space for reading from terminal */
*slp ; /* pointer to slash in progname */
int pwdfile ; /* read handle for password file */
/* determine name of program */
progname = *argv ;
if (slp = strrchr(progname, '/')) {
progname = slp + 1 ;
}
/* get host and user names */
if (gethostname(hostname, 19) == -1) {
hostname[0] = '\0' ;
}
uid = getuid() ;
pw_entry = getpwuid(uid) ;
/* note that pw_entry->pw_dir is the user's home dir */
if (pw_entry != NULL) {
if (hostname[0] != '\0') {
sprintf(prompt, "Unlock %s@%s: ", pw_entry->pw_name, hostname) ;
} else {
sprintf(prompt, "Unlock user %s: ", pw_entry->pw_name) ;
}
} else if (hostname[0] != '\0') {
sprintf(prompt, "Unlock host %s ", hostname) ;
} else {
sprintf(prompt, "Unlock: " ) ;
}
/* build name of password file */
strcpy(pfilnam, getenv("HOME")) ;
strcat(pfilnam, "/") ;
strcat(pfilnam, PFILE) ;
prepterm() ; /* prepare terminal */
if (argc > 1) { /* check arguments */
if (strcmp(argv[1], "-p") || argc != 2) {
reset() ;
usage() ;
exit(1) ;
} else {
newpwdfile() ; /* -p: new password */
}
}
/* Open password file. If it does not exist, create it first. */
do {
if ((pwdfile = open(pfilnam, O_RDONLY)) == -1) {
if (errno == ENOENT) {
puts("No password file.\r") ;
fflush(stdout) ;
newpwdfile() ;
} else {
perror(pfilnam) ;
reset() ;
exit(errno) ;
}
}
} while (pwdfile == -1) ;
/* read and check old crypt */
if (read(pwdfile, oldc, CLEN) != CLEN || checkoldc()) {
fputs("~/", stdout) ;
fputs(PFILE, stdout) ;
puts(" in wrong format\r") ;
fflush(stdout) ;
reset() ;
exit(3) ;
}
/* clear screen and read password */
do {
fail_count++;
clear() ;
refresh() ;
fputs(prompt, stdout) ;
fflush(stdout) ;
readpass(tmpl, false) ;
strcpy(newc, crypt(tmpl, oldc)) ;
} while (strcmp(newc, oldc) &&
(puts("\r\nNo way.\r"), fflush(stdout), sleep(3), 1)) ;
/* this is not nice, I know */
/* ready */
reset() ;
if (fail_count) {
printf("Failed attemps: %d\nPress return to exit ", fail_count) ;
fflush(stdout) ;
gets(oldc);
}
exit(0) ;
}
/* read a line in raw mode, terminated by newline or carriage return
* or exceeding SIZE. Can get interrupted by Ctrl-C if intr != 0. */
readpass(p, intr)
char *p ;
int intr ;
{
int n ;
char c = ' ' ; /* to have a value which is neither */
/* '\n' nor '\r' */
for (n = 0; n < SIZE && c != '\r' && c != '\n'; n++) {
c = p[n] = getchar() ;
if (intr && c == '\003') {
reset() ;
exit(1) ;
}
}
p[n] = '\0' ;
}
/* prepare terminal: open stdin and stdout to /dev/tty, don't echo */
/* characters and make sure we get no signal (raw mode + some help). */
prepterm()
{
int in ;
/* we want to read the password ONLY from a terminal */
if ((in = open("/dev/tty", O_RDWR)) == -1) {
perror("/dev/tty") ;
exit(1) ;
}
close(0) ;
dup(in) ;
close(1) ;
dup(in) ;
close(2) ;
dup(in) ;
/* make sure we won't get interrupted */
initscr() ;
raw() ;
/* the break key on ISC's at386 console generates a SIGINT even in
* raw mode */
signal(SIGINT, SIG_IGN) ;
/* don't echo keystrokes */
noecho() ;
}
/* put terminal into a state the user is supposed to want after the */
/* termination of the program. */
reset()
{
int i ;
/* reset modes */
clear() ;
noraw() ;
echo() ;
/* end curses */
endwin() ;
/* delete prompt */
for (i = 0; i < strlen(prompt); i++) {
putchar('\b');
putchar(' ');
putchar('\b');
}
}
/* create a new password file */
newpwdfile()
{
char tmpl[SIZE+1], salt[3] ;
int out ;
/* make salt for crypt */
srand(time(NULL)) ;
salt[0] = SALTC[rand() % strlen(SALTC)] ;
salt[1] = SALTC[rand() % strlen(SALTC)] ;
salt[3] = '\0' ;
/* read and verify password */
fputs("Enter password: ", stdout) ;
fflush(stdout) ;
readpass(tmpl, true) ;
strcpy(oldc, crypt(tmpl, salt)) ;
fputs("\r\nRetype password: ", stdout) ;
fflush(stdout) ;
readpass(tmpl, true) ;
strcpy(newc, crypt(tmpl, salt)) ;
newc[CLEN] = '\0' ;
if (strcmp(oldc, newc)) {
puts("\r\nNo match.\r") ;
fflush(stdout) ;
reset() ;
exit(2) ;
}
/* create password file */
if ((out = open(pfilnam, O_WRONLY | O_CREAT, 0600)) == -1) {
reset() ;
perror(pfilnam) ;
exit(errno) ;
}
/* write crypt */
write(out, newc, CLEN) ;
close(out) ;
}
usage()
{
fputs("Usage: ", stdout) ;
fputs(progname, stdout) ;
puts(" [ -p ]\r") ;
}
/* returns true if oldc does not look like a valid crypt */
checkoldc()
{
int i ;
/* check for illegal characters */
for (i = 0; i < CLEN - 1; i++) {
if (!strchr(SALTC, oldc[i])) {
return true ;
}
}
/* check for terminating null character */
return oldc[i] ;
}