1
0
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:
Lars Brinkhoff 2018-10-20 10:34:00 +00:00
commit eb120e076e
8 changed files with 1738 additions and 0 deletions

343
rsh.mid Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,3 @@
@pcc rshsrv.c
@pcc rshlib.c
@clink rshsrv,rshlib