; .TITLE scli - Main Security CLI ; .IDENT /1.17/ .REM | *+ scli - Main Security CLI File:scli.mac Version: 1.17 Author: Last Edit: 14-JUN-1985 14:47:43 Last Update: 3-Oct-1985 09:05:46 modify for G.Lab This is the root module for SCLI. It contains initialization, and main-line code. *- | .sbttl CONDITIONALS ;;debug = 0 ; define for debug code ;;bkdoor = 0 ; define to include back door code .list meb .enable lc .LIBRARY /LB:[1,1]GLMAC.MLB/ .mcall push,pop,call,return .sbttl DPBS .psect dpbs d,lcl,con .rem | This psect contains the static dpbs for this module. These are possibly skeletal -- required info is filled in at run-time, and the directives are executed by a DIR$ call. | .MCALL GCCI$,RPOI$,SCLI$,EXIT$S,QIOW$,ALUN$,DIR$ GCCI: GCCI$ CMDBUF,CBLEN,IBUF,IBLEN,0,GC.CST ; note: the definitions for two gcci bits were left out of RSX!? ; the one needed is defined here, from the documentation in EXEC REF. gc.cnl = 1 ; null command line RPOI: RPOI$ SHI SCLI: SCLI$ MCR CLUN: alun$ 2,CO ; assign LUN 2 to console .even .SBTTL LOCAL DATA .psect ldat,d,lcl,con ; ; use this psect for scratch storage - it is not guaranteed to be saved ; across calls to the module ; log1: .word 0 ; reserve some variables for logging log2: .word 0 ; ... log3: .word 0 ; ... ; ; get the global definitions ; .include /sclidat.mac/ .psect data,d,gbl,con ; ; use this psect for module-specific data which must be retained across ; calls to the module ; ; ; BUFFER AREAS ; CMDBUF: .BLKB 255.+G.CCBF ;length = header plus command in bytes ; big enough for M-PLUS command lines CBLEN=.-CMDBUF ;calculate length .EVEN IBUF: .BLKB G.CCCA+2 ;long enough to contain all information IBLEN=.-IBUF ;calculate length .EVEN .if df bkdoor pound: .word 0 ; for testing use - back-door exit .endc rplptr: .word 0 ; pointer to reply string msptr: .word 0 ; general msg pointer pass: .word 0 ; flag we will give tt to mcr nodmp: .word 0 ; flag we will NOT dump raw command ; some strings.... .even .sbttl SCLI Main .PSECT ; code goes in the blank psect INIT: dir$ #CLUN ; assign console lun bcc 100$ ; br if no errors mov $dsw, log1 ; save dsw mov #1, log2 ; num params mov #5, log3 ; error number dolog 9., 100$: ; clear out user-id from tt-table. This shows the init code ; that we are really starting from scratch. mov #tttbl, r0 ; point to tt table 150$: clr tt.uid(r0) ; clear user-id clr tt.tot(r0) ; clear total foo-count clr tt.foo(r0) ; and current foo-count add #ttsiz, r0 ; point to next record tst (r0) ; off end? bne 150$ ; no - loop clr flags ; init flags START: DIR$ #GCCI ;GET A COMMAND FROM SYSTEM bcc 50$ ; br if no error ; directive errors here are simply not tolerated! mov #1, r0 mov $dsw, r1 iot ; crash and burn 50$: ; ; IF THE GCCI$ DIRECTIVE HAD THE GC.CST OPTION SPECIFIED, WE MAY HAVE ; JUST BEEN UNSTOPPED, SO WE HAVE TO GET THE COMMAND. ; CMP #IS.CLR,$DSW ;WERE WE JUST UNSTOPPED? BEQ START ;IF EQ YES MOV #CMDBUF,R0 ;POINT TO COMMAND BUFFER TST (R0) ;IS THIS A SYSTEM MESSAGE? bne 100$ ; no -br .globl domsg call DOMSG ; process system messages br start ; and loop ; ; AT THIS POINT, THE CLI HAS A COMMAND TO BE PROCESSED. THE CODE FROM ; THE "START:" LABEL TO HERE SHOULD BE FAIRLY COMMON AMONG ALL CLIS. 100$: ; just loop on null command lines, mostly to allow ; autobaud dial-up bitb #gc.cnl, g.ccfl(r0) ; null command line bne start ; yes - loop .if df bkdoor ; for testing, if command terminator is , remember this fact, ; and set to MCR regardless of SCLI actions - this is a back-door ; and must be removed for production use! clr pound ; not escape command cmpb #33, g.cctc(r0) ; back-door key? bne 200$ ; nope inc pound ; open back door .endc 200$: clr rplptr ; init to no reply clr pass ; init to no-pass clr nodmp ; will let verbose dump command (for now) movb g.ccct(r0), r1 ; get command length add #g.ccbf, r0 ; point to command text .globl lookup call lookup ; get index into command table mov #cmdbuf, r0 ; point back to gcci buffer mov #cmdtbl, ctptr ; construct pointer to command record mov r2, r3 ; want single-register multiply asr r3 ; make byte offset into record number mul #cmdsiz, r3 ; construct offset cmp r3, #maxcmd ; index within limits bhi 250$ ; index too high - use zero (illegal) add r3, ctptr ; ctptr now points to record in cmdtbl mov ctptr,r3 ; check for message type record cmp #ac.mes, cm.act(r3) ; is this valid only for messages? bhi 250$ ; not a message, br mov #cmdbuf, ctptr ; is a message, so make illegal command inc nodmp ; but don't allow dump of it 250$: mov #tttbl, r4 ; point to beginning of tt-table movb g.ccun(r0), ttnum ; save tt number for logging 300$: cmpb g.ccun(r0), (r4) ; tt match? beq 400$ ; yes - br add #ttsiz, r4 ; point to next record tst (r4) ; off end? bne 300$ ; no - loop ; the command came from an 'unknown' tt??!!!??? ; ; do something nasty to the guy who went SET /CLI=TI:SCLI ; dolog 11., ; log unknown terminal jmp start ; for now, just ignore 400$: mov r4, ttptr ; save pointer to tt record ; with the preliminaries accomplished, see what we should do, and ; do it ; note: ; r5 -> garbage ; r4 -> tt-table record ; r3 = garbage ; r2 = garbage ; r1 = buffer length ; r0 -> GCCI buffer ; bit #fl.mbl, tt.flg(r4) ; tt in mumble mode? beq 1000$ ; no - br ; ; tt is in mumble-mode. issue garbage reply regardless of command, ; and count input commands during mumble-mode ; inc tt.foo(r4) ; increment foo-count mov #rpl0, rplptr ; set 'random' reply br 2000$ ; join common code 1000$: ; here, tt is not now in mumble-mode ; is command a password? mov ctptr, r5 ; point into command table mov cm.rpl(r5), rplptr ; set reply pointer cmp #ac.pas, cm.act(r5) ; let him in? bne 1200$ ; no - br inc pass ; remember to let him in inc nodmp ; don't dump passwords! mov cm.id(r5), log1 ; point to user-id for later logging clr tt.foo(r4) ; zero invalid count clr tt.tot(r4) ; and total invalid mov cm.id(r5), tt.uid(r4) ; remember user id br 2000$ ; join commmon code 1200$: ; ; here, tt not now in mumble-mode, but invalid reply ; count invalid attempts, and kick into mumble mode ; if try limit exceeded ; inc tt.foo(r4) ; increment foo-count cmp tt.foo(r4), #maxfoo ; over the limit? blo 2000$ ; no - br .globl mblon call mblon ; start mumble-mode ; go issue 'illegal command' message br 2010$ 2000$: ; if verbose mode set, and nodump clear, un-encrypt ; the text, and dump it in an 'illegal command' message bit #gf.vrb, flags ; verbose mode? beq 2040$ ; no - br 2010$: tst nodmp ; dump suppressed for this command? bne 2040$ ; yes - br ; ; since we carefully encrypted the input, we must reverse ; the process now in order to dump the plain text out. ; push ; save a reg add #g.ccbf, r0 ; point to command text mov r0, log1 ; save pointer for logging .globl crypt call crypt ; un-encrypt the command text add r1, r0 ; point past end clrb (r0) ; make asciz pop ; restore cmdbuf pointer dolog 10., ; log the illegal attempt 2040$: ; issue the reply, set to mcr (if pass), then loop tst rplptr ; check for null reply bne 2050$ ; not null - br mov #rpl0, rplptr ; set 'random' reply 2050$: call type,r5, ; type out message at rplptr .if df bkdoor tst pound ; back-door open? bne 2100$ ; yes, go thru .endc tst pass ; set to MCR? beq 3000$ ; no - br 2100$: ; set cli to MCR via SCLI directive dolog 1, ; log the 'login' bic #fl.pro, tt.flg(r4) ; set not protected mov #scli, r4 ; point to dpb mov g.ccdv(r0), s.cidv(r4) ; stuff device name movb g.ccun(r0), s.ciun(r4) ; and unit number clrb s.ciun+1(r4) ; make sure hi byte zero dir$ #scli ; switch cli's bcc 3000$ ; ok - br jmp ferr1 ; fatal error 3000$: jmp start ferr1: mov #1, r0 mov $dsw, r1 br ferr ferr: iot ; crash and burn .end INIT