home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3191 / locktty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  5.5 KB  |  245 lines

  1. /* locktty - lock terminal 
  2.  *
  3.  * compile with cc -o locktty locktty.c -lcurses -ltermcap
  4.  * Usage: locktty [ -p ]
  5.  *
  6.  * locktty puts the terminal into raw mode, clears the screen, and
  7.  * prompts the user for a password. Entered passwords are crypted and
  8.  * checked against a crypted password in a file in the users' home
  9.  * directory (~/.lockpasswd). If the correct password is given, the
  10.  * terminal is set into normal state again. If not, a messgae is
  11.  * given, and after some time a new password is read.
  12.  * If the file ~/.lockpasswd does not exist, the user is prompted for
  13.  * a password twice before the screen is locked. This password is
  14.  * crypted and stored in ~/.lockpasswd.
  15.  * The encrypted password in ~/.lockpasswd can be changed by invoking
  16.  * locktty with the -p option.
  17.  *
  18.  * Please send corrections, improvements, and flames to
  19.  *    nickel@w104zrz.zrz.tu-berlin.de (Juergen Nickelsen)
  20.  */
  21.  
  22. #include <curses.h>
  23. #include <signal.h>
  24. #include <stdio.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <string.h>
  28.  
  29. #define true    1
  30. #define false    0
  31.  
  32. #define SIZE    1024        /* maximum size for password */
  33. #define PFILE    ".lockpasswd"    /* name of password file */
  34. #define MAXPATHLEN    4096    /* this should exceed the real value
  35.                  * on nearly all machines */
  36. #define CLEN    14        /* enough for the crypted pwd's */
  37. #define LOCKP    "Unlock: "    /* prompt in "lock" mode */
  38. #define SALTC    \
  39.     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"
  40.                 /* characters that may appear in the salt */
  41. char
  42.     *progname,            /* the name of the game */
  43.     newc[CLEN + 1],        /* entered pwd (crypted) */
  44.     oldc[CLEN + 1],        /* old pwd (crypted) */
  45.     pfilnam[MAXPATHLEN] ;    /* name of password file */
  46.  
  47.  
  48. main(argc, argv)
  49. int argc ;
  50. char **argv ;
  51. {
  52.     char 
  53.     tmpl[SIZE+1],        /* space for reading from terminal */
  54.     *slp ;            /* pointer to slash in progname */
  55.     int pwdfile ;        /* read handle for password file */
  56.  
  57.     /* determine name of program */
  58.     progname = *argv ;
  59.     if (slp = strrchr(progname, '/')) {
  60.     progname = slp + 1 ;
  61.     }
  62.  
  63.     /* build name of password file */
  64.     strcpy(pfilnam, getenv("HOME")) ;
  65.     strcat(pfilnam, "/") ;
  66.     strcat(pfilnam, PFILE) ;
  67.  
  68.     prepterm() ;        /* prepare terminal */
  69.  
  70.     if (argc > 1) {        /* check arguments */
  71.     if (strcmp(argv[1], "-p") || argc != 2) {
  72.         reset() ;
  73.         usage() ;
  74.         exit(1) ;
  75.     } else {
  76.         newpwdfile() ;    /* -p: new password */
  77.     }
  78.     }
  79.  
  80.     /* Open password file. If it does not exist, create it first. */
  81.     do {
  82.     if ((pwdfile = open(pfilnam, O_RDONLY)) == -1) {
  83.         if (errno == ENOENT) {
  84.         puts("No password file.\r") ;
  85.         newpwdfile() ;
  86.         } else {
  87.         perror(pfilnam) ;
  88.         reset() ;
  89.         exit(errno) ;
  90.         }
  91.     }
  92.     } while (pwdfile == -1) ;
  93.     
  94.     /* read and check old crypt */
  95.     if (read(pwdfile, oldc, CLEN) != CLEN || checkoldc()) {
  96.     fputs("~/", stdout) ;
  97.     fputs(PFILE, stdout) ;
  98.     puts(" in wrong format\r") ;
  99.     reset() ;
  100.     exit(3) ;
  101.     }
  102.  
  103.     /* clear screen and read password */
  104.     do {
  105.     clear() ;
  106.     refresh() ;
  107.     fputs(LOCKP, stdout) ;
  108.  
  109.     readpass(tmpl, false) ;
  110.     strcpy(newc, crypt(tmpl, oldc)) ;
  111.     } while (strcmp(newc, oldc) && (puts("\r\nNo way.\r"), sleep(3), 1)) ;
  112.  
  113.     /* ready */
  114.     reset() ;
  115.     exit(0) ;
  116. }
  117.  
  118.  
  119. /* read a line in raw mode, terminated by newline or carriage return
  120.  * or exceeding SIZE. Can get interrupted by Ctrl-C if intr != 0. */
  121. readpass(p, intr)
  122. char *p ;
  123. int intr ;
  124. {
  125.     int n ;
  126.     char c = ' ' ;
  127.  
  128.     for (n = 0; n < SIZE && c != '\r' && c != '\n'; n++) {
  129.     c = p[n] = getchar() ;
  130.     if (intr && c == '\003') {
  131.         reset() ;
  132.         exit(1) ;
  133.     }
  134.     }
  135.     p[n] = '\0' ;
  136. }
  137.  
  138.  
  139. /* prepare terminal: open stdin and stdout to /dev/tty, don't echo */
  140. /* characters and make sure we get no signal (raw mode + some help). */
  141. prepterm()
  142. {
  143.     int in ;
  144.  
  145.     /* we want to read the password ONLY from a terminal */
  146.     if ((in = open("/dev/tty", O_RDWR)) == -1) {
  147.     perror("/dev/tty") ;
  148.     exit(1) ;
  149.     }
  150.     close(0) ;
  151.     dup(in) ;
  152.     close(1) ;
  153.     dup(in) ;
  154.     close(2) ;
  155.     dup(in) ;
  156.  
  157.     /* make sure we won't get interrupted */
  158.     initscr() ;
  159.     raw() ;
  160.     /* the break key on ISC's at386 console generates a SIGINT even in
  161.      * raw mode */
  162.     signal(SIGINT, SIG_IGN) ;
  163.  
  164.     /* don't echo keystrokes */
  165.     noecho() ;
  166. }
  167.  
  168.  
  169. /* put terminal into a state the user is supposed to want after the */
  170. /* termination of the program. */
  171. reset()
  172. {
  173.     clear() ;
  174.     noraw() ;
  175.     echo() ;
  176.     endwin() ;
  177.     putchar('\r') ;
  178.  
  179. }
  180.  
  181.  
  182. /* create a new password file */
  183. newpwdfile()
  184. {
  185.     char tmpl[SIZE+1], salt[3] ;
  186.     int out ;
  187.  
  188.     /* make salt for crypt */
  189.     srand(time(NULL)) ;
  190.     salt[0] = SALTC[rand() % strlen(SALTC)] ;
  191.     salt[1] = SALTC[rand() % strlen(SALTC)] ;
  192.     salt[3] = '\0' ;
  193.  
  194.     /* read and verify password */
  195.     fputs("Enter password:  ", stdout) ;
  196.     readpass(tmpl, true) ;
  197.     strcpy(oldc, crypt(tmpl, salt)) ;
  198.     fputs("\r\nRetype password: ", stdout) ;
  199.     readpass(tmpl, true) ;
  200.     strcpy(newc, crypt(tmpl, salt)) ;
  201.     newc[CLEN] = '\0' ;
  202.  
  203.     if (strcmp(oldc, newc)) {
  204.     puts("\r\nNo match.\r") ;
  205.     reset() ;
  206.     exit(2) ;
  207.     }
  208.  
  209.     /* create password file */
  210.     if ((out = open(pfilnam, O_WRONLY | O_CREAT, 0600)) == -1) {
  211.     reset() ;
  212.     perror(pfilnam) ;
  213.     exit(errno) ;
  214.     }
  215.  
  216.     /* write crypt */
  217.     write(out, newc, CLEN) ;
  218.     close(out) ;
  219. }
  220.  
  221.  
  222. usage()
  223. {
  224.     fputs("Usage: ", stdout) ;
  225.     fputs(progname, stdout) ;
  226.     puts(" [ -p ]\r") ;
  227. }
  228.  
  229.  
  230. /* returns true if oldc does not look like a valid crypt */
  231. checkoldc()
  232. {
  233.     int i ;
  234.  
  235.     /* check for illegal characters */
  236.     for (i = 0; i < CLEN - 1; i++) {
  237.     if (!strchr(SALTC, oldc[i])) {
  238.         return true ;
  239.     }
  240.     }
  241.  
  242.     /* check for terminating null character */
  243.     return oldc[i] ;
  244. }
  245.