Commit 2b1bccc2 authored by rswindell's avatar rswindell
Browse files

Received-telnet command improvements:

- If a telnet command was received in multiple packets, the memcpy optimization
  in telnet_interpret() would skip/drop all bytes in the subsequent pkt payload
  before an IAC char. Don't optimize when in the middle of a telnet command.
- If a received telnet command exceeds the telnet_cmd buffer, reset the
  received telnet_cmdlen and log a warning-level message
- If a telnet sub-negotiation END command is received as the beginning of a
  new telnet command, log a warning-level message and reset the telnet_cmdlen.

This fixes the occasional problem observed when using fTelnet and its sending
the "SEND-LOCATION" sub-neg command split between 2 TCP packets. Only
part of the first packet would be used as the location data and the rest
processed as input from the users (e.g. as the Login: prompt). Thanks, Ree!
parent f87552c5
......@@ -1469,8 +1469,9 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
BYTE* first_cr=NULL;
int i;
outlen=0;
if(inlen<1) {
outlen=0;
return(inbuf); // no length? No interpretation
}
......@@ -1485,19 +1486,20 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
first_cr=(BYTE*)memchr(inbuf, CR, inlen);
}
if(!sbbs->telnet_cmdlen && first_iac==NULL && first_cr==NULL) {
outlen=inlen;
return(inbuf); // no interpretation needed
}
if(!sbbs->telnet_cmdlen) {
if(first_iac==NULL && first_cr==NULL) {
outlen=inlen;
return(inbuf); // no interpretation needed
}
if(first_iac!=NULL || first_cr!=NULL) {
if(first_iac!=NULL && (first_cr==NULL || first_iac<first_cr))
outlen=first_iac-inbuf;
else
outlen=first_cr-inbuf;
memcpy(outbuf, inbuf, outlen);
} else
outlen=0;
if(first_iac!=NULL || first_cr!=NULL) {
if(first_iac!=NULL && (first_cr==NULL || first_iac<first_cr))
outlen=first_iac-inbuf;
else
outlen=first_cr-inbuf;
memcpy(outbuf, inbuf, outlen);
}
}
for(i=outlen;i<inlen;i++) {
if(!(sbbs->telnet_mode&TELNET_MODE_GATE)
......@@ -1524,11 +1526,21 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
if(sbbs->telnet_cmdlen<sizeof(sbbs->telnet_cmd))
sbbs->telnet_cmd[sbbs->telnet_cmdlen++]=inbuf[i];
else {
lprintf(LOG_WARNING, "Node %d telnet command (%d, %d) buffer limit reached (%u bytes)"
,sbbs->cfg.node_num, sbbs->telnet_cmd[1], sbbs->telnet_cmd[2], sbbs->telnet_cmdlen);
sbbs->telnet_cmdlen = 0;
}
uchar command = sbbs->telnet_cmd[1];
uchar option = sbbs->telnet_cmd[2];
if(sbbs->telnet_cmdlen>=2 && command==TELNET_SB) {
if(sbbs->telnet_cmdlen == 2 && command == TELNET_SE) {
lprintf(LOG_WARNING, "Node %d unexpected telnet sub-negotiation END command"
,sbbs->cfg.node_num);
sbbs->telnet_cmdlen = 0;
}
else if(sbbs->telnet_cmdlen>=2 && command==TELNET_SB) {
if(inbuf[i]==TELNET_SE
&& sbbs->telnet_cmd[sbbs->telnet_cmdlen-2]==TELNET_IAC) {
......@@ -1633,7 +1645,7 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
,sbbs->telnet_cmd[3]);
sbbs->telnet_cmdlen=0;
}
}
} // Sub-negotiation command
else if(sbbs->telnet_cmdlen==2 && inbuf[i]<TELNET_WILL) {
if(startup->options&BBS_OPT_DEBUG_TELNET)
lprintf(LOG_DEBUG,"Node %d %s telnet cmd: %s"
......@@ -1725,9 +1737,7 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen,
#endif
}
}
sbbs->telnet_cmdlen=0;
}
if(sbbs->telnet_mode&TELNET_MODE_GATE) // Pass-through commands
outbuf[outlen++]=inbuf[i];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment