; WHEEL.ASM  -  Password access for ZCPR/ZCMD systems  -  05/20/86
;
;                 copyrighted by Irv Hoff W6FFC
;
;
       ASEG                    ; For M80 and RMAC ignore error with MAC
;
; This program permits the SYSOP to activate the WHEEL byte.  This kicks
; in the drives and user areas set for the Sysop in place of those set
; for the remote user.
;
; There are several ways to change these allocations:
;
;       1) Using ZCMD or ZCPR without BYE5 for remote use
;       2) Using ZCMD or ZCPR with BYE5 for remote use
;       3) Using ZCMD or ZCPR with/without BYE5 with external flow path
;
; All of these cases are covered.  In the case of an external flow path
; be sure to set the EXTPATH equate below.
;
; This program is placed in A0: so the Sysop can request it without the
; WHEEL byte being activated.  Since any user could do the same, several
; levels of security are included:
;
;       1) Go to the 'special attention' area below and:
;               a) add your own password at PSSWD (use only upper-case)
;               b) select remote user's max drive/user
;               c) select Sysop's max drive/user
;               d) select external path (if used in ZCMD or ZCPR)
;
;       2) Assemble and load to get WHEEL.COM
;       3) Rename program for additional security, instead of WHEEL.COM
;       4) Place on A0: and 'hide' with STAT.COM as a .SYS file
;
;               A0>STAT IRV.COM $SYS    ; (So the name can't be seen)
;
;       5) Assuming for the example "HOFF" was chosen for a password:
;
;               A0>IRV HOFF     ; To enable the wheel byte mode
;               A0>IRV -        ; Resets for remote user, types msg.
;               A0>IRV
;                  Password:    ; Requests password, which is not
;                               ; displayed so nobody can see what you
;                               ; are using
;
;-----------------------------------------------------------------------
;
; IRV.COM would be the first level of security.  Hiding it as a system
; file on A0: prevents others from knowing the initial program's name.
; HOFF in this case would be the second level of security.  Even if you
; type:  A0>IRV <ret> when some remote user is watching, and they see
; the request for a password, they will not see your answer.  If it is
; wrong, it wipes out the 'Password: ' and replaces it with the name of
; the program with a '?' as though CP/M doesn't know what you are asking
; for and there is no such program - another mild form of security.
;
; If some twit does attempt to find your initial password (name of pgm)
; and uses the correct name (IRV in this case), it resets for remote
; user (without displaying any message) and then shows IRV? indicating
; no such file exists.  (It really does, but this is an additional level
; of security to discourage twits.)
;
; SUMMARY:
; =======
;       There may be other programs existing with similar features but
;       none I ran across have as much security as this program, which
;       is why I wrote it.  I use it with ZCMD2x, BYE5 and KMD on two
;       different systems, one having a BBS and one without.  This is
;       also useful for giving friends access to your system when you
;       do not have a BBS that automatically asks their name and kicks
;       them in as a Sysop.  The primary use though, is so the Sysop
;       can kick in his own capability whenever he wishes, perhaps on
;       some occasion a particular user is on his system and the Sysop
;       needs more capability than the remote user is normally given.
;
;                                       - Notes by Irv Hoff
       ORG     0100H
;
       JMP     START
;
;
;=======================================================================
;               (start of special attention area)
;
; NOTE: Set the following four values for your system's normal use:
;
RDRIVE  EQU     2               ; Number of drives available to user
RUSER   EQU     12              ; # of highest area for remote users
SDRIVE  EQU     2               ; Number of drives available to SYSOP
SUSER   EQU     15              ; # of highest area for SYSOP (0-15)
;.....
;
;
; Put your password here, end it with a '0', can be 15 characters or
; less, not including the 0.
;
PSSWRD: DB      'PASS'          ; Up to 15 characters, end with 0 below
       DB      0
;
;
; If using an external path, set the following equate YES and check the
; address of the external path in the line following that, usually 40h.
;
EXTPATH EQU     0               ; 0 = NO, 1 = YES
PATHADR EQU     40H             ; Change if needed
;
;               (end of special attention items)
;=======================================================================
;
; Tells the SYSOP the WHEEL byte is now activated
;
WHLMSG: DB      0DH,0AH,'   WHEEL is on',0DH,0AH,'$'
WHLOFF: DB      0DH,0AH,'   WHEEL is off',0DH,0AH,'$'
;.....
;
;
; Equates
;
BDOS    EQU     0005H           ; BDOS location
CR      EQU     0DH             ; Carriage return character
DIRCON  EQU     0006H           ; Direct console call
LF      EQU     0AH             ; Line feed character
FCB     EQU     005CH           ; File control block
DRVMAX  EQU     003DH           ; Location of MAXDRV byte
PRINT   EQU     09H             ; BDOS print a string
USRMAX  EQU     003FH           ; Location of MAXUSER byte
WHEEL   EQU     003EH           ; Location of wheel byte
WRCON   EQU     02H             ; Display a character on CRT
;
;
START:  LDA     FCB+1           ; See what we are supposed to do
       CPI     ' '
       JZ      ASKFOR          ; Nothing typed, ignore request
       CPI     '-'             ; Disable wheel mode
       JZ      DISABLE
;
CHECK:  LXI     H,FCB+1         ; Set up all the pointers
       LXI     D,PSSWRD        ; Location of password buffer
;
CHECK1: LDAX    D               ; Actual password in 'A' register
       ORA     A
       JZ      OK              ; If zero, checks ok
       CMP     M               ; Characters match?
       JNZ     ABORT           ; No check, exit with no changes
       INX     H               ; Address of next password address
       INX     D               ; Address of next password typed entry
       JMP     CHECK1          ; If not zero, check another character
;
OK:     JMP     ENABLE
;
;
;-----------------------------------------------------------------------
;                         subroutines
;-----------------------------------------------------------------------
;
; Aborts if a person happens to type to correct filename, reprints the
; name to throw him off, then resets the system for a remote user, as an
; added level of security.
;
ABORT:  MVI     C,PRINT
       LXI     D,ABTCLR
       CALL    BDOS
;
       LDA     0002H           ; MSP of BIOS address
       SUI     22
       MOV     H,A
       MVI     L,8             ; Index into buffer
;
ABORT1: MOV     A,M             ; Get the character there
       ORA     A               ; See if finished
       JZ      ABORT2
       CPI     ' '
       JZ      ABORT2
       CALL    SHOW
       INX     H               ; Next location
       JMP     ABORT1
;
ABORT2: MVI     A,'?'
       CALL    SHOW
       MVI     A,LF
       CALL    SHOW
;
ABORT3: JMP     DISAB0          ; Go disable the drives
;...
;
;
ABTCLR: DB      CR,'                ',CR,'$' ; wipes out 'Password: '
;.....
;
;
; Asks for a password if none was given, allows typing so nobody can
; see what it is.  (Just the local typist.)
;
ASKFOR: MVI     C,PRINT
       LXI     D,ASKPAS
       CALL    BDOS
       LXI     D,FCB+1         ; Location to put password for compare
;
ASK1:   PUSH    D
       MVI     C,6             ; Direct console I/O
       MVI     E,0FFH          ; Ask for character
       CALL    BDOS
       POP     D               ; Get the address back
       ORA     A
       JZ      ASK1
;
       CPI     'a'             ; Make sure character is upper case
       JC      ASK2
       CPI     'z'+1
       JNC     ASK2
       ANI     5FH             ; Change to upper-case
;
ASK2:   CPI     CR
       JZ      CHECK
       STAX    D
       INX     D
       JMP     ASK1
;...
;
;
ASKPAS: DB      '   Password is: ','$'
;.....
;
;
; Change the external path from Sysop to remote or vice versa
;
CHANGE: MVI     C,7
;
CHANG1: LDAX    D
       MOV     M,A
       INX     D
       INX     H
       DCR     C
       JNZ     CHANG1
       RET
;.....
;
;
; See if BYE5 is active
;
CKBYE:  MVI     C,32
       MVI     E,0F1H
       CALL    BDOS
       CPI     4DH
       RET
;.....
;
;
; Intentional disable shows the WHEEL is off, then resets the system
; for a normal remote user again.
;
DISABLE:MVI     C,PRINT         ; WHEEL "OFF" message
       LXI     D,WHLOFF
       CALL    BDOS
;
DISAB0: XRA     A               ; Turn the WHEEL byte off
       STA     WHEEL
       CALL    CKBYE           ; See if BYE5 is active
       JNZ     DISAB1          ; If yes exit
;...
;
;
; BYE5 is in use, so set things through it.  First get the BYE5 address
; and then increment into the program to the location of max user (+12_
; and max drive (+13).
;
       CALL    SETBYE
;
; Now have the max user address
;
       LDA     RUSER+1
       MOV     M,A
       INX     H               ; Address of max drive
       LDA     RDRIVE
       MOV     M,A
;
;
; No BYE5 in use, assume ZCMD or ZCPR is setting max drive and max user.
;
DISAB1: MVI     A,RUSER+1       ; Sysop maximum user area
       STA     USRMAX
       MVI     A,RDRIVE-1      ; Sysop number of drives
       STA     DRVMAX
       STA     DRVMAX
;
        IF     EXTPATH
       LXI     D,RPATH         ; Remote user external path, prevents
       LXI     H,PATHADR       ;   his using A15:
       CALL    CHANGE
        ENDIF                  ; EXTPATH
;
       JMP     EXIT
;.....
;
;
; Set the WHEEL, max user, max drive but first check to see if BYE is
; active and handle accordingly.
;
ENABLE: MVI     A,0FFH          ; Turn the WHEEL byte on
       STA     WHEEL
;
       MVI     C,PRINT         ; WHEEL in use message
       LXI     D,WHLMSG
       CALL    BDOS
       CALL    CKBYE           ; See if BYE5 is active
       JNZ     ENAB1           ; Exit if BYE5 is in use
;
;
; BYE5 is in use, so set things through it.  First get the BYE5 address
; and then increment into the program to the location of max user (+12_
; and max drive (+13).
;
       CALL    SETBYE
;
; Now have the max user address
;
       LDA     SUSER+1
       MOV     M,A
       INX     H               ; Address of max drive
       LDA     SDRIVE
       MOV     M,A
;
;
; No BYE5 in use, assume ZCMD or ZCPR is setting max drive and max user.
;
ENAB1:  MVI     A,SUSER+1       ; Sysop maximum user area
       STA     USRMAX
       MVI     A,SDRIVE-1      ; Sysop number of drives
       STA     DRVMAX
;
        IF     EXTPATH
       LXI     D,SPATH         ; Sysop external path (includes user 15)
       LXI     H,PATHADR
       CALL    CHANGE
        ENDIF                  ; EXTPATH
;...
;
;
EXIT:   RET                     ; Jump back to original address
;.....
;
;
; Remote user's external path flow - WHEEL off - if any paths are added,
; alter the value at CHANGE: above.
;
RPATH:  DB      '$','$'         ; Current drive, user area
       DB      1,0             ; 'A' drive, 0 user area
       DB      0,0             ; Skips additional checks
       DB      0               ; Finished
;.....
;
;
; Sysop's external path flow - WHEEL off - if any paths are added,
; alter the value at CHANGE: above.
;
SPATH:  DB      '$','$'         ; Current drive, user area
       DB      1,0             ; 'A' drive, 0 user area
       DB      1,15            ; 'A' drive, 15 user area
       DB      0               ; Finished
;.....
;
;
SETBYE: LHLD    0000H+1         ; Warm boot vector address
       DCX     H               ; MSP of cold boot vector
       MOV     D,M             ; Put into 'D' register
       DCX     H               ; LSP of cold boot vector
       MOV     E,M             ; Put into the 'E' register
;
; Now have the BYE5 MCBOOT location, add 6 to find max user location.
;
       LXI     H,6
       DAD     D               ; Add to MCBOOT location
       RET
;.....
;
;
SHOW:   PUSH    H
       MOV     E,A
       MVI     C,WRCON
       CALL    BDOS
       POP     H
       RET
;.....
;
;
       END