title "tShell logon module version 0.60" ; ; (c) 1985 S. Kluger, All Rights Reserved. ; This is the logon module for tShell. It ; should be copied to 31A:WARMSTRT.AUT. ; ; History: ; 12/14/85 started, completed default logon code, ; completed userid/password entry routine. ; 12/15/85 ready for extensive testing! ; 12/20/85 added drive access display ; 12/21/85 added priv level display ; 12/22/85 added logoff before logon, made DELETED flag work ; 01/01/86 changed for USRSUP ; 01/04/86 started clock inop code ; cr equ 0dh lf equ 0ah cfunc equ 5 tfunc equ 50h jconv equ 10958 tries equ 4 ; up to 4 missed logons in a row wait equ 60 ; number of seconds to delay after n tries ; .z80 .request syslib ; ; +----------------------+ ; | data storage section | ; +----------------------+ ; dseg ; INCLUDE TSHELL.DEF ; idfcb: db 1,'TSHELL IDS',0,0,0,0 ; password file ds 22 logfcb: db 1,'TSHELL LOG',0,0,0,0 ; activity log ds 22 crtfcb: db 1,'TSHELL CRT',0,0,0,0 ; crt configuration file ds 22 lgofcb: db 1,'TSHELL SCR',0,0,0,0 ; logo file ds 22 bulfcb: db 1,'TSHELL BUL',0,0,0,0 ; bulletin file ds 22 ; rqid: db ' ' ; requested user id rqpw: db ' ' ; requested password ; idsize: dw 0 ; password file size (must be < 8M) ; retry: db tries ; retry counter delay: db wait ; inbuf1: db 5 db 0 hhmm: db '00:00' ; inbuf: db 8 ccnt: db 0 ; @dcfld::db '00/00/00 at ',0 mnon: db 'nonprivileged',0 msemi: db 'restricted',0 mfull: db 'full access',0 ; bauds:: db 5,6,7,10,12,14,15,0ffh ds 9 ; actlog: db 1ah actid: ds 8 ; activity log user id actdt: ds 4 ; date/time actst: ds 2 ; station act01: db 0 ; on/off/bad flag (1/0/FF) actdu: ds 2 ; drive/user actbp: ds 8 ; bad password given db 1ah,1ah,1ah,1ah,1ah,1ah ; filler ; mstrs: db 0 ; master date reset code (c9=ok) ; id: db '.tShell.' offset: db 0 mstoff: db 0 ; ; default buffer. this buffer is overwritten as soon ; as a valid password file is detected. ; defbuf: db 'UNLOGGED',2,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh db 'ABCDEFGHIJKLMNOP',1,1 ds 128-($-defbuf) ; reserve 128 bytes ds 40 ; stack space stack equ $ ; ; +------------------+ ; | code begins here | ; +------------------+ ; cseg ; start: jr .skcls ; skip past cls code ; defcls: db 2,1bh,'E',0,0 ; default clearscreen 'Copyright (c) 1985 S. Kluger. All Rights Reserved. ' ; .skcls: ld sp,stack ; set up local stack ld c,8 ; set abort address ld de,abort ; point to any RET call tfunc ld de,80h ld hl,id ld bc,8 ldir ld bc,41 ld l,0 call tfunc ld (offset),a ; save offset or a jp z,fatal ; fatal error if no USR FCN ld bc,0fe29h ; now set reset time in master ld de,0 ld l,0 call tfunc ld (mstoff),a call resmt ld c,13 ; set compatibility flags ld e,0f8h call tfunc ld bc,41 ; log off tShell ld de,0ffffh ld l,2 call getoff ; get usrsup offset call tfunc ld de,idfcb ; get password file push de ld c,35 ; filesize function call cfunc ld hl,(idfcb+33) ; get size ld (idsize),hl ; save it pop de ; get fcb back or a jp nz,deflog ; default logon without any ado ld hl,defcls ; default clearscreen call crtctl call print## cr,lf 'tShell (c) 1985 S. Kluger, All Rights Reserved.' ' 8-bit Station ',0 ld c,12 ; get network address call cfunc ld a,d add a,'A' call cout## ld a,'-' call cout## ld a,e call pafdc## call crlf## ld de,lgofcb call fi0$open## ; open for byte read call z,dsplgo ; display logo if found ld de,USERID ; set dma to password file template ld c,26 call cfunc idloop: ld hl,actlog+1 ld b,25 .zal..: ld (hl),0 inc hl djnz .zal.. call print## ; now ask for userid cr,lf 'Enter User ID >',0 ld hl,rqid call get8 ; get up to 8 chars call print## ; now ask for password cr,lf 'Enter Password >',0 ld hl,rqpw call get8n ; get up to 8 chars without echo ld hl,rqid ld de,actid ld bc,8 ldir ; move name to log line ld de,idfcb call openf ; now open password file ld hl,(idsize) ; get filesize ld a,h or l ; if initially 0k file... jp z,errlog ; then error .rpfl.: dec hl ; decrement file pointer ld (idfcb+33),hl ; set file pointer ld de,idfcb ; point to file call rdsec ; read a sector jp nz,errlog ; default logon if error call match ; try to match userid/password ld hl,(idfcb+33) ; get pointer ld a,h or l ; if not yet 0... jr nz,.rpfl. ; ...then loop ld de,idfcb ; else close file ld c,16 call cfunc call print## cr,lf,7 'ERROR: invalid logon',cr,lf,0 ld hl,rqpw ld de,actbp ld bc,8 ldir ; move bad password ld a,0ffh ld (act01),a ; set bad flag call applog ; append to log file ld a,(retry) dec a ld (retry),a jp nz,idloop call print## cr,lf,lf 9,9,9,'*** SECURITY ACCESS VIOLATION ***',cr,lf,lf 'WAIT: [',0 ..try.: ld a,(delay) dec a ld (delay),a jr z,.kill call pa3dc## call print## ']',7,7,7,7,8,8,8,8,0 ld c,2 ld de,60 ; 60 ticks call tfunc jr ..try. ; .kill: ld bc,41 ld l,6 call getoff call tfunc ..inf: call cin## jr ..inf ; ; attempt to match typed id/pw with the current sector ; return only if no match ; match: call decryp ; decrypt sector ld hl,USERID ld de,rqid ld b,8 call compb## ; compare userid ret nz ; return if error ld hl,PASSWD ld de,rqpw ld b,8 call compb## ; compare password ret nz ; return if error ld a,(LEVEL) ; get priv level cp 0e5h ; deleted? ret z ; yes, ignore ld hl,USERID ld de,defbuf ; move for update ld bc,128 ldir ld de,defbuf ld c,26 call cfunc ; set dma ld c,10 call tfunc ; get date/time ld (defbuf+(LASTON-USERID)),hl ; store date ld (defbuf+(LASTON+2-USERID)),de ; store time ld c,12 ; get ckt/node call cfunc ld (defbuf+(LASTPR-USERID)),de ; store it call encryp ; encrypt ld de,idfcb call wrsec ; write sector back ld c,16 ld de,idfcb call cfunc ; close ; ; housekeeping done, now transpose data to the ; user data block and log him on ; ld hl,USERID ld de,LCLID ld bc,8 ldir ld a,(LEVEL) ld (LCLLV),a ld a,(USRCOD) ld (LCLUSC),a ld hl,(DRVACC) ld (LCLDRA),hl ld hl,(USRACC) ld (LCLUSA),hl ld hl,(USRACC+2) ld (LCLUSA+2),hl ld hl,DREDEF ld de,LCLRDD ld bc,16 ldir ld a,0ffh ld (LCLLGD),a ld a,(SHRDRV) ld (LCLSHD),a ld hl,(DEFPRT) ld (LCLDPR),hl ld a,(SCREEN) ld (LCLSCM),a ld a,(INITUS) ; get initial user ld e,a ; put into e ld a,(INITDR) ; get initial drive ld d,a ld (actdu),de ; save in activity log ld a,1 ; set on flag ld (act01),a push de call applog pop de ld a,(LEVEL) ; get acl and 3 cp 2 ; see if full jr nz,..nf. ; no ld a,80h or e ld e,a ..nf.: ld c,14 call tfunc inc a ; see if t-logon ok jp z,log.er ; no, error!!! ld de,LCLID ; set dma ld c,26 call cfunc ld de,0ffffh ; set security ld bc,41 ld l,1 call getoff call tfunc ; attempt tShell logon or a jp nz,log.er ; error! ld a,(mstrs) ; see if master was date-reset inc a jp nz,..mrtk ; yes, reset time ok call resmt ; else try now inc a jp nz,..mrtk call print## cr,lf,lf 'Please enter:',cr,lf,0 .date.: call print## cr,'Date : [MM/DD/YY]',8,8,8,8,8,8,8,8,8,0 ld hl,inbuf call bline## cp 8 jr nz,.date. call @udcvt## ; convert date jr c,.date. ld de,jconv add hl,de push hl ; save julian date ld a,' ' ld (@dcfld+8),a call crlf## .time.: call print## cr,'Time : [HH:MM]',8,8,8,8,8,8,0 ld hl,inbuf1 call bline## cp 5 jr nz,.time. ld hl,hhmm call eval10## push af inc hl call eval10## pop af ld d,a pop hl ld b,0 ld c,9 call tfunc call resmt ..mrtk: call print## cr,lf,lf 'Logged on ',0 ld c,10 call tfunc call time ld hl,(LASTON) ld a,h or l ; ever been on? jr z,.never ; no, skip call print## '. Last on ',0 ld de,(LASTON+2) call time call print## ' on terminal ',0 ld hl,(LASTPR) ld a,'A' add a,h call cout## ld a,'-' call cout## ld a,l call pafdc## .never: call print## cr,lf,lf 'Privilege level ',0 ld a,(LEVEL) and 3 add a,'0' call cout## call print## ' (',0 ld hl,mnon ; expect nonpriv sub 30h jr z,..ppl ld hl,msemi dec a jr z,..ppl ld hl,mfull ..ppl: call pstr## call print## ')',cr,lf 'Drive access: ',0 ld de,80h ; set dma to 80h ld c,26 call cfunc ld bc,41 ld de,0ffffh ld l,10 ; get dskast call getoff call tfunc ld hl,80h ; hl=pointer ld de,3 ; de=increment ld b,16 ; b =count ld c,0 ; c =drive .ckdr.: ld a,(hl) ; get access byte inc a ; see if FF jr z,.ckna. ; yes, no access ld a,'A' ; make drive letter add a,c call cout## ; print it .ckna.: inc c ; bump drive add hl,de ; point to next entry djnz .ckdr. ; and loop till done call crlf## ld de,(DEFPRM) ; get default printer stuff ld b,0ffh ; do not change spool drive ld c,27 call tfunc ld a,(LEVEL) ; get access codes and 80h ; see if menu jp nz,wrmxit ; yes, exit with warmstart ld de,CMDLN ; point to command line ld a,(de) ; get count or a ; empty? jr z,.skc.. ; yes, skip ld c,18 call tfunc .skc..: jp nwrmxt ; exit without warmstart ; ; default error logon (this should never happen, but...) ; errlog: call print## cr,lf,lf,7 'ERROR: munched password file? Call sysadmin.',cr,lf,lf,0 ld a,30 ld (deflog+3),a ; make logon user 30, nonpriv ; ; default logon, priv 0A: ; deflog: ld c,14 ; logon ld de,80h ; priv level 1 call tfunc inc a ; test error jp z,log.er ld de,defbuf ; point to default buffer ld c,26 call cfunc ; set dma ld bc,41 ; log into tshell ld de,0ffffh ld l,1 call getoff call tfunc or a jp nz,log.er call crlf## rst 0 ; ; subroutines ; ; display logo file ; dsplgo: call f0$get## ; get a byte jr nz,.dslx ; eof maybe or some other error and 7fh ; strip parity cp 1ah ; eof? jr z,.dslx ; yes cp 7fh ; another way to mark eof jr z,.dslx ; yes call cout## ; display character jr dsplgo ; and loop ; .dslx: call fi0$close## ; close file abort: ret ; ; get up to 8 characters ; get8n: ld d,1 jr .g8. ; get8: ld d,0 .g8.: call .g8zl ; clear input line ld b,8 ; set max count .g8l: call capin## ; get a character, capitalize cp ' '+1 ; check if space or less jr nc,.g8nc ; no, continue cp 8 ; backspace? jr z,.g8bs cp 7fh ; delete? jr z,.g8bs cp cr ; return? jr nz,.g8er ; no, error ld a,8 ; see if b=8 cp b ret nz ; typed something (b<8) .g8er: call error jr .g8l ; .g8nc: bit 0,d ; see if echo on call z,cout## ld (hl),a inc hl djnz .g8l ; loop .g8wcr: call capin## ; wait for cr or bs cp cr ret z ; return if cr cp 7fh jr z,.g8bs ; backspace if delete key cp 8 jr z,.g8bs call error jr .g8wcr ; ; process backspace ; .g8bs: ld a,8 ; see if b=8 cp b jr z,.g8er ; can't backspace on blank line inc b ; increment counter dec hl ; decrement pointer ld (hl),' ' ; blank out bit 0,d ; test echo flag jr nz,.g8l ; loop back if echo off call print## ; else wipe out char on screen 8,' ',8,0 jr .g8l ; ; zero input line ; .g8zl: push hl ld b,8 .g8zll: ld (hl),' ' inc hl djnz .g8zll pop hl ret ; log.er: ld b,a call logerr ; display logon error message inc b jr z,l.ts.e call print## 'TurboDOS',0 jp wrmxit ; exit with warmstrt on ; l.ts.e: call print## 'tShell',0 ; ; exit with warmstart enabled ; wrmxit: ld e,0ffh jr exit ; ; exit with warmstart disabled ; nwrmxt: ld e,0 exit: ld c,17 ; warmstart function call tfunc call print## cr,lf,lf,0 ld hl,USERID ; be sure to blank data area ld bc,stack-USERID .bldl: ld (hl),0 inc hl dec bc ld a,b or c jr nz,.bldl rst 0 ; exit to tdos ; logerr: call print## cr,lf,lf 'ERROR: Cannot log on! Error source: ',0 error: ld a,7 ; sound bell jp cout## ; ; crt control routine ; input: hl points to string ... ; uses hl, af ; crtctl: ld a,(hl) or a ret z ; return if null push bc ld b,a ; count to b .crctl: inc hl ld a,(hl) call cout## djnz .crctl pop bc ret ; ; open file with lock ; openf: ld hl,5 ; point to shared flag add hl,de ld a,80h or (hl) ld (hl),a ; set shared flag push de ld c,15 call cfunc pop de ld hl,32 add hl,de ld (hl),0 or a ret z ; file is now open jr openf ; else loop since we know file exists ; ; read a sector - enter with hl = sector, de = fcb ; rdsec: call loksec ; lock sector push de ld c,33 ; read call cfunc or a ; set error flag jr fresec ; free sector ; ; write a sector - enter with hl = sector, de=fcb ; wrsec: call loksec ; lock sector push de ; save fcb ld c,34 ; write call cfunc or a ; set error flag ; ; free current file sector ; fresec: pop de push af ld c,43 call cfunc pop af ret ; ; lock current file sector ; loksec: push de ; save fcb pointer ld c,42 ; attempt lock call cfunc pop de cp 8 ; locked already? jr z,loksec ; yes, loop ret ; ; decrypt user block ; decryp: ld hl,USERID ret ; ; encrypt default buffer ; encryp: ld hl,defbuf ret ; time: push de ld de,-jconv add hl,de call @dcvrt## ld hl,@dcfld call pstr## pop de ld a,d call ..10 ld a,':' call cout## ld a,e ..10: cp 10 jr nc,..10. push af ld a,'0' call cout## pop af ..10.: jp pafdc## ; ; append to activity log ; applog: ld de,logfcb ; point to log ld c,35 ; filesize call cfunc or a ret nz ; ignore file not found ld c,10 call tfunc ; get date/time ld (actdt),hl ld (actdt+2),de ld c,12 call cfunc ; get station ld (actst),de ld hl,(logfcb+33) dec hl ld (logfcb+33),hl ; decrement file pointer ld de,logfcb call openf ; open shared ld de,80h ; set defdma ld c,26 call cfunc ld de,logfcb call rdsec ; read last sector ld hl,80h ; hl=pointer to def dma ld de,20h ; de=byte count ..ckel: ld a,(hl) ; get byte cp 0ffh ; endmark? jr z,.fe.. ; yes add hl,de ld a,l or a jr nz,..ckel ; try next entry ld hl,(logfcb+33) inc hl ld (logfcb+33),hl ld hl,80h ; set start of buffer push hl .zac.: ld (hl),0ffh ; blank buffer inc l jr nz,.zac. pop hl .fe..: ld de,actlog ex de,hl ld bc,32 ; 32 bytes to be moved ldir ld a,l ; see if end of buffer or a jr z,.eob. ; yes, skip ld (hl),0ffh ; else set endmark .eob.: ld de,logfcb call wrsec ; write the sector ld de,logfcb ld c,16 jp cfunc ; close and exit ; getoff: ld a,(offset) add a,l ld l,a ret ; ; reset master reset date/time ; resmt:: ld a,(offset) add a,16 ld l,a ld bc,41 call tfunc ; get master node ex de,hl ld a,(mstoff) add a,15 ld l,a ld bc,0fe29h call tfunc ld (mstrs),a ; save master date set code ret ; fatal: call print## cr,lf,lf,7 'ERROR: tShell not installed',cr,lf,lf,0 rst 0 end  dma ld de,20h ; de=byte count ..ckel: ld a,(hl) ; get byte cp 0f