C
      PROGRAM TERM_LOCK
C
C ***********************************************************************
C    This program was written, so a user did not have to log off the
C     system every time they left their terminal. I had in mind priveleged
C     accounts at the time. The program does not require any priveleges to
C     run. There is a problem, where I cannot include the code to LGI$HPWD.
C     This is DEC's password hashing function, however it is supplied in
C     the VMS micro-fiche, but I did include the object file. Another little
C     program needed was UAI_DEF.MAR, this program when assembled, provides
C     the needed symbols for $GETUAI. To put TERM_LOCK altogether, execute
C     the following commands:
C
C     FORT TERM_LOCK
C     MACRO UAI_DEF
C     LINK/NOTRACE TERM_LOCK,UAI_DEF,HPWD
C
C    The program starts by disabling CONTROL_Y and CONTROL_T. We know why
C    CONTROL_Y is disabled, CONTROL_T is disabled so that a would be
C    troublemaker cannot find out who is running the program. Next, the image
C    gathers the terminal name and USERNAME that is using this image. If
C    the terminal is over the network and a person presses CONTROL_Y enough
C    the system asks if you are aborting the login, thus one could end up
C    back on someone else's account or prevent somebody from getting to their
C    process. The USERNAME is used to get the appropriate UAF record,
C    especially the correct PASSOWRD. I use $GETUAI, because a user with 
C    no privelges can get only their record, and nobody elses'. Also, because
C    the program uses only the USERNAME running this particular image, a
C    user cannot get at another users' UAF record. After we get this
C    information I begin building pasteboards, virtual displays and keyboard.
C    I chose Screen Management, because it would run on any type terminal.
C    The SMG routines, also let me prompt for the USERNAME and PASSWORD,
C    and at the same time prevent echoing on the screen and converts the 
C    data to uppercase. I next run what the user enters through the hashing
C    routine and compare the hashed quadwords for a correct password match.
C    If the quadwords match, they have entered a valid password and the program
C    exits, otherwise the terminal bell is rung and the user reprompted.
C    I display on the terminal screen, while this image is running, that
C    this is a "SECURE TERMINAL" in double high , double wide , bold text.
C    This message is easily changed.
C
C    I know that the program does not take into account secondary passwords,
C     but, our site does not use them.
C
C    If you find any problems or make any enhancements please let me know.
C    I can be reached at the following address and phone:
C
C                     Gary Sachs
C                     Lawrence Institute of Technology
C                     21000 W 10 Mile Rd.
C                     Southfield, Mi  48075
C                     Ph. 313-356-0200  xtn 3700
C
C    Written by:    Gary Sachs    July 10, 1986
C
C **************************************************************************
C
      IMPLICIT INTEGER (A-Z)
C
      BYTE ENCRYPT
C
      INTEGER*2 SALT , U , P
C
      CHARACTER PASS*31 , USER*12 , USER_NAME*12 , TERMINAL*7
C
      DIMENSION PASS1(2) , PASS2(2) , ECN(2)
C
      EXTERNAL UAI$_SALT,UAI$_ENCRYPT,UAI$_PWD
C
      PARAMETER BLANK = ' '
C
      INCLUDE '($JPIDEF)'
      INCLUDE '($SMGDEF)'
      INCLUDE '($LIBCLIDEF)'
      INCLUDE '($TRMDEF)'
C
      STRUCTURE  /ITMLST/
       UNION
        MAP
         INTEGER*2  BUFLEN , ITMCOD
         INTEGER*4  BUFADR , RETADR
        END MAP
        MAP
         INTEGER*4  END_LIST
        END MAP
       END UNION
      END STRUCTURE
C
      RECORD /ITMLST/ ITM(4)
C
C **********************************************************************
C
C  Disable CONTROL_T and CONTROL_Y.
      MASK = LIB$M_CLI_CTRLT .OR. LIB$M_CLI_CTRLY
      STAT = LIB$DISABLE_CTRL (MASK,)
C
C  Set up an item list to find out what terminal the process is on and the
C   username running this image.
C  Get the terminal.
      ITM(1).BUFLEN = 7
      ITM(1).ITMCOD = JPI$_TERMINAL
      ITM(1).BUFADR = %LOC(TERMINAL)
      ITM(1).RETADR = 0
C
C  Get the username.
      ITM(2).BUFLEN = 12
      ITM(2).ITMCOD = JPI$_USERNAME
      ITM(2).BUFADR = %LOC(USER_NAME)
      ITM(2).RETADR = 0
      ITM(3).END_LIST = 0
C
      STAT = SYS$GETJPI (,,, ITM ,,,)
      IF (.NOT. STAT) CALL LIB$SIGNAL (%VAL(STAT))
C
C  Check to see if we are over the network, if so abort.
      IF (INDEX(TERMINAL , 'RT') .GT. 0) THEN
        PRINT*, 'ABORTING!! NO SECURITY OVER A REMOTE TERMINAL' 
        GOTO 99999
      ENDIF
C
C  Build the item list to gather UAF info.
C  The encryption value.
      ITM(1).BUFLEN = 1
      ITM(1).ITMCOD = %LOC(UAI$_ENCRYPT)
      ITM(1).BUFADR = %LOC(ENCRYPT)
      ITM(1).RETADR = 0
C
C  The salt value.
      ITM(2).BUFLEN = 2
      ITM(2).ITMCOD = %LOC(UAI$_SALT)
      ITM(2).BUFADR = %LOC(SALT)
      ITM(2).RETADR = 0
C
C  The hashed password.
      ITM(3).BUFLEN = 8
      ITM(3).ITMCOD = %LOC(UAI$_PWD)
      ITM(3).BUFADR = %LOC(PASS2)
      ITM(3).RETADR = 0
C
      ITM(4).END_LIST = 0
C
C  Now to get the UAF info.
      STAT = SYS$GETUAI (,, USER_NAME , ITM ,,,)
      IF (.NOT. STAT) CALL LIB$SIGNAL (%VAL(STAT))
C
C  Create a pasteboard and virtual diplay.
      STAT = SMG$CREATE_PASTEBOARD (PSTB ,,,,)
      STAT = SMG$CREATE_VIRTUAL_DISPLAY (10 , 80 , VD1 ,,,)
      STAT = SMG$PASTE_VIRTUAL_DISPLAY (VD1 , PSTB , 1 , 1 ,)
C
C  Create the virtual keyboard.
      STAT = SMG$CREATE_VIRTUAL_KEYBOARD (KB ,,,,0)
C
C  Set teh keypad to numeric mode.
      STAT = SMG$SET_KEYPAD_MODE (KB , 0)
C
C  Display message.
      STAT = SMG$PUT_CHARS_HIGHWIDE (VD1 , 'SECURE TERMINAL' ,
     -                               2 , 32 , SMG$M_BOLD ,,)
C
C  Initialize mask for terminal attributes.
      TRMSK = TRM$M_TM_CVTLOW .OR. TRM$M_TM_NOECHO
C
C  Get the user name.
100   STAT = SMG$REPAINT_SCREEN (PSTB)
      STAT = SMG$SET_CURSOR_ABS (VD1 , 5 , 1)
      STAT = SMG$READ_STRING (KB , USER , 'Enter Username: ',, 
     -                        TRMSK ,,, U ,,,,,)
C
C  Get the password.
      STAT = SMG$SET_CURSOR_ABS (VD1 , 6 , 1)
      STAT = SMG$READ_STRING (KB , PASS , 'Enter Password: ',,
     -                        TRMSK ,,, P ,,,,,)
C
C  Check the encryption value against the Purdy value.
      T = 12
      IF (ENCRYPT .NE. %LOC(UAI$C_PURDY)) T = U
C
C  Build descriptor to receive hashed password.
      ECN(1) = 8
      ECN(2) = %LOC(PASS1)
C
C  Hash the password entered.
      STAT = LGI$HPWD (ECN , PASS(1:P)
     -                ,%VAL(ENCRYPT),%VAL(SALT),USER(1:T))
C
C  Compare hashed passwords.
      IF (PASS1(1) .NE. PASS2(1)) THEN
        STAT = SMG$RING_BELL (VD1 , 10)
        GOTO 100
      ENDIF
C
      IF (PASS1(2) .NE. PASS2(2)) THEN
        STAT = SMG$RING_BELL (VD1 , 10)
        GOTO 100
      ENDIF
C
C  Time to cleanup.
99999 STAT = SMG$DELETE_VIRTUAL_KEYBOARD (KB)
      STAT = SMG$DELETE_VIRTUAL_DISPLAY (VD1)
      STAT = SMG$DELETE_PASTEBOARD (PSTB , )
      STAT = LIB$ENABLE_CTRL (MASK,)
      CALL EXIT
      END
