1
0
mirror of https://github.com/prirun/p50em.git synced 2026-01-11 23:42:56 +00:00

Workaround for locked up AMLC lines

As it was in the real world, especially with dialup ports, it is possible
for an emulator AMLC line to get blocked by stray flow control characters.
The blocked port may appear dead to the next user to connect, if they are
not "serial savvy" enough to try sending an XON character.

A large number of vulnerability scanners have found and have been hitting
the public emulators, injecting HTTP transactions or worse into the AMLC
ports and often locking all of them daily.

This workaround injects an XON (DC1, 0221) and a line kill character as
extracted from the DEFKIL field in FIGCOM, into the AMLC line when a new
connection is received.

There is a -dolineclear command line switch to enable the behavior.
This commit is contained in:
Dennis Boone 2021-02-07 00:37:15 -05:00
parent ea2edd89de
commit d6d01cd05c
3 changed files with 64 additions and 0 deletions

View File

@ -262,6 +262,7 @@ int devamlc (int class, int func, int device) {
unsigned short ctinterrupt; /* 1 bit per line */
unsigned short dss; /* 1 bit per line */
unsigned short connected; /* 1 bit per line */
unsigned short dolineclear; /* 1 bit per line */
unsigned short serial; /* true if any CT_SERIAL lines */
unsigned short dsstime; /* countdown to dss poll */
short fd[16]; /* Unix fd, 1 per line */
@ -329,6 +330,7 @@ int devamlc (int class, int func, int device) {
for (dx=0; dx<MAXBOARDS; dx++) {
dc[dx].deviceid = 0;
dc[dx].connected = 0;
dc[dx].dolineclear = 0;
dc[dx].serial = 0;
for (lx = 0; lx < 16; lx++) {
dc[dx].fd[lx] = -1;
@ -885,6 +887,7 @@ int devamlc (int class, int func, int device) {
close(dc[i].fd[lx]);
dc[i].dss |= BITMASK16(lx+1);
dc[i].connected |= BITMASK16(lx+1);
dc[i].dolineclear |= BITMASK16(lx+1);
dc[i].fd[lx] = fd;
dc[i].tstate[lx] = TS_DATA;
//printf("em: AMLC connection, fd=%d, device='%o, line=%d\n", fd, dc[i].deviceid, lx);
@ -1140,6 +1143,53 @@ dorecv:
if (dc[dx].deviceid == 0 || dc[dx].connected == 0 || dc[dx].eor)
continue;
/* Inject xon / kill if dolineclear is true */
if (dolinecleararg)
for (lx = 0; lx < 16; lx++)
if (dc[dx].dolineclear & BITMASK16(lx+1))
{
unsigned char ch;
unsigned short utemp;
int dmcpair, lcount;
ea_t dmcea, dmcbufbegea, dmcbufendea;
unsigned short dmcnw;
if (dc[dx].bufnum)
dmcea = dc[dx].dmcchan + 2;
else
dmcea = dc[dx].dmcchan;
dmcpair = get32io(dmcea);
dmcbufbegea = dmcpair>>16;
dmcbufendea = dmcpair & 0xffff;
dmcnw = dmcbufendea - dmcbufbegea + 1;
if (dmcnw < 2)
continue;
utemp = lx<<12 | 0x0200 | 0221; /* dc1/xon */
put16io(utemp, dmcbufbegea);
dmcbufbegea = INCVA(dmcbufbegea, 1);
ch = (unsigned char)get16(MAKEVA(014, 0705));
utemp = lx<<12 | 0x0200 | ch; /* kill */
put16io(utemp, dmcbufbegea);
dmcbufbegea = INCVA(dmcbufbegea, 1);
dc[dx].recvlx = lx;
if (dmcbufbegea-1 > dmcbufendea)
fatal("AMLC tumble table overflowed?");
put16io(dmcbufbegea, dmcea);
if (dmcbufbegea > dmcbufendea) { /* end of range has occurred */
dc[dx].bufnum = 1-dc[dx].bufnum;
dc[dx].eor = 1;
neweor = 1;
anyeor = 1;
}
dc[dx].dolineclear &= ~BITMASK16(lx+1);
}
/* select to see which lines have data to be read */
FD_ZERO(&readfds);

9
em.1
View File

@ -145,6 +145,15 @@ on the host. Multiple trace types may be listed, separated by
spaces. Tracing may be initially turned off by including the
.I off
trace type.
.PP
\fB-dolineclear\fR
.IP
Inject an XON (DC1, 0221) character and a line kill character into the
input buffers each time an AMLC line receives an incoming connection.
The system's configured line kill character is fetched from the
DEFKIL field of FIGCOM, at address 14(0)/705. This behavior helps
counteract lines which have been blocked by internet vulnerability
scanners injecting non-telnet data streams.
.\" ---------------------------------------------------------------------------
.SH FILES
.TP

5
em.c
View File

@ -658,6 +658,7 @@ static unsigned short *physmem = NULL; /* system's physical memory */
//static ea_t tnoua_ea=0, tnou_ea=0, tsrc_ea=0;
static int domemdump; /* -memdump arg */
static int dolinecleararg; /* -dolineclear arg */
static int tport; /* -tport option (incoming terminals) */
static int nport; /* -nport option (PNC/Ringnet) */
@ -4451,6 +4452,7 @@ int main (int argc, char **argv) {
#include "dispatch.h"
domemdump = 0;
dolinecleararg = 0;
bootarg = NULL;
bootfile[0] = 0;
gv.pmap32bits = 0;
@ -4470,6 +4472,9 @@ int main (int argc, char **argv) {
} else if (strcmp(argv[i],"-memdump") == 0) {
domemdump = 1;
} else if (strcmp(argv[i],"-dolineclear") == 0) {
dolinecleararg = 1;
} else if (strcmp(argv[i],"-ss") == 0) {
if (i+1 < argc && argv[i+1][0] != '-') {
sscanf(argv[++i],"%o", &templ);