TITLE IDENTD - TCP port user identification server SEARCH MONSYM,MACSYM ;;; IDENTD server for TOPS-20 (using the IDENT protocol of RFC ????), written ;;; by Anders Andersson (Anders.Andersson@DoCS.UU.SE), Update Computer Club. ;;; This code is put into the public domain. Do whatever you like with it. ;;; I can't provide any support, but you are welcome to tell me your opinions ;;; about it. ;;; ;;; This code makes use of the unsupported STAT% and MONRD% system calls (as ;;; does SYSDPY) to obtain information about TCP ports. The MONRD% call needs ;;; to be installed in the monitor beforehand, by having "SYSDPY E" run with ;;; WHEEL capability at system startup if by no other means. ;;; ;;; This server operates on a single local interface only. By default, ;;; interface #0 is used. In order to use a different interface, deposit its ;;; number in location INTNUM before starting the server. ;;; ;;; This server is single-threaded, meaning that it may easily be blocked by ;;; a slow, broken, or plain evil client that fails to provide input. This is ;;; the next thing that needs to be fixed (perhaps NETSRV can help)... ;;; This code was last hacked May 31, 1992. ;;; 36 >> 32! VERMAJ= 1 VERMIN= 0 VEREDT= ^D31 VERWHO= 2 IDPORT= ^D113 ;according to RFC 931, ???? ECODE= 6 ;error code TCBCNT= 7 ;TCB counter LPORT= 11 ;number of local port FPORT= 12 ;number of foreign port LHOST= 13 ;address of local host FHOST= 14 ;address of foreign host TCB: BLOCK ;storage for retrieved TCB info NAMBUF: BLOCK <^D50/5+1> ;buffer for TCP: file name string HLABUF: BLOCK ;local host address buffer LINBUF: BLOCK </5+1> ;command line buffer ATMBUF: BLOCK </5+1> ;command atom buffer ANSWER: BLOCK <^D80/5+1> ;buffer for answer text CSB: EXP ;no indirect files, no reparse possible EXP <0,,.NULIO> ;we don't want any output from COMND% EXP <-1,,[ASCIZ //]> ;null prompt BLOCK 1 BLOCK 1 BLOCK 1 BLOCK 1 BLOCK 1 BLOCK 1 EXP <0> ;no GTJFN% block needed TCPJFN: BLOCK 1 ;IDENT client file handle ANSPTR: BLOCK 1 ;pointer into answer buffer USERNO: BLOCK 1 ;number of user owning job INTNUM: EXP <0> ;interface# (change this as appropriate) EVEC: JRST START JRST REENT BYTE (3)VERWHO(9)VERMAJ(6)VERMIN(18)VEREDT ERRTXT: EXP [ASCIZ /INVALID-PORT/] EXP [ASCIZ /NO-USER/] EXP [ASCIZ /UNKNOWN-ERROR/] ERRIP= 1 ERRNU= 2 ERRUE= 3 START: RESET% REENT: MOVEI 1,.GTHLA MOVEI 3,HLABUF MOVEI 4,HLASIZ GTHST% ;obtain all local addresses ERJMP FATAL MOVE 1,INTNUM ;this is the selected interface # CAIL 1,0 ;negative interface #? CAML 1,4 ;within the range of existing interfaces? JRST NONINT ;the specified interface does not exist MOVE LHOST,HLABUF(1) ;pick the corresponding local address HRROI 1,NAMBUF ;create a file name string for GTJFN% HRROI 2,[ASCIZ /TCP:/] MOVEI 3,0 SOUT% ERJMP FATAL MOVE 2,LHOST MOVE 3,[NO%MAG!NO%LFL!NO%ZRO!FLD(^D11,NO%COL)!FLD(^D8,NO%RDX)] NOUT% ERJMP FATAL MOVEI 2,"-" IDPB 2,1 MOVEI 2,IDPORT MOVEI 3,^D10 NOUT% ERJMP FATAL MOVEI 2,"V"-"@" ;insert a ^V IDPB 2,1 ;we want this source file to be mailable HRROI 2,[ASCIZ /#..0;CONNECTION:PASSIVE/] MOVEI 3,0 SOUT% ERJMP FATAL LISTEN: SETZB LPORT,FPORT ;destroy possible garbage HRROI 1,LINBUF ;set up CSB pointers and counters MOVEM 1,CSB+.CMBFP MOVEM 1,CSB+.CMPTR MOVEI 1,LINSIZ MOVEM 1,CSB+.CMCNT MOVEM 1,CSB+.CMINC HRROI 1,ATMBUF MOVEM 1,CSB+.CMABP MOVEI 1,ATMSIZ MOVEM 1,CSB+.CMABC MOVE 1,[GJ%SHT!GJ%OLD!0] ;establish a server port... HRROI 2,NAMBUF GTJFN% ERJMP FATAL MOVE 2,[FLD(^D8,OF%BSZ)!FLD(.TCMWI,OF%MOD)!OF%RD!OF%WR] OPENF% ;wait for a client to connect... ERJMP FATAL MOVEM 1,TCPJFN HRLM 1,CSB+.CMIOJ ;input JFN GDSTS% ;get info about the client ERJMP FATAL MOVEM 3,FHOST ;save client host MOVEI ECODE,ERRIP ;default error message: invalid port MOVEI 1,CSB MOVEI 2,[FLDDB.(.CMINI)] COMND% ERJMP CFATAL TLNE 1,(CM%NOP) JRST MREPLY MOVEI 2,[FLDDB.(.CMNUM,CM%SDH,^D10)] COMND% ;parse local port number ERJMP CFATAL TLNE 1,(CM%NOP) JRST MREPLY MOVE LPORT,2 MOVEI 2,[FLDDB.(.CMCMA,CM%SDH)] COMND% ;parse a comma ERJMP CFATAL TLNE 1,(CM%NOP) JRST MREPLY MOVEI 2,[FLDDB.(.CMNUM,CM%SDH,^D10)] COMND% ;parse foreign port number ERJMP CFATAL TLNE 1,(CM%NOP) JRST MREPLY MOVE FPORT,2 MOVEI 2,[FLDDB.(.CMCFM,CM%SDH)] COMND% ;parse CRLF ERJMP CFATAL TLNE 1,(CM%NOP) JRST MREPLY TDNN LPORT,[^-177777] TDNE FPORT,[^-177777] JRST MREPLY ;check that port numbers are within range MOVEI ECODE,0 ;no error so far MREPLY: HRROI 1,ANSWER ;put some port numbers back in reply MOVEI 3,^D10 MOVE 2,LPORT NOUT% ERJMP FATAL MOVEI 2,"," IDPB 2,1 MOVE 2,FPORT NOUT% ERJMP FATAL MOVEM 1,ANSPTR CAIE ECODE,0 ;was there an error? JRST EREPLY ;then make this an error reply HRLZI 1,(TCP%NI) STAT% ;get number of TCBs ERJMP FATAL MOVE TCBCNT,2 TCLOOP: HRLI 1,(TCP%IX) HRR 1,TCBCNT MOVSI 2,-200 MOVE 3,[-200,,TCB] STAT% ;retrieve current TCB ERJMP FATAL CAMN FHOST,TCB+7 ;the wanted foreign host? CAME LHOST,TCB+10 ;the wanted local host also? JRST TCNEXT ;no, ignore this one CAMN FPORT,TCB+11 ;the requested foreign port? CAME LPORT,TCB+12 ;the requested local port also? JRST TCNEXT ;no, ignore this one MOVEI 1,16 HLRZ 2,TCB+6 ;get monitor local job number MONRD% ;convert to cluster (?) global job number ERJMP FATAL MOVE 1,2 ;find out user of job MOVE 2,[-1,,USERNO] MOVEI 3,.JIUNO GETJI% ERJMP FATAL MOVE 1,ANSPTR HRROI 2,[ASCIZ /:USERID:TOPS20:/] MOVEI 3,0 SOUT% ERJMP FATAL MOVE 2,USERNO ;translate to user name string DIRST% ERJMP FATAL JRST TCPUSH ;go tell all to the client (ptr in AC1) NONINT: HRROI 1,[ASCIZ /IP interface /] ESOUT% MOVEI 1,.PRIOU MOVE 2,INTNUM MOVEI 3,^D8 NOUT% ERJMP FATAL HRROI 1,[ASCIZ / does not exist -- change INTNUM and continue /] PSOUT% HALTF% JRST START TCNEXT: AOBJN TCBCNT,TCLOOP MOVEI ECODE,ERRNU ;no matching ports in use found EREPLY: MOVE 1,ANSPTR HRROI 2,[ASCIZ /:ERROR:/] MOVEI 3,0 SOUT% ERJMP FATAL HRRO 2,ERRTXT-1(ECODE) MOVEI 3,0 SOUT% ERJMP FATAL TCPUSH: MOVEI 2,"M"-"@" ;be sure buf ptr is in AC1 here IDPB 2,1 MOVEI 2,"J"-"@" IDPB 2,1 MOVEI 3,0 ;terminate string with a NUL byte IDPB 3,1 MOVE 1,TCPJFN SETZM TCPJFN ;don't tell client about errors after this HRROI 2,ANSWER SOUT% ERJMP FATAL MOVEI 2,.TCPSH ;this is our last word TCOPR% ERJMP FATAL CLOSF% ERJMP FATAL JRST LISTEN ;go wait for our next client CFATAL: MOVEI 1,.FHSLF ;COMND% had an error, check what it is GETER% HRRZ 2,2 CAIE 2,COMNX2 ;field too long? CAIN 2,COMNX3 ;command too long? JRST MREPLY ;client's fault, go tell him CAIN 2,COMNX9 ;end of input? JRST MREPLY ;also client's fault ; JRST FATAL ;else fall through and tell us FATAL: HRROI 1,[ASCIZ /JSYS error - /] ESOUT% MOVEI 1,.PRIOU HRLOI 2,.FHSLF MOVEI 3,0 ERSTR% NOP ;never mind NOP ;fat chance HRROI 2,[ASCIZ / /] PSOUT% MOVEI ECODE,ERRUE ;this is not a normal error SKIPE TCPJFN ;do we have a connection? JRST EREPLY ;then try to finish it and continue HALTF% ;else die... JRST .-1 ;...and stay there END <3,,EVEC>