mirror of
https://github.com/PDP-10/rsh.git
synced 2026-01-12 00:02:45 +00:00
Files from ftp.ultimate.com: /pdp10/bucs20-anon/rsh.
This commit is contained in:
commit
eb120e076e
343
rsh.mid
Normal file
343
rsh.mid
Normal file
@ -0,0 +1,343 @@
|
||||
Title RSH - Speak Un*x rshell protocol
|
||||
.DecSave
|
||||
|
||||
DBG==0
|
||||
Ifndef TCPX31,TCPX31=603436 ;Connection error or connection rejected
|
||||
Ifndef TCPX19,TCPX19=603422 ;TCP connection allready exists
|
||||
|
||||
Define Error &s
|
||||
Jrst [ Hrroi 1,[Asciz s]
|
||||
Jrst .Error ]
|
||||
Termin
|
||||
|
||||
Define JError &s
|
||||
Jrst [ Hrroi 1,[Asciz s]
|
||||
Jrst .Jerror ]
|
||||
Termin
|
||||
|
||||
Define EJError &s
|
||||
Erjmp [ Hrroi 1,[Asciz s]
|
||||
Jrst .Jerror ]
|
||||
Termin
|
||||
|
||||
x==10 ;Loop var
|
||||
bp==11 ;BP in to InBuf
|
||||
up==12 ;BP to 4n user
|
||||
cp==13 ;BP to command text
|
||||
|
||||
p==17
|
||||
|
||||
Stack: Block <Stklen==20>
|
||||
String: Block <Strlen==20>
|
||||
Me: Block Strlen ;local user (lower case)
|
||||
InBuf: Block Strlen ;RSCAN JCL
|
||||
Host: Block 1 ;4n host number
|
||||
Jfn: Block 1 ;Net JFN
|
||||
Prompt: Block 1 ;BP to prompt in GStr
|
||||
|
||||
Chntab: 1,,TTYINT
|
||||
Block 34.
|
||||
|
||||
Levtab: PC1 ? PC2 ? PC3
|
||||
PC1: Block 1
|
||||
PC2: Block 1
|
||||
PC3: Block 1
|
||||
|
||||
Crlf: .BYTE 7 ? ^m ? ^j ? .BYTE
|
||||
|
||||
S: Jfcl
|
||||
RESET
|
||||
|
||||
Movei 1,.FHSLF
|
||||
Seto 3,
|
||||
EPCAP
|
||||
|
||||
Move p,[-StkLen,,Stack-1]
|
||||
|
||||
Movei 1,.RSINI
|
||||
RSCAN
|
||||
JError 'RSCAN failed'
|
||||
|
||||
Jumpe 1,.Usage
|
||||
Movn 3,1
|
||||
Movei 1,.PRIIN
|
||||
Hrroi 2,InBuf
|
||||
SIN
|
||||
Erjmp .Usage
|
||||
|
||||
Move bp,[440700,,InBuf]
|
||||
Call SkipNs
|
||||
.Usage: Error 'Usage: rsh host [-u 4nuser] command'
|
||||
|
||||
Call SkipSp
|
||||
Jrst .Usage
|
||||
|
||||
IFN DBG,[
|
||||
Move 1,bp
|
||||
PSOUT
|
||||
Movei 1,"/
|
||||
PBOUT
|
||||
] ;DBG
|
||||
|
||||
Movei 1,.GTHSN ; translate name to number
|
||||
Move 2,bp
|
||||
GTHST%
|
||||
Erjmp [Hrroi 1,[Asciz 'Bad Host']
|
||||
Jrst .Jerror ]
|
||||
Move bp,2
|
||||
Movem 3,Host
|
||||
|
||||
Call SkipSp
|
||||
Jrst .Usage
|
||||
|
||||
Call GetMe
|
||||
Move cp,bp ;Save bp (might be command)
|
||||
Hrroi up,Me ;Make 4n user be me
|
||||
Ildb 1,bp ;Get next char
|
||||
Jumpe 1,.Usage
|
||||
Caie 1,"- ;'-'?
|
||||
Jrst go4it
|
||||
Ildb 1,bp
|
||||
Jumpe 1,.Usage
|
||||
Caie 1,"u
|
||||
Cain 1,"U
|
||||
Trna
|
||||
Error 'Bad flag'
|
||||
Call SkipSp
|
||||
Error 'No user'
|
||||
Move up,bp ;Save user pointer
|
||||
Call SkipNs ;Skip non-spaces
|
||||
Error 'No command'
|
||||
Setz 1,
|
||||
Idpb 1,bp ;Tie off user
|
||||
Move cp,bp
|
||||
|
||||
go4it: Call DoOpen
|
||||
|
||||
IFN DBG,[
|
||||
Move 1,up
|
||||
PSOUT
|
||||
Movei 1,"/
|
||||
PBOUT
|
||||
Move 1,cp
|
||||
PSOUT
|
||||
Hrroi 1,CrLf
|
||||
PSOUT
|
||||
] ;DBG
|
||||
|
||||
Call DoSend
|
||||
HALTF
|
||||
Jrst .-1
|
||||
|
||||
GetMe: GJINF
|
||||
Move 2,1 ;Get user number
|
||||
Hrroi 1,Me
|
||||
DIRST ;Stringify
|
||||
Trn
|
||||
Move 1,[440700,,Me]
|
||||
LcLop: Ildb 2,1 ;Make lc
|
||||
Jumpe 2,R
|
||||
Cail 2,"A
|
||||
Caile 2,"Z
|
||||
Jrst LcLop
|
||||
Addi 2,"a-"A
|
||||
Dpb 2,1
|
||||
Jrst LcLop
|
||||
R: Ret
|
||||
|
||||
DoOpen: Movei x,1023. ;higest prived port
|
||||
Srclop: Hrroi 1,String
|
||||
Hrroi 2,[Asciz /TCP:/]
|
||||
Setz 3,
|
||||
SOUT
|
||||
Movei 2,(x)
|
||||
Movei 3,10.
|
||||
NOUT
|
||||
Jfcl
|
||||
Hrroi 2,[Asciz /#./]
|
||||
Setz 3,
|
||||
SOUT
|
||||
Move 2,Host
|
||||
Movei 3,10
|
||||
NOUT
|
||||
jfcl
|
||||
Hrroi 2,[asciz /-514;PERSIST:30;CONNECT:ACTIVE/]
|
||||
Setz 3,
|
||||
SOUT
|
||||
Idpb 3,2
|
||||
|
||||
Movsi 1,(GJ%SHT\GJ%ACC)
|
||||
Hrroi 2,String
|
||||
GTJFN
|
||||
JError 'Could not get jfn'
|
||||
Movem 1,Jfn
|
||||
|
||||
Move 2,[100000,,OF%RD+OF%WR] ;8 bit bytes
|
||||
tryopn: OPENF
|
||||
Skipa 3,1 ;Save error code
|
||||
Jrst Won
|
||||
Move 1,Jfn
|
||||
RLJFN
|
||||
trn
|
||||
Caie 3,TCPX19 ;Usual error?
|
||||
Cain 3,TCPX31 ; or this one?
|
||||
Sojg x,Srclop ; Yes, search..
|
||||
JError 'Could not open' ;out of luck
|
||||
Won: Ret
|
||||
|
||||
DoSend: Hrroi 2,[Asciz '0'] ;Stderr port number
|
||||
Call SndStr
|
||||
|
||||
Move 2,up ;Send 4n user
|
||||
Call Sndstr
|
||||
|
||||
Hrroi 2,Me ;Send local user
|
||||
Call Sndstr
|
||||
|
||||
Move 2,cp ;Send command
|
||||
Call Sndstr
|
||||
Call Flush
|
||||
|
||||
GetSts: Move 1,Jfn
|
||||
BIN
|
||||
EJerror 'Could not get status byte'
|
||||
Jumpe 2,PiIni ;AOK, start input PIs
|
||||
Hrroi 1,[Asciz '4n Error: ']
|
||||
ESOUT
|
||||
Jrst OK
|
||||
|
||||
PiIni: Hrroi 1, [Asciz 'Open...
|
||||
'] ? PSOUT
|
||||
|
||||
Movei 1,.FHSLF
|
||||
Move 2,[Levtab,,Chntab]
|
||||
SIR
|
||||
EIR
|
||||
|
||||
Movsi 2,(Setz) ;Channel 0
|
||||
AIC
|
||||
|
||||
Movsi 1,.TICTI ;input, channel 0
|
||||
ATI
|
||||
|
||||
Movei 1,.PRIOU
|
||||
RFMOD
|
||||
Tlz 2,TT%DAM
|
||||
SFMOD
|
||||
|
||||
OK: Move 1,Jfn
|
||||
BIN
|
||||
Erjmp Done
|
||||
Movei 1,.PRIOU
|
||||
BOUT
|
||||
Jrst OK
|
||||
|
||||
Done: Move 1,Jfn
|
||||
CLOSF
|
||||
Jerror 'Close failed'
|
||||
HALTF
|
||||
Jrst .-1
|
||||
|
||||
TTYINT: Push P,1
|
||||
Push P,2
|
||||
Push P,3
|
||||
TTYLOP: Movei 1,.PRIIN
|
||||
SIBE
|
||||
Trna
|
||||
Jrst TTYEND
|
||||
BIN
|
||||
Erjmp TTYEND
|
||||
Cain 2,^M
|
||||
Jrst TTYLOP
|
||||
Cain 2,^Z
|
||||
Jrst ContZ
|
||||
Move 1, JFN
|
||||
BOUT
|
||||
Erjmp TTYLOP
|
||||
Jrst TTYLOP
|
||||
TTYEND: Call Flush
|
||||
Pop P,3
|
||||
Pop P,2
|
||||
Pop P,1
|
||||
DEBRK
|
||||
|
||||
ContZ: Move 1,JFN
|
||||
CLOSF
|
||||
trn
|
||||
HRROI 1,[ASCIZ '
|
||||
EOF']
|
||||
PSOUT
|
||||
HALTF
|
||||
Jrst .-1
|
||||
|
||||
Flush: Move 1,Jfn
|
||||
Hrroi 2,[0]
|
||||
Setz 3,
|
||||
SOUTR
|
||||
EJError 'Flush failed'
|
||||
Ret
|
||||
|
||||
; Send string + nul
|
||||
; 2/ bp
|
||||
Sndstr: Move 1,Jfn
|
||||
Setz 3,
|
||||
SOUT
|
||||
EJError 'Sndstr failed'
|
||||
Setz 2,
|
||||
BOUT
|
||||
EJError 'Sndstr failed(2)'
|
||||
Ret
|
||||
|
||||
IOerr: Jerror 'I/O error'
|
||||
|
||||
; 1/ bp to prompt
|
||||
Gstr: Movem 1,Prompt
|
||||
Gstr2: Move 3,Prompt
|
||||
Move 1,3
|
||||
PSOUT
|
||||
Hrroi 1, String
|
||||
Move 2, [<Strlen*5-1>\RD%CRF]
|
||||
RDTTY
|
||||
ErJmp gstr2
|
||||
Setz 2,
|
||||
Dpb 2,1
|
||||
Ret
|
||||
|
||||
.Jerror:
|
||||
ESOUT
|
||||
Hrroi 1,[Asciz ': ']
|
||||
PSOUT
|
||||
Movei 1,.PRIOU
|
||||
Hrloi 2,.FHSLF
|
||||
Setz 3,
|
||||
ERSTR
|
||||
Skipa
|
||||
Jfcl
|
||||
HALTF
|
||||
Jrst .-1
|
||||
|
||||
.Error: ESOUT
|
||||
HALTF
|
||||
Jrst .-1
|
||||
|
||||
Skips0: Skipa bp,2
|
||||
SkipSp: Move 2,bp
|
||||
Ildb 1,2
|
||||
Jumpe 1,R
|
||||
Caie 1," ;Space?
|
||||
Cain 1,^I ; or Tab?
|
||||
Jrst SkipS0
|
||||
Rskp: Aos (p)
|
||||
Ret
|
||||
|
||||
SkipN0: Skipa bp,2
|
||||
SkipNs: Move 2,bp
|
||||
Ildb 1,2
|
||||
Jumpe 1,R
|
||||
Caie 1," ;Space?
|
||||
Cain 1,^I ; or Tab?
|
||||
AosA (p)
|
||||
Jrst SkipN0
|
||||
Ret
|
||||
|
||||
End S
|
||||
150
rshd.148
Normal file
150
rshd.148
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* RSHD.C -- Phil Budne @ BostonU / Distributed Systems
|
||||
* BSD Un*x style remote shell daemon for Twenex
|
||||
*
|
||||
* (c) 1986 Boston University.
|
||||
* Permission granted to copy for non-profit use.
|
||||
*
|
||||
* Written using UTAH PCC-20. Link with RSHLIB.
|
||||
*
|
||||
* Scenario:
|
||||
* Wait for connection, then spawn a new job loaded with RSHSRV,
|
||||
* NLI with the CJ%LWP (BU -- login without password).
|
||||
*/
|
||||
|
||||
# include "pcc:stdio.h"
|
||||
# include "pcc:tops20.h"
|
||||
# include "pcc:mon_files.h"
|
||||
# include "pcc:mon_fork.h"
|
||||
# include "mon_crjob.h"
|
||||
|
||||
main() {
|
||||
int jfn;
|
||||
|
||||
epcap(FHslf,-1); /* wheel up */
|
||||
|
||||
for( ; ; ) {
|
||||
jfn = srvjfn(); /* wait for connect */
|
||||
if( jfn < 0 ) {
|
||||
perror("could not get jfn");
|
||||
exit(1);
|
||||
} /* could not open server */
|
||||
worker(jfn);
|
||||
} /* forever */
|
||||
} /* main */
|
||||
|
||||
worker(jfn)
|
||||
int jfn;
|
||||
{
|
||||
char foreign[30];
|
||||
int host, sock;
|
||||
|
||||
if( (sock = get_fsock(jfn)) > 1023 || (host = get_fhost(jfn)) < 0 ||
|
||||
hostname(foreign, host) < 0 )
|
||||
return( punt(jfn,"Permission denied.") );
|
||||
|
||||
printf("RSHD: contact from %s, port %d\n", foreign, sock);
|
||||
if( makjob(jfn, "SYSTEM:RSHSRV.EXE") < 0 )
|
||||
printf("could not create job");
|
||||
|
||||
} /* worker */
|
||||
|
||||
/*
|
||||
* jfn jfn of TCP: connection
|
||||
* prog name of .EXE file or NULL
|
||||
*/
|
||||
|
||||
int makjob(jfn, prog)
|
||||
char *prog;
|
||||
int jfn;
|
||||
{
|
||||
int tvt, job;
|
||||
int crjblk[015], acs[5];
|
||||
register int i;
|
||||
|
||||
for( i = 0; i < sizeof( crjblk ); i++ )
|
||||
crjblk[i] = 0;
|
||||
|
||||
/* wait 'till attached, load file, give my caps, login w/o password */
|
||||
ac1 = Value(CJ_wta) | Value(CJ_fil) | Value(CJ_cap) | Value(CJ_lwp);
|
||||
ac2 = (int) crjblk;
|
||||
|
||||
crjblk[CJfil] = POINT(prog); /* BP to program to load */
|
||||
crjblk[CJtty] = NUlio; /* new job is detached */
|
||||
|
||||
if( JSYS(JScrjob,acs) == JSerr )
|
||||
return( punt(jfn, "Could not create job") );
|
||||
job = ac1; /* save job number */
|
||||
|
||||
tvt = maktvt(jfn); /* convert jfn to tvt */
|
||||
if( tvt < 0 ) {
|
||||
logout(job); /* could not create TVT, kill job */
|
||||
return( punt(jfn, "Could not create net virtual terminal") );
|
||||
} /* maktvt failed */
|
||||
|
||||
ac1 = job | (0100000 << 18); /* AT%TRM */
|
||||
ac2 = 0;
|
||||
ac3 = 0;
|
||||
ac4 = tvt;
|
||||
if( JSYS(JSatach,acs) == JSerr ) { /* attach job to terminal */
|
||||
ac1 = job; /* failed!! */
|
||||
JSYS(JSlgout,acs); /* blast job */
|
||||
return( -1 ); /* no way to send error text!! */
|
||||
} /* atach failed */
|
||||
return( job );
|
||||
} /* makjob */
|
||||
|
||||
int maktvt(jfn)
|
||||
int jfn;
|
||||
{
|
||||
int nvtdes, acs[5];
|
||||
|
||||
acs[1] = jfn;
|
||||
if( JSYS(JSatnvt,acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
nvtdes = acs[1];
|
||||
if( JSYS(JSrfmod,acs) == JSerr )
|
||||
return( nvtdes );
|
||||
acs[2] |= 040000<<18; /* set TT%LCA */
|
||||
JSYS(JSstpar,acs);
|
||||
|
||||
acs[1] = nvtdes;
|
||||
acs[2] = 031; /* .MOSLW - set width */
|
||||
acs[3] = 0; /* to zero */
|
||||
JSYS(JSmtopr,acs);
|
||||
return( nvtdes );
|
||||
}
|
||||
|
||||
int get_fsocket(jfn)
|
||||
int jfn;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = jfn;
|
||||
if( JSYS(JSgdsts,acs) == JSerr )
|
||||
return( 0377777777777 ); /* +INF as local socket */
|
||||
else
|
||||
return( ac4 );
|
||||
} /* get_fsocket */
|
||||
|
||||
int get_fhost(jfn)
|
||||
int jfn;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = jfn;
|
||||
if( JSYS(JSgdsts,acs) == JSerr )
|
||||
return( -1 );
|
||||
else
|
||||
return( ac3 );
|
||||
} /* get_fhost */
|
||||
|
||||
int srvjfn() {
|
||||
return( trytcp( "TCP:514\026#;CONNECT:PASSIVE" ) );
|
||||
} /* srvjfn */
|
||||
|
||||
|
||||
/** Local Modes: * */
|
||||
/** Comment Column:40 * */
|
||||
/** End: * */
|
||||
222
rshd.c
Normal file
222
rshd.c
Normal file
@ -0,0 +1,222 @@
|
||||
/* pty version */
|
||||
|
||||
/*
|
||||
* RSHD.C -- Phil Budne @ BostonU / Distributed Systems
|
||||
* BSD Un*x style remote shell daemon for Twenex
|
||||
*
|
||||
* (c) 1986 Boston University.
|
||||
* Permission granted to copy for non-profit use.
|
||||
*
|
||||
* Written using UTAH PCC-20. Link with RSHLIB.
|
||||
*
|
||||
* Scenario:
|
||||
* Wait for connection, then spawn a new job loaded with RSHSRV,
|
||||
* NLI with the CJ%LWP (BU -- login without password).
|
||||
*/
|
||||
|
||||
# include "pcc:stdio.h"
|
||||
# include "pcc:tops20.h"
|
||||
# include "pcc:mon_files.h"
|
||||
# include "pcc:mon_fork.h"
|
||||
# include "mon_crjob.h"
|
||||
|
||||
main() {
|
||||
int jfn;
|
||||
|
||||
epcap(FHslf,-1); /* wheel up */
|
||||
|
||||
for( ; ; ) {
|
||||
jfn = srvjfn(); /* wait for connect */
|
||||
if( jfn < 0 ) {
|
||||
perror("could not get jfn");
|
||||
exit(1);
|
||||
} /* could not open server */
|
||||
worker(jfn);
|
||||
} /* forever */
|
||||
} /* main */
|
||||
|
||||
worker(jfn)
|
||||
int jfn;
|
||||
{
|
||||
char foreign[30], fhnstr[20];
|
||||
int host, sock, pty;
|
||||
|
||||
if( (sock = get_fsock(jfn)) > 1023 || (host = get_fhost(jfn)) < 0 ||
|
||||
hostname(foreign, host) < 0 )
|
||||
return( punt(jfn,"Permission denied.") );
|
||||
|
||||
printf("RSHD: contact from %s, port %d\n", foreign, sock);
|
||||
/***** SHOULD FORK HERE *****/
|
||||
if( (pty = makjob(jfn, "USR0:<BUDD>RSHSRV.EXE")) < 0 )
|
||||
perror("RSHD: could not create job");
|
||||
|
||||
fhnstr[0] = 0;
|
||||
sprintf(fhnstr, "%d", host);
|
||||
printf("fhnstr: %s\n", fhnstr);
|
||||
|
||||
{
|
||||
register char *cp;
|
||||
cp = fhnstr;
|
||||
do {
|
||||
ac1 = pty;
|
||||
ac2 = *cp;
|
||||
if( *cp == '\0' ) break;
|
||||
JSYS(JSbout, acs);
|
||||
/* printf("putting %c (%d)\n", *cp, *cp ); /**/
|
||||
} while( *cp++ != '\0' );
|
||||
jflush(jfn);
|
||||
}
|
||||
|
||||
if( fork() > 0 ) { /* parent */
|
||||
for( ; ; ) {
|
||||
int i, acs[5];
|
||||
ac1 = pty; /* get from pty to net */
|
||||
if( JSYS(JSbin, acs) == JSerr )
|
||||
return;
|
||||
i = ac2;
|
||||
ac1 = jfn;
|
||||
if( JSYS(JSbout, acs) == JSerr )
|
||||
return;
|
||||
jflush(jfn);
|
||||
/* printf("pty -> net: %o (%c)\n", i, i); /**/
|
||||
} /* forever parent */
|
||||
} /* parent */
|
||||
else {
|
||||
for( ; ; ) {
|
||||
ac1 = jfn;
|
||||
if( JSYS(JSbin, acs) == JSerr )
|
||||
return;
|
||||
/* printf("net -> pty: %o (%c)\n", ac2, ac2); /**/
|
||||
ac1 = pty;
|
||||
if( JSYS(JSbout, acs) == JSerr )
|
||||
return;
|
||||
} /* forever parent */
|
||||
} /* child */
|
||||
} /* worker */
|
||||
|
||||
/*
|
||||
* jfn jfn of TCP: connection
|
||||
* prog name of .EXE file or NULL
|
||||
*/
|
||||
|
||||
int makjob(jfn, prog)
|
||||
char *prog;
|
||||
int jfn;
|
||||
{
|
||||
int pty, job;
|
||||
int crjblk[015], acs[5];
|
||||
register int i;
|
||||
|
||||
for( i = 0; i < sizeof( crjblk ); i++ )
|
||||
crjblk[i] = 0;
|
||||
|
||||
/* wait 'till attached, load file, give my caps, login w/o password */
|
||||
ac1 = Value(CJ_wta) | Value(CJ_fil) | Value(CJ_cap) | Value(CJ_lwp);
|
||||
ac2 = (int) crjblk;
|
||||
|
||||
crjblk[CJfil] = POINT(prog); /* BP to program to load */
|
||||
crjblk[CJtty] = NUlio; /* new job is detached */
|
||||
|
||||
if( JSYS(JScrjob,acs) == JSerr )
|
||||
return( punt(jfn, "Could not create job") );
|
||||
job = ac1; /* save job number */
|
||||
|
||||
pty = attpty(jfn, job); /* create pty and attach */
|
||||
if( pty < 0 ) {
|
||||
logout(job); /* could not create pty, kill job */
|
||||
return( punt(jfn, "Could not create pseudo terminal") );
|
||||
} /* attpty failed */
|
||||
return( pty );
|
||||
} /* makjob */
|
||||
|
||||
int attpty(jfn, job)
|
||||
int jfn, job;
|
||||
{
|
||||
int acs[5];
|
||||
int pty, ptyoff, maxpty;
|
||||
register int i;
|
||||
|
||||
ac1 = 026; /* 0,,.PTYPA */
|
||||
if( JSYS(JSgetab, acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
maxpty = (ac1 >> 18) - 1;
|
||||
ptyoff = ac1 & 0777777;
|
||||
|
||||
pty = ac1;
|
||||
for( i = 0; i < maxpty; i++ ) {
|
||||
char fname[100];
|
||||
|
||||
fname[0] = 0;
|
||||
sprintf(fname, "PTY%o:", i);
|
||||
ac1 = Value(GJ_sht);
|
||||
ac2 = POINT(fname);
|
||||
if( JSYS(JSgtjfn,acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
pty = ac1;
|
||||
ac2 = makefield(OF_bsz,8) | /* makefield(OF_mod, 010) | */
|
||||
Value(OF_rd) | Value(OF_wr); /* 8bit, image mode, read/write */
|
||||
if( JSYS(JSopenf, acs) != JSerr )
|
||||
break;
|
||||
|
||||
reljfn(pty);
|
||||
pty = -1;
|
||||
} /* for i */
|
||||
|
||||
if( pty < 0 )
|
||||
return( -1 );
|
||||
|
||||
ac1 = job | (0100000 << 18); /* AT%TRM */
|
||||
ac2 = 0;
|
||||
ac3 = 0;
|
||||
ac4 = i + ptyoff; /* terminal on pty */
|
||||
if( JSYS(JSatach,acs) == JSerr ) { /* attach job to terminal */
|
||||
close( pty ); /* toss pty */
|
||||
return( -1 );
|
||||
} /* atach failed */
|
||||
return( pty );
|
||||
}
|
||||
|
||||
int get_fsocket(jfn)
|
||||
int jfn;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = jfn;
|
||||
if( JSYS(JSgdsts,acs) == JSerr )
|
||||
return( 0377777777777 ); /* +INF as local socket */
|
||||
else
|
||||
return( ac4 );
|
||||
} /* get_fsocket */
|
||||
|
||||
int get_fhost(jfn)
|
||||
int jfn;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = jfn;
|
||||
if( JSYS(JSgdsts,acs) == JSerr )
|
||||
return( -1 );
|
||||
else
|
||||
return( ac3 );
|
||||
} /* get_fhost */
|
||||
|
||||
int srvjfn() {
|
||||
return( trytcp( "TCP:514\026#;CONNECT:PASSIVE" ) );
|
||||
} /* srvjfn */
|
||||
|
||||
jflush(jfn)
|
||||
int jfn;
|
||||
{
|
||||
char c[2];
|
||||
c[0] = 0;
|
||||
ac1 = jfn;
|
||||
ac2 = POINT(c);
|
||||
ac3 = 0;
|
||||
JSYS(JSsoutr, acs);
|
||||
}
|
||||
|
||||
/** Local Modes: * */
|
||||
/** Comment Column:40 * */
|
||||
/** End: * */
|
||||
103
rshd.msg
Normal file
103
rshd.msg
Normal file
@ -0,0 +1,103 @@
|
||||
I have tried to implement an RSHD using NVTs also. I ended up with
|
||||
the same technique that MRC suggested, RSHD just listens for a connect
|
||||
and verifies that it comes from a 'secure' port (<1024.) on a host we
|
||||
have a name for, and then CRJOBs a job loaded with "RSHSRV", creates
|
||||
an NVT and ATACHes the two.
|
||||
|
||||
Problem;
|
||||
Since we have not read any data we don't know who to log in as.
|
||||
|
||||
Solution;
|
||||
I added a bit CR%LWP to CRJOB (Login Without Password), this sets a
|
||||
bit in the SYSFK word of the created fork.
|
||||
|
||||
Problem 2;
|
||||
Some huge number of useful things under TOPS-20 are not programs but
|
||||
EXEC commands.. So you hack up your EXEC to read one command from the
|
||||
RSCAN buffer and then quit when entered in a new entry vector
|
||||
position.
|
||||
|
||||
Problem 3;
|
||||
Ok so you have this running, everything looks fine -- but you notice
|
||||
that when a BSD user types "rsh twenex foo", they get output, then you
|
||||
see a logout message, and the connection hangs.
|
||||
|
||||
So, you have RSHSRV detach and LGOUT when the hacked EXEC returns.
|
||||
|
||||
Fix this, you still hang, the job never detaches.
|
||||
|
||||
Well, you see TVTs are expected to talk TELNET protocol. DTACH does a
|
||||
DOBE, which sends a TELNET mark-time command, to which RSHD does not
|
||||
know how to respond. (You might have noticed that TVT-SMTP jobs hung
|
||||
for the same reason).
|
||||
|
||||
Cure; have DOBE on a TVT be a NOOP.
|
||||
|
||||
Now the job logs out cleanly, but you STILL hang on your UNIX system.
|
||||
This may simply be a misfeature of the BSD RSH program, it doesn't
|
||||
expect anyone to implement RSH for a system that can not 'half close'
|
||||
a connection.
|
||||
|
||||
But wait, just try to write something that transfers large amounts of
|
||||
data, say 'RCP' or 'RMT' BINARY DATA... You will find that TVT thruput
|
||||
is well, awful, and you will lose data espcially anything containing
|
||||
IAC.
|
||||
|
||||
Problem N.1;
|
||||
You want to write an RSH for tops-20 do you? Well RSH is
|
||||
a secure protocol, and depends on the fact that only SuperUser can
|
||||
open a connection with a local port of <1024. Any connection with a
|
||||
remote local port of <1024. is to be trusted, and when the data says
|
||||
the remote user name is "foo" it is to be believed.
|
||||
|
||||
So you can either; leave the monitor the way it came (only ports <512
|
||||
protected), or add a new magic bit in SYSFK. If we have just done an
|
||||
execute only GET% we look at the FDB of the EXE file, if it has a
|
||||
special (priv'ed) bit lit, we light the SYSFK bit, and the fork is
|
||||
ENCHANTED. This bit is checked at the same places (several) that
|
||||
check for WOPR on a TCP open.
|
||||
|
||||
Problem N.2;
|
||||
|
||||
The RSH protocol (and this is used by BSD rsh), specifies that the
|
||||
first data item is a foreign port (or zero) for sending back data from
|
||||
the forks stderr, in fact the rsh will wait for a connect on that port
|
||||
until it proceeds. This connection must originate from a secure port
|
||||
.. so that the RSHSRV must be created with pre-login WOPR, or be
|
||||
enchanted (note since enchanted-ness is not a capability it is never
|
||||
inherited by children).
|
||||
|
||||
TOPS-20 only checks local ports for uniqueness within a job, BSD never
|
||||
creates the same local port twice. For a reason that escapes me (but
|
||||
has to do with the STDERR connection), this causes problems. OK,
|
||||
remove that code too. Whew!! FTP continues to work.
|
||||
|
||||
--
|
||||
Moral, Or how I would try to do it next if I had the strength;
|
||||
|
||||
First and foremost this proves that Un*x software and concepts are
|
||||
completely transportable... between any two Un*x systems :-)
|
||||
|
||||
a) Have RSHD listen for connects, process the data and drop a PTY
|
||||
connect a job logged into whoever we please and just pass the data.
|
||||
Feature; require NO monitor changes. 'Bit nasty to have the process
|
||||
in between handling all the data for all the RSHs.
|
||||
|
||||
b) Create a not logged in job loaded with RSHSRV, CJ%LWP set, and
|
||||
either WOPR or enchanted. Does a passive listen for RSH connects.
|
||||
When a connect is received, either spawn a another like us, or notify
|
||||
an authority via IPCF to do so (DEC DTRSRV (datatrieve) and the new
|
||||
RMSFAL do just this). RSHSRV then reads and validates the data,
|
||||
creates the error pipe if needed, and LOGs in. Get a PTY, and assign
|
||||
it as controlling for an EXEC, and ferry data back and forth between
|
||||
the PTY and the TCP connection. This avoids having on central octopus
|
||||
hacking the PTYs.
|
||||
|
||||
|
||||
Good Guys RSH
|
||||
0 34359738367
|
||||
|
||||
I wrote all my code using the UTAH PCC-20 compiler, you're welcome to it!!
|
||||
|
||||
Philip Budne
|
||||
Boston University / Distributed Systems
|
||||
94
rshlib.c
Normal file
94
rshlib.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* RSHLIB.C -- Phil Budne @ BostonU / Distributed Systems
|
||||
* Common routines for RSHSRV/RSHD
|
||||
*
|
||||
* (c) 1986 Boston University.
|
||||
* Permission granted to copy for non-profit use.
|
||||
*
|
||||
* Written using UTAH PCC-20.
|
||||
*
|
||||
*/
|
||||
|
||||
# include "pcc:stdio.h"
|
||||
# include "pcc:tops20.h"
|
||||
# include "pcc:mon_files.h"
|
||||
# include "pcc:mon_fork.h"
|
||||
# include "mon_crjob.h"
|
||||
# include "mon_networks.h"
|
||||
|
||||
int punt(jfn, s)
|
||||
int jfn;
|
||||
char *s;
|
||||
{
|
||||
write(jfn, "\01", 1); /* pass failure code */
|
||||
write(jfn, s, strlen(s)); /* pass failure string */
|
||||
write(jfn, "\n", 1); /* send newline */
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
reljfn(j)
|
||||
int j;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
acs[1] = j;
|
||||
JSYS(JSrljfn,acs);
|
||||
} /* reljfn */
|
||||
|
||||
|
||||
int trytcp(name)
|
||||
char *name;
|
||||
{
|
||||
int acs[5], jfn;
|
||||
|
||||
ac1 = Value(GJ_sht);
|
||||
ac2 = POINT(name);
|
||||
if( JSYS(JSgtjfn,acs) == JSerr )
|
||||
return( -1 );
|
||||
jfn = ac1; /* save jfn */
|
||||
|
||||
ac2 = 0100400300000; /* 8bit, interactive, rd/wr */
|
||||
if( JSYS(JSopenf,acs) == JSerr ) {
|
||||
reljfn(jfn);
|
||||
return( -1 );
|
||||
} /* openf failed */
|
||||
return( jfn );
|
||||
} /* trytcp */
|
||||
|
||||
epcap(fork,i) /* enable process capabilities */
|
||||
int fork, i;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = fork;
|
||||
ac3 = i; /* enable mask */
|
||||
JSYS(JSepcap,acs); /* perform enable */
|
||||
} /* epcap */
|
||||
|
||||
logout(job)
|
||||
int job;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = job;
|
||||
JSYS(JSlgout,acs); /* blast job */
|
||||
} /* logout */
|
||||
|
||||
int hostname(str, numb) /* convert address to name */
|
||||
char *str;
|
||||
int numb;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = GThns; /* string from address */
|
||||
ac2 = POINT(str); /* bp to string */
|
||||
ac3 = numb; /* address */
|
||||
if( JSYS(JSgthst, acs) == JSerr )
|
||||
return( -1 );
|
||||
else
|
||||
return( 0 );
|
||||
} /* hostname */
|
||||
|
||||
/** Local Modes: * */
|
||||
/** Comment Column:40 * */
|
||||
/** End: * */
|
||||
404
rshsrv.219
Normal file
404
rshsrv.219
Normal file
@ -0,0 +1,404 @@
|
||||
/****************************************************************/
|
||||
/* R S H S R V . C */
|
||||
/* */
|
||||
/* Phil Budne @ Boston U / DSG */
|
||||
/* (c) 1986 Boston University. */
|
||||
/* Permission granted to copy for non-profit use. */
|
||||
/* */
|
||||
/* This program is CRJOB'ed not-logged-in by RSHD. */
|
||||
/* The monitor must include support for a special bit */
|
||||
/* for the CRJOB JSYS so that when CJ%LWP is set the */
|
||||
/* job may log in without a password. */
|
||||
/* */
|
||||
/* After reading and vaidating data we fork */
|
||||
/* SYSTEM:RSHEXEC.EXE, and start it at +2 (Version!!). */
|
||||
/* RSHEXEC is an EXEC which reads one command, then */
|
||||
/* exits it also never prompts or heralds. */
|
||||
/* */
|
||||
/* This program was written using UTAH TOPS-20 PCC */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
# include <stdio.h>
|
||||
# include <signal.h>
|
||||
# include <ctype.h>
|
||||
|
||||
# include "pcc:tops20.h"
|
||||
# include "pcc:mon_files.h"
|
||||
# include "pcc:mon_fork.h"
|
||||
# include "mon_networks.h"
|
||||
# include "mon_crjob.h"
|
||||
|
||||
# define RC_emo 01:35-17
|
||||
# define PRast 2
|
||||
# define RSini 0
|
||||
|
||||
/* # define DEBUG 1 /* define to enable debugging */
|
||||
|
||||
main() {
|
||||
int jfn;
|
||||
|
||||
# ifndef DEBUG
|
||||
if( logged_in() ) {
|
||||
printf("Foo! you are already logged in!!\n");
|
||||
exit(999);
|
||||
} /* already logged in */
|
||||
# endif
|
||||
|
||||
setname("RSHSRV"); /* Set up name so not LOGOUT */
|
||||
|
||||
epcap(FHslf,-1); /* Enable all privs (needs ABS-SOCK) */
|
||||
|
||||
jfn = openttyraw(); /* get raw tty jfn */
|
||||
if( jfn < 0 ) punt(PRiou, "Could not open TTY:");
|
||||
doit(jfn);
|
||||
# ifndef DEBUG
|
||||
keel();
|
||||
# endif
|
||||
} /* main */
|
||||
|
||||
logged_in() {
|
||||
int acs[5];
|
||||
|
||||
JSYS(JSgjinf, acs); /* get job info */
|
||||
if( ac1 == 0 )
|
||||
return( 0 );
|
||||
else
|
||||
return( 1 );
|
||||
|
||||
} /* logged_in */
|
||||
|
||||
keel() {
|
||||
int acs[5];
|
||||
|
||||
JSYS(JSdtach, acs); /* hide embarrassing LOGOUT mess */
|
||||
logout(-1); /* log self out */
|
||||
JSYS(JShaltf, acs); /* halt?! */
|
||||
} /* keel */
|
||||
|
||||
int openttyraw() {
|
||||
int acs[5], jfn;
|
||||
|
||||
ac1 = Value(GJ_sht); /* short form */
|
||||
ac2 = POINT("TTY:"); /* get TTY: */
|
||||
if( JSYS(JSgtjfn, acs) == JSerr ) /* get jfn */
|
||||
return( -1 ); /* sigh! */
|
||||
jfn = ac1; /* save jfn */
|
||||
|
||||
ac2 = makefield(OF_bsz,8) | makefield(OF_mod, 010) |
|
||||
Value(OF_rd) | Value(OF_wr); /* 8bit, image mode, read/write */
|
||||
if( JSYS(JSopenf, acs) == JSerr ) { /* open! */
|
||||
reljfn(jfn); /* failed, release jfn */
|
||||
return( -1 ); /* return failure */
|
||||
} /* openf failed */
|
||||
|
||||
return( jfn ); /* return jfn */
|
||||
} /* openttyraw */
|
||||
|
||||
# define VALJFN jfn /* JFN for validation (0/1) */
|
||||
|
||||
doit(jfn)
|
||||
int jfn;
|
||||
{
|
||||
char buff[10], foreign[30], fnuser[17], lcuser[39], command[200],cmd2[200];
|
||||
int errport, errjfn, acs[5], fhno, fpno, execfork, userno;
|
||||
|
||||
# ifndef DEBUG
|
||||
signal(SIGHUP, keel); /* logout if detached */
|
||||
/* Doesn't work? Check library.. */
|
||||
signal(SIGALRM, keel); /* keel when time runs out */
|
||||
alarm( 5 * 60 ); /* set clock for 5 minutes */
|
||||
|
||||
JSYS(JSgjinf, acs); /* get job info */
|
||||
fhno = tvtstat(ac4, 7); /* get TFH word */
|
||||
if( fhno < 0 )
|
||||
return( punt(jfn, "TFH STAT failed") );
|
||||
|
||||
fpno = tvtstat(ac4, 011); /* get TFP word */
|
||||
if( fpno < 0 )
|
||||
return( punt(jfn, "TFP STAT failed") );
|
||||
|
||||
if( fpno > 1023 )
|
||||
return( punt(jfn, "Foreign port .GT. 1023") );
|
||||
|
||||
# endif
|
||||
|
||||
if( getstr(jfn, buff, 10) )
|
||||
return( punt(jfn, "could not read error socket number") );
|
||||
|
||||
errport = atoi(buff);
|
||||
if( errport > 0 ) {
|
||||
errjfn = getcon(fhno, errport); /* establish error stream */
|
||||
if( errjfn < 0 )
|
||||
return( punt(jfn, "could not open error socket") );
|
||||
} /* wants socket for errors */
|
||||
else errjfn = jfn;
|
||||
|
||||
# ifndef DEBUG
|
||||
if( hostname(foreign, fhno) < 0 )
|
||||
return( punt(VALJFN, "Could not get name for client host") );
|
||||
lowerify(foreign);
|
||||
# endif
|
||||
|
||||
if( getstr(jfn, lcuser, 39) )
|
||||
return( punt(VALJFN, "bad locuser") );
|
||||
|
||||
if( getstr(jfn, fnuser, 17) )
|
||||
return( punt(VALJFN, "bad frnuser") );
|
||||
|
||||
if( getstr(jfn, command, 200) )
|
||||
return( punt(VALJFN, "bad command") );
|
||||
|
||||
ac1 = Value(RC_emo);
|
||||
ac2 = POINT(lcuser);
|
||||
if( JSYS(JSrcusr, acs) == JSerr )
|
||||
return( punt(VALJFN, "local user does not exist") );
|
||||
userno = ac3;
|
||||
|
||||
# ifndef DEBUG
|
||||
if( ruserok(foreign, 0, fnuser, lcuser ) != 0 )
|
||||
return( punt(VALJFN, "Permission denied.") );
|
||||
|
||||
ac1 = userno; /* get user # in ac1 */
|
||||
ac2 = POINT(""); /* null password */
|
||||
ac3 = POINT(""); /* null account */
|
||||
if( JSYS(JSlogin, acs) == JSerr )
|
||||
return( punt(VALJFN, "LOGIN failed") );
|
||||
# endif
|
||||
|
||||
ac1 = CR_cap; /* pass caps */
|
||||
if( JSYS(JScfork, acs) == JSerr ) /* create a fork */
|
||||
return( punt(VALJFN, "Could not create EXEC fork") );
|
||||
execfork = ac1;
|
||||
|
||||
ac1 = Value(GJ_sht) + Value(GJ_old);
|
||||
ac2 = POINT("SYSTEM:RSHEXEC.EXE");
|
||||
if( JSYS(JSgtjfn, acs) == JSerr )
|
||||
return( punt(VALJFN, "Could not find SYSTEM:RSHEXEC.EXE") );
|
||||
|
||||
ac1 = makeword( execfork, getright(ac1) );
|
||||
if( JSYS(JSget, acs) == JSerr )
|
||||
return( punt(VALJFN, "Could not GET EXEC") );
|
||||
|
||||
/* doprarg(execfork); */
|
||||
|
||||
fnstd(cmd2, command); /* convert unix path to '20 form */
|
||||
if( rcstring(cmd2) < 0 ) /* place in rscan buffer */
|
||||
return( punt(VALJFN, "Could not set up command") );
|
||||
|
||||
write(VALJFN, "", 1); /* send null (validated ok) */
|
||||
|
||||
ac1 = execfork;
|
||||
ac2 = 2; /* start at +2 */
|
||||
if( JSYS(JSsfrkv, acs) == JSerr )
|
||||
return( punt2(VALJFN, "Could not start EXEC") );
|
||||
|
||||
ac1 = execfork;
|
||||
if( JSYS(JSwfork, acs) == JSerr )
|
||||
return( punt2(VALJFN, "Could not wait for EXEC") );
|
||||
|
||||
write(errjfn, "", 1);
|
||||
|
||||
if( errjfn != jfn ) /* if we have an error jfn */
|
||||
close(errjfn, Value(CZ_abt)); /* close (and abort) it */
|
||||
} /* doit */
|
||||
|
||||
int tvtstat(tvt, word)
|
||||
int tvt, word;
|
||||
{
|
||||
int acs[5], result;
|
||||
|
||||
ac1 = tvt + Value(TCP_tv); /* get TVT number in A */
|
||||
ac2 = makeword(-1,word); /* get specified word */
|
||||
ac3 = makeword(-1,(int) &result); /* result */
|
||||
if( JSYS(JSstat, acs) == JSerr ) /* read TCP connection 4n host */
|
||||
return( -1 );
|
||||
else
|
||||
return( result );
|
||||
} /* tvtstat */
|
||||
|
||||
|
||||
setname(s)
|
||||
char *s;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = ac2 = makesix(s);
|
||||
JSYS(JSsetsn, acs);
|
||||
} /* setname */
|
||||
|
||||
int makesix(s)
|
||||
register char *s;
|
||||
{
|
||||
register int i, j;
|
||||
register char c;
|
||||
|
||||
j = 0;
|
||||
for( i = 0; i < 6; i++ ) {
|
||||
if( (c = *s++) != NULL ) {
|
||||
if( c < 040 ) c = '?';
|
||||
if( c > '_' ) c = c - 040;
|
||||
j = (j << 6) + c - 040;
|
||||
} /* if got a char */
|
||||
else break;
|
||||
} /* for */
|
||||
|
||||
if( i < 6 ) j = j << (6 - i);
|
||||
} /* makesix */
|
||||
|
||||
int getstr(jfn, buff, len) /* read counted string, or till NUL */
|
||||
char buff[];
|
||||
int jfn;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = jfn;
|
||||
ac2 = POINT(buff);
|
||||
ac3 = len;
|
||||
ac4 = 0;
|
||||
|
||||
if( JSYS(JSsin,acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
if( ac3 == 0 || (len - ac3) == 0 ) /* overflow or read nothing? */
|
||||
return( -1 );
|
||||
else
|
||||
return( 0 );
|
||||
} /* getstr */
|
||||
|
||||
|
||||
/**************** FROM RCMD.C ****************/
|
||||
|
||||
extern char *index();
|
||||
|
||||
ruserok(rhost, superuser, ruser, luser)
|
||||
char *rhost;
|
||||
int superuser;
|
||||
char *ruser, *luser;
|
||||
{
|
||||
FILE *hostf;
|
||||
char ahost[32];
|
||||
int first = 1;
|
||||
|
||||
hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
|
||||
again:
|
||||
if (hostf) {
|
||||
while (fgets(ahost, sizeof (ahost), hostf)) {
|
||||
char *user, *idx;
|
||||
if ( (idx = index(ahost, '\n')) )
|
||||
*idx = 0;
|
||||
user = index(ahost, ' ');
|
||||
if (user)
|
||||
*user++ = 0;
|
||||
if (!strcmp(rhost, ahost) &&
|
||||
!strcmp(ruser, user ? user : luser)) {
|
||||
(void) fclose(hostf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
(void) fclose(hostf);
|
||||
}
|
||||
if (first == 1) {
|
||||
char buf[100]; /* BUDD */
|
||||
sprintf(buf, "ps:<%s>\026.rhosts", luser); /* BUDD */
|
||||
first = 0;
|
||||
hostf = fopen(buf, "r"); /* BUDD */
|
||||
goto again;
|
||||
}
|
||||
return (-1);
|
||||
} /* ruserok */
|
||||
|
||||
int getcon(fhost, fsock)
|
||||
int fhost, fsock;
|
||||
{
|
||||
char buffer[50];
|
||||
int lsock, jfn;
|
||||
|
||||
for( lsock = 1; lsock < 1024; lsock++ ) {
|
||||
sprintf(buffer,"TCP:%d\026#.%o-%d;CONN:ACT", lsock, fhost, fsock );
|
||||
if( (jfn = trytcp(buffer)) > 0 )
|
||||
return( jfn );
|
||||
} /* for */
|
||||
return( -1 );
|
||||
} /* getcon */
|
||||
|
||||
int punt2(jfn, s)
|
||||
int jfn;
|
||||
char *s;
|
||||
{
|
||||
write(jfn, s, strlen(s)); /* pass failure string */
|
||||
return( -1 );
|
||||
} /* punt2 */
|
||||
|
||||
doprarg(fork)
|
||||
int fork;
|
||||
{
|
||||
int scjprb[8], acs[5];
|
||||
register int *sp;
|
||||
|
||||
sp = scjprb;
|
||||
|
||||
*sp++ = 4; /* 0 - 4 words.. */
|
||||
*sp++ = makeword(0414100, 02545); /* 1 - very magic word */
|
||||
*sp++ = 4; /* 2 - word 4 is data */
|
||||
*sp++ = 0; /* 3 - nothing */
|
||||
*sp++ = (1 << 35); /* 4 - suppress exec herald */
|
||||
|
||||
ac1 = makeword(PRast, fork);
|
||||
ac2 = (int) scjprb;
|
||||
ac3 = 6;
|
||||
JSYS(JSprarg, acs);
|
||||
|
||||
} /* doprarg */
|
||||
|
||||
lowerify(s)
|
||||
register char *s;
|
||||
{
|
||||
register char c;
|
||||
|
||||
while( (c = *s) != NULL ) {
|
||||
if( isupper( c ) ) *s = tolower( c );
|
||||
s++;
|
||||
} /* while */
|
||||
} /* lowerify */
|
||||
|
||||
|
||||
rcstring(s) /* place string in RSCAN buffer */
|
||||
register char *s;
|
||||
{
|
||||
char bigbuf[500], lc;
|
||||
register char c, *d;
|
||||
int acs[5];
|
||||
|
||||
d = bigbuf;
|
||||
while( (c = *s++) != NULL ) {
|
||||
lc = c;
|
||||
if( c == '\n' ) { /* convert NL to CRLF */
|
||||
*d++ = '\r';
|
||||
*d++ = '\n';
|
||||
}
|
||||
else if( c != '\r' ) /* discard CR */
|
||||
*d++ = c;
|
||||
} /* while */
|
||||
|
||||
if( lc != '\n' ) { /* if last was not NL, add CRLF */
|
||||
*d++ = '\r';
|
||||
*d++ = '\n';
|
||||
} /* last not NL */
|
||||
|
||||
*d++ = '\0'; /* tie off with NUL */
|
||||
|
||||
ac1 = POINT(bigbuf); /* insert string into RSCAN */
|
||||
if( JSYS(JSrscan, acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
ac1 = RSini; /* make RSCAN available as input */
|
||||
if( JSYS(JSrscan, acs) == JSerr )
|
||||
return( -1 );
|
||||
return( 0 );
|
||||
|
||||
} /* rcstring */
|
||||
|
||||
/** Local Modes: * */
|
||||
/** Comment Column:40 * */
|
||||
/** End: * */
|
||||
419
rshsrv.c
Normal file
419
rshsrv.c
Normal file
@ -0,0 +1,419 @@
|
||||
/* pty version */
|
||||
# define BLEH
|
||||
|
||||
/****************************************************************/
|
||||
/* R S H S R V . C */
|
||||
/* */
|
||||
/* Phil Budne @ Boston U / DSG */
|
||||
/* (c) 1986 Boston University. */
|
||||
/* Permission granted to copy for non-profit use. */
|
||||
/* */
|
||||
/* This program is CRJOB'ed not-logged-in by RSHD. */
|
||||
/* The monitor must include support for a special bit */
|
||||
/* for the CRJOB JSYS so that when CJ%LWP is set the */
|
||||
/* job may log in without a password. */
|
||||
/* */
|
||||
/* After reading and vaidating data we fork */
|
||||
/* SYSTEM:RSHEXEC.EXE, and start it at +2 (Version!!). */
|
||||
/* RSHEXEC is an EXEC which reads one command, then */
|
||||
/* exits it also never prompts or heralds. */
|
||||
/* */
|
||||
/* This program was written using UTAH TOPS-20 PCC */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
# include <stdio.h>
|
||||
# include <signal.h>
|
||||
# include <ctype.h>
|
||||
|
||||
# include "pcc:tops20.h"
|
||||
# include "pcc:mon_files.h"
|
||||
# include "pcc:mon_fork.h"
|
||||
# include "mon_networks.h"
|
||||
# include "mon_crjob.h"
|
||||
|
||||
# define RC_emo 01:35-17
|
||||
# define PRast 2
|
||||
# define RSini 0
|
||||
|
||||
/* # define DEBUG 1 /* define to enable debugging */
|
||||
|
||||
main() {
|
||||
int jfn;
|
||||
|
||||
# ifndef DEBUG
|
||||
if( logged_in() ) {
|
||||
printf("Foo! you are already logged in!!\n");
|
||||
exit(999);
|
||||
} /* already logged in */
|
||||
# endif
|
||||
|
||||
setname("RSHSRV"); /* Set up name so not LOGOUT */
|
||||
|
||||
epcap(FHslf,-1); /* Enable all privs (needs ABS-SOCK) */
|
||||
|
||||
jfn = openttyraw(); /* get raw tty jfn */
|
||||
if( jfn < 0 ) punt(PRiou, "Could not open TTY:");
|
||||
doit(jfn);
|
||||
# ifndef DEBUG
|
||||
keel();
|
||||
# endif
|
||||
} /* main */
|
||||
|
||||
logged_in() {
|
||||
int acs[5];
|
||||
|
||||
JSYS(JSgjinf, acs); /* get job info */
|
||||
if( ac1 == 0 )
|
||||
return( 0 );
|
||||
else
|
||||
return( 1 );
|
||||
|
||||
} /* logged_in */
|
||||
|
||||
keel() {
|
||||
int acs[5];
|
||||
|
||||
JSYS(JSdtach, acs); /* hide embarrassing LOGOUT mess */
|
||||
logout(-1); /* log self out */
|
||||
JSYS(JShaltf, acs); /* halt?! */
|
||||
} /* keel */
|
||||
|
||||
int openttyraw() {
|
||||
int acs[5], jfn;
|
||||
|
||||
ac1 = Value(GJ_sht); /* short form */
|
||||
ac2 = POINT("TTY:"); /* get TTY: */
|
||||
if( JSYS(JSgtjfn, acs) == JSerr ) /* get jfn */
|
||||
return( -1 ); /* sigh! */
|
||||
jfn = ac1; /* save jfn */
|
||||
|
||||
ac2 = makefield(OF_bsz,8) | makefield(OF_mod, 010) |
|
||||
Value(OF_rd) | Value(OF_wr); /* 8bit, image mode, read/write */
|
||||
if( JSYS(JSopenf, acs) == JSerr ) { /* open! */
|
||||
reljfn(jfn); /* failed, release jfn */
|
||||
return( -1 ); /* return failure */
|
||||
} /* openf failed */
|
||||
|
||||
if( JSYS(JSrfmod,acs) != JSerr ) {
|
||||
ac3 &= ~0300; /* clear TT%DAM (image) */
|
||||
JSYS(JSsfmod,acs);
|
||||
}
|
||||
|
||||
return( jfn ); /* return jfn */
|
||||
} /* openttyraw */
|
||||
|
||||
# define VALJFN jfn /* JFN for validation (0/1) */
|
||||
|
||||
doit(jfn)
|
||||
int jfn;
|
||||
{
|
||||
char buff[10], foreign[30], fnuser[17], lcuser[39], command[200],cmd2[200];
|
||||
char fhnstr[20];
|
||||
int errport, errjfn, acs[5], fhno, execfork, userno;
|
||||
|
||||
# ifndef DEBUG
|
||||
signal(SIGHUP, keel); /* logout if detached */
|
||||
/* Doesn't work? Check library.. */
|
||||
/* signal(SIGALRM, keel); /* keel when time runs out */
|
||||
/* alarm( 5 * 60 ); /* set clock for 5 minutes */
|
||||
|
||||
if( getstr(jfn, fhnstr, 20 ) )
|
||||
return( punt(jfn, "could not get 4n host number") );
|
||||
fhno = atoi( fhnstr );
|
||||
# ifdef BLEH
|
||||
printf("fhno: %d\n", fhno);
|
||||
# endif
|
||||
|
||||
if( getstr(jfn, buff, 10) )
|
||||
return( punt(jfn, "could not read error socket number") );
|
||||
|
||||
errport = atoi(buff);
|
||||
# ifdef BLEH
|
||||
printf("errport: %d\n", errport); /**/
|
||||
# endif
|
||||
|
||||
if( errport > 0 ) {
|
||||
errjfn = getcon(fhno, errport); /* establish error stream */
|
||||
if( errjfn < 0 )
|
||||
return( punt(jfn, "could not open error socket") );
|
||||
} /* wants socket for errors */
|
||||
else errjfn = jfn;
|
||||
|
||||
# ifdef NOTDEF
|
||||
if( hostname(foreign, fhno) < 0 )
|
||||
return( punt(VALJFN, "Could not get name for client host") );
|
||||
lowerify(foreign);
|
||||
# endif
|
||||
|
||||
if( getstr(jfn, lcuser, 39) )
|
||||
return( punt(VALJFN, "bad locuser") );
|
||||
# ifdef BLEH
|
||||
printf("lc: %s\n", lcuser); /**/
|
||||
# endif
|
||||
|
||||
if( getstr(jfn, fnuser, 17) )
|
||||
return( punt(VALJFN, "bad frnuser") );
|
||||
# ifdef BLEH
|
||||
printf("fn: %s\n", fnuser); /**/
|
||||
# endif
|
||||
|
||||
if( getstr(jfn, command, 200) )
|
||||
return( punt(VALJFN, "bad command") );
|
||||
# ifdef BLEH
|
||||
printf("cm: %s\n", command); /**/
|
||||
# endif
|
||||
|
||||
ac1 = Value(RC_emo);
|
||||
ac2 = POINT(lcuser);
|
||||
if( JSYS(JSrcusr, acs) == JSerr )
|
||||
return( punt(VALJFN, "local user does not exist") );
|
||||
userno = ac3;
|
||||
|
||||
# ifndef DEBUG
|
||||
if( ruserok(foreign, 0, fnuser, lcuser ) != 0 )
|
||||
return( punt(VALJFN, "Permission denied.") );
|
||||
|
||||
ac1 = userno; /* get user # in ac1 */
|
||||
ac2 = POINT(""); /* null password */
|
||||
ac3 = POINT(""); /* null account */
|
||||
if( JSYS(JSlogin, acs) == JSerr )
|
||||
return( punt(VALJFN, "LOGIN failed") );
|
||||
# endif
|
||||
|
||||
ac1 = CR_cap; /* pass caps */
|
||||
if( JSYS(JScfork, acs) == JSerr ) /* create a fork */
|
||||
return( punt(VALJFN, "Could not create EXEC fork") );
|
||||
execfork = ac1;
|
||||
|
||||
ac1 = Value(GJ_sht) + Value(GJ_old);
|
||||
ac2 = POINT("SYSTEM:RSHEXEC.EXE");
|
||||
if( JSYS(JSgtjfn, acs) == JSerr )
|
||||
return( punt(VALJFN, "Could not find SYSTEM:RSHEXEC.EXE") );
|
||||
|
||||
ac1 = makeword( execfork, getright(ac1) );
|
||||
if( JSYS(JSget, acs) == JSerr )
|
||||
return( punt(VALJFN, "Could not GET EXEC") );
|
||||
|
||||
/* doprarg(execfork); */
|
||||
|
||||
fnstd(cmd2, command); /* convert unix path to '20 form */
|
||||
if( rcstring(cmd2) < 0 ) /* place in rscan buffer */
|
||||
return( punt(VALJFN, "Could not set up command") );
|
||||
|
||||
write(VALJFN, "", 1); /* send null (validated ok) */
|
||||
|
||||
ac1 = execfork;
|
||||
ac2 = 2; /* start at +2 */
|
||||
if( JSYS(JSsfrkv, acs) == JSerr )
|
||||
return( punt2(VALJFN, "Could not start EXEC") );
|
||||
|
||||
ac1 = execfork;
|
||||
if( JSYS(JSwfork, acs) == JSerr )
|
||||
return( punt2(VALJFN, "Could not wait for EXEC") );
|
||||
|
||||
write(errjfn, "", 1);
|
||||
|
||||
if( errjfn != jfn ) /* if we have an error jfn */
|
||||
close(errjfn, Value(CZ_abt)); /* close (and abort) it */
|
||||
} /* doit */
|
||||
|
||||
int tvtstat(tvt, word)
|
||||
int tvt, word;
|
||||
{
|
||||
int acs[5], result;
|
||||
|
||||
ac1 = tvt + Value(TCP_tv); /* get TVT number in A */
|
||||
ac2 = makeword(-1,word); /* get specified word */
|
||||
ac3 = makeword(-1,(int) &result); /* result */
|
||||
if( JSYS(JSstat, acs) == JSerr ) /* read TCP connection 4n host */
|
||||
return( -1 );
|
||||
else
|
||||
return( result );
|
||||
} /* tvtstat */
|
||||
|
||||
|
||||
setname(s)
|
||||
char *s;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = ac2 = makesix(s);
|
||||
JSYS(JSsetsn, acs);
|
||||
} /* setname */
|
||||
|
||||
int makesix(s)
|
||||
register char *s;
|
||||
{
|
||||
register int i, j;
|
||||
register char c;
|
||||
|
||||
j = 0;
|
||||
for( i = 0; i < 6; i++ ) {
|
||||
if( (c = *s++) != NULL ) {
|
||||
if( c < 040 ) c = '?';
|
||||
if( c > '_' ) c = c - 040;
|
||||
j = (j << 6) + c - 040;
|
||||
} /* if got a char */
|
||||
else break;
|
||||
} /* for */
|
||||
|
||||
if( i < 6 ) j = j << (6 - i);
|
||||
} /* makesix */
|
||||
|
||||
int getstr(jfn, buff, len) /* read counted string, or till NUL */
|
||||
char buff[];
|
||||
int jfn;
|
||||
{
|
||||
int acs[5];
|
||||
|
||||
ac1 = jfn;
|
||||
ac2 = POINT(buff);
|
||||
ac3 = len;
|
||||
ac4 = 0;
|
||||
|
||||
if( JSYS(JSsin,acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
if( ac3 == 0 || (len - ac3) == 0 ) /* overflow or read nothing? */
|
||||
return( -1 );
|
||||
else
|
||||
return( 0 );
|
||||
} /* getstr */
|
||||
|
||||
|
||||
/**************** FROM RCMD.C ****************/
|
||||
|
||||
extern char *index();
|
||||
|
||||
ruserok(rhost, superuser, ruser, luser)
|
||||
char *rhost;
|
||||
int superuser;
|
||||
char *ruser, *luser;
|
||||
{
|
||||
FILE *hostf;
|
||||
char ahost[32];
|
||||
int first = 1;
|
||||
|
||||
hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
|
||||
again:
|
||||
if (hostf) {
|
||||
while (fgets(ahost, sizeof (ahost), hostf)) {
|
||||
char *user, *idx;
|
||||
if ( (idx = index(ahost, '\n')) )
|
||||
*idx = 0;
|
||||
user = index(ahost, ' ');
|
||||
if (user)
|
||||
*user++ = 0;
|
||||
if (!strcmp(rhost, ahost) &&
|
||||
!strcmp(ruser, user ? user : luser)) {
|
||||
(void) fclose(hostf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
(void) fclose(hostf);
|
||||
}
|
||||
if (first == 1) {
|
||||
char buf[100]; /* BUDD */
|
||||
sprintf(buf, "ps:<%s>\026.rhosts", luser); /* BUDD */
|
||||
first = 0;
|
||||
hostf = fopen(buf, "r"); /* BUDD */
|
||||
goto again;
|
||||
}
|
||||
return (-1);
|
||||
} /* ruserok */
|
||||
|
||||
int getcon(fhost, fsock)
|
||||
int fhost, fsock;
|
||||
{
|
||||
char buffer[50];
|
||||
int lsock, jfn;
|
||||
|
||||
for( lsock = 1; lsock < 1024; lsock++ ) {
|
||||
sprintf(buffer,"TCP:%d\026#.%o-%d;CONN:ACT", lsock, fhost, fsock );
|
||||
if( (jfn = trytcp(buffer)) > 0 )
|
||||
return( jfn );
|
||||
} /* for */
|
||||
return( -1 );
|
||||
} /* getcon */
|
||||
|
||||
int punt2(jfn, s)
|
||||
int jfn;
|
||||
char *s;
|
||||
{
|
||||
write(jfn, s, strlen(s)); /* pass failure string */
|
||||
return( -1 );
|
||||
} /* punt2 */
|
||||
|
||||
doprarg(fork)
|
||||
int fork;
|
||||
{
|
||||
int scjprb[8], acs[5];
|
||||
register int *sp;
|
||||
|
||||
sp = scjprb;
|
||||
|
||||
*sp++ = 4; /* 0 - 4 words.. */
|
||||
*sp++ = makeword(0414100, 02545); /* 1 - very magic word */
|
||||
*sp++ = 4; /* 2 - word 4 is data */
|
||||
*sp++ = 0; /* 3 - nothing */
|
||||
*sp++ = (1 << 35); /* 4 - suppress exec herald */
|
||||
|
||||
ac1 = makeword(PRast, fork);
|
||||
ac2 = (int) scjprb;
|
||||
ac3 = 6;
|
||||
JSYS(JSprarg, acs);
|
||||
|
||||
} /* doprarg */
|
||||
|
||||
lowerify(s)
|
||||
register char *s;
|
||||
{
|
||||
register char c;
|
||||
|
||||
while( (c = *s) != NULL ) {
|
||||
if( isupper( c ) ) *s = tolower( c );
|
||||
s++;
|
||||
} /* while */
|
||||
} /* lowerify */
|
||||
|
||||
|
||||
rcstring(s) /* place string in RSCAN buffer */
|
||||
register char *s;
|
||||
{
|
||||
char bigbuf[500], lc;
|
||||
register char c, *d;
|
||||
int acs[5];
|
||||
|
||||
d = bigbuf;
|
||||
while( (c = *s++) != NULL ) {
|
||||
lc = c;
|
||||
if( c == '\n' ) { /* convert NL to CRLF */
|
||||
*d++ = '\r';
|
||||
*d++ = '\n';
|
||||
}
|
||||
else if( c != '\r' ) /* discard CR */
|
||||
*d++ = c;
|
||||
} /* while */
|
||||
|
||||
if( lc != '\n' ) { /* if last was not NL, add CRLF */
|
||||
*d++ = '\r';
|
||||
*d++ = '\n';
|
||||
} /* last not NL */
|
||||
|
||||
*d++ = '\0'; /* tie off with NUL */
|
||||
|
||||
ac1 = POINT(bigbuf); /* insert string into RSCAN */
|
||||
if( JSYS(JSrscan, acs) == JSerr )
|
||||
return( -1 );
|
||||
|
||||
ac1 = RSini; /* make RSCAN available as input */
|
||||
if( JSYS(JSrscan, acs) == JSerr )
|
||||
return( -1 );
|
||||
return( 0 );
|
||||
|
||||
} /* rcstring */
|
||||
|
||||
/** Local Modes: * */
|
||||
/** Comment Column:40 * */
|
||||
/** End: * */
|
||||
3
rshsrv.ctl
Normal file
3
rshsrv.ctl
Normal file
@ -0,0 +1,3 @@
|
||||
@pcc rshsrv.c
|
||||
@pcc rshlib.c
|
||||
@clink rshsrv,rshlib
|
||||
Loading…
x
Reference in New Issue
Block a user