void doLinemode(struct WindRec *tw) { short i; unsigned char subBeginSeq[4] = {IAC,TEL_SB,N_LINEMODE,L_SLC}; unsigned char subEndSeq[2] = {IAC,TEL_SE}; unsigned char toSend[3]; tw->lmodeBits = 0; tw->lmode = TRUE; tw->litNext = FALSE; netwrite(tw->port,subBeginSeq,4); opts_debug_print("SENT: IAC SB LINEMODE SLC"); for (i=1; i<= SLC_MAX; i++) { if (tw->slc[i]==255) { toSend[0] = i; toSend[1] = SLC_NOSUPPORT; toSend[2] = 0; #ifdef OPTS_DEBUG sprintf(munger," %s NO_SUPPORT 0",LMoptions[i]); #endif } else { toSend[0] = i; toSend[1] = SLC_VALUE; toSend[2] = tw->slc[i]; #ifdef OPTS_DEBUG sprintf(munger," %s VALUE %d",LMoptions[i],(short)tw->slc[i]); #endif } opts_debug_print(munger); netwrite(tw->port,toSend,3); } opts_debug_print("SENT: IAC SE"); netpush(tw->port); netwrite(tw->port,subEndSeq,2); }
void process_key(unsigned char ascii,struct WindRec *tw) { if (tw->litNext) { //do no processing on next key tw->litNext = FALSE; kbwrite(tw, &ascii, 1); if (tw->echo) { if (ascii>31 && ascii <127) { /* add these chars to buffer */ parse(tw, &ascii, 1); } return; } } if (tw->lmodeBits & 2) { // TRAPSIG mode active unsigned char toSend[2] = {IAC,0}; short whichSignal = 0; if (ascii == tw->slc[SLC_IP]) { whichSignal = SLC_IP; toSend[1] = TEL_IP; } else if (ascii == tw->slc[SLC_SUSP]) { whichSignal = SLC_SUSP; toSend[1] = TEL_SUSP; } // RAB BetterTelnet 2.0b1 // The defaults in parse.h are to send ABORT on ^\ which is usually correct, but // feel free to hack this (in parse.h, not here) if BRK is better in your configuration. else if (ascii == tw->slc[SLC_ABORT]) { whichSignal = SLC_ABORT; toSend[1] = TEL_ABORT; } else if (ascii == tw->slc[SLC_BRK]) // RAB BetterTelnet 2.0b1 { whichSignal = SLC_BRK; toSend[1] = TEL_BREAK; } if (toSend[1]) //if we have a signal to catch { // if (tw->echo) // parse(tw, &ascii, 1); // echo if we should tw->kblen=0; //zero out the buffer netpush(tw->port); netwrite(tw->port,toSend,2); //send IAC whatever if (tw->slcLevel[whichSignal] & SLC_FLUSHIN) { unsigned char dm[2] = {IAC,TEL_DM}; netpush(tw->port); netUrgent();//send next as urgent data netwrite(tw->port,dm,2);//send IAC DM } if (tw->slcLevel[whichSignal] & SLC_FLUSHOUT) { unsigned char tm[3] = {IAC,TEL_DOTEL,N_TIMING}; tw->timing = 1; //tell ourselves to wait for WILL TIMING netpush(tw->port); netwrite(tw->port,tm,3);//send DO TIMING } return; } } if ((tw->lmodeBits & L_SOFT_TAB)&&(ascii == 0x09)) // SOFT_TAB mode active; expand tab into spaces { short numSpaces = VSIgetNextTabDistance(); unsigned char spacechar = ' '; while (numSpaces-- > 0) { kbwrite(tw, &spacechar, 1); } if (tw->echo) parse(tw, &ascii, 1); return; } if (tw->lmodeBits & L_EDIT) //handle editing functions { if (ascii == '\015') //CR { //since we are in edit, send the buffer and CR-LF kbflush(tw); netpush(tw->port); netwrite(tw->port,"\015\012",2); if (tw->echo) parse(tw,(unsigned char *) "\012\015",2); return; } if (ascii == tw->slc[SLC_EC]) //kill the character { if (tw->echo) parse(tw,(unsigned char *) "\010 \010",3); tw->kblen--; return; } else if (ascii == tw->slc[SLC_AO]) //kill the line { while (tw->kblen >0) { if (tw->echo) parse(tw,(unsigned char *) "\010 \010",3); tw->kblen--; } return; } else if (ascii == tw->slc[SLC_EL]) //kill the line { while (tw->kblen >0) { if (tw->echo) parse(tw,(unsigned char *) "\010 \010",3); tw->kblen--; } return; } else if ((ascii == tw->slc[SLC_EOF]) && (tw->lmodeBits & 2)) { //push the buffer, send IAC EOF (RAB BetterTelnet 2.0b1 - only under TRAPSIG) char eofString[2] = { IAC, TEL_EOF }; kbflush(tw); // RAB BetterTelnet 2.0b1 - BAD! BAD! BAD! // Fix for *BSD (and probably others): // Putting ^D into Telnet's key buffer after sending an EOF could make it pop up later, so // hitting some keys (arrows seemed to do the trick) that flushed Telnet's key buffer // after a cat command which terminated with ^D caused a logout. Yuck. // tw->kbbuf[0]=ascii; // tw->kblen=1; netpush(tw->port); netwrite(tw->port,eofString, 2); return; } // RAB BetterTelnet 2.0b1 // We don't need to do this down here if we're already handling TRAPSIG mode // separately. The SUSP (usually ^Z) char is part of TRAPSIG, not EDIT. // else if (ascii == tw->slc[SLC_SUSP]) // { // char eofString[2] = { IAC, TEL_SUSP }; // if (tw->kblen > 0) // netwrite(tw->port, tw->kbbuf, tw->kblen); // tw->kblen = 0; // netpush(tw->port); // netwrite(tw->port,eofString, 2); // return; // } else if (ascii == tw->slc[SLC_EW]) { while ((tw->kbbuf[tw->kblen-1] != 0x20)&&(tw->kblen >= 0)) //while its not a space { if (tw->echo) parse(tw,(unsigned char *)"\010 \010",3); tw->kblen--; } } else if (ascii == tw->slc[SLC_RP]) { VSredrawLine(tw->vs); return; } else if (ascii == tw->slc[SLC_LNEXT]) { tw->litNext = TRUE; return; } else if (ascii == tw->slc[SLC_XON]) { if (tw->allow_flow) { //remote flow control can turn this off tw->enabled = 1; // oops small bug (RAB BetterTelnet 2.0b1) changeport(scrn, scrn); } return; } else if (ascii == tw->slc[SLC_XOFF]) { if (tw->allow_flow) { //remote flow control can turn this off tw->enabled = 0; changeport(scrn, scrn); } return; } else if ((ascii == tw->slc[SLC_FORW1])||(ascii == tw->slc[SLC_FORW1])) { kbflush(tw); netwrite(tw->port,&ascii,1); return; } //ok, at this point, we are past all local editing functions. Now, add the character to the buffer. else { kbwrite(tw, &ascii, 1); } } else if (ascii == '\015') //CR; map this to CR-LF { unsigned char toSend[2] = {0x0D,0x00}; netpush(tw->port); netwrite(tw->port,toSend,2); if (tw->echo) parse(tw,(unsigned char *) "\012\015",2); return; } else //not editing; send it { netpush(tw->port); netwrite( tw->port, &ascii, 1); // if full send buffer } if (tw->echo) /* Handle local ECHOs */ { if (ascii>31 && ascii <127) /* add these chars to buffer */ parse(tw, &ascii, 1); else /* not printable char */ { if (!(tw->lmodeBits & L_LIT_ECHO)) //don't echo if this is set { ascii='@'+ascii; parse(tw,(unsigned char *) "^",1); parse(tw, &ascii, 1); } } } }
void linemode_suboption(struct WindRec *tw) { switch(tw->parsedat[1]) { char s[80]; case L_MODE: /* change mode */ #ifdef OPTS_DEBUG strcpy(s, "RECV: SB LINEMODE MODE => "); DemangleLineModeShort(s, tw->parsedat[2]); opts_debug_print(s); #endif if (tw->lineAllow) { // First make sure we allowed linemode in the first place. // RFC 1184 says client should ignore MODE negotiations with the MODE_ACK bit set, and should not // generate a response if the negotiated MODE matches the current MODE if (!((tw->parsedat[2] & L_MODE_ACK) || ((tw->parsedat[2] & L_MODE_MASK) == tw->lmodeBits))) { tw->lmodeBits = tw->parsedat[2]; // Accept the mode tw->parsedat[2] |= L_MODE_ACK; // Set the MODE_ACK bit sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_MODE); netwrite(tw->port,s,4); sprintf(s,"%c%c%c",tw->parsedat[2],IAC,TEL_SE); netwrite(tw->port,s,3); #ifdef OPTS_DEBUG opts_debug_print("SENT: IAC SB"); strcpy(s, "SENT: LM MODE = "); DemangleLineModeShort(s, tw->parsedat[2]); opts_debug_print(s); opts_debug_print("SENT: IAC SE"); #endif } #ifdef OPTS_DEBUG else { strcpy(s, "LINEMODE MODE = "); DemangleLineModeShort(s, tw->parsedat[2]); opts_debug_print(s); if (tw->parsedat[2] & L_MODE_ACK) opts_debug_print("\tignored because MODE_ACK was set."); else opts_debug_print("\tIgnored because we are already at that mode."); strcpy(s, "Curr Linemode = "); DemangleLineModeShort(s, tw->lmodeBits); opts_debug_print(s); } #endif } break; case TEL_DOTEL: #ifdef OPTS_DEBUG sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]); opts_debug_print(munger); #endif tw->forwardMask = TRUE; setForwardMask(tw); str_lm[3] = TEL_WILLTEL; str_lm[4] = L_FORWARDMASK; netpush(tw->port); netwrite(tw->port, str_lm, sizeof(str_lm)); #ifdef OPTS_DEBUG sprintf(munger,"SENT: IAC SB LINEMODE WILL %c IAC SE", tw->parsedat[2]); opts_debug_print(munger); #endif break; case TEL_DONTTEL: #ifdef OPTS_DEBUG sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]); opts_debug_print(munger); #endif tw->forwardMask = FALSE; str_lm[3] = TEL_WONTTEL; str_lm[4] = L_FORWARDMASK; netpush(tw->port); netwrite(tw->port, str_lm, sizeof(str_lm)); #ifdef OPTS_DEBUG sprintf(munger,"SENT: IAC SB LINEMODE WONT %c IAC SE", tw->parsedat[2]); opts_debug_print(munger); #endif break; case L_SLC: /* set local chars */ negotiateSLC(tw); break; default: #ifdef OPTS_DEBUG sprintf(munger, "RECV: SB LINEMODE ?? (?? = %c)", tw->parsedat[1]); opts_debug_print(munger); #endif break; }//switch parsedat }
void negotiateSLC(struct WindRec *tw) { short lmslcflag = 0; unsigned char *ourValues = tw->slc; unsigned char *ourLevels = tw->slcLevel; short i; #ifdef OPTS_DEBUG sprintf(munger,"RECV: IAC SB LINEMODE SLC"); opts_debug_print(munger); for(i=2;i <= tw->parseIndex - 3; i+=3) { if (tw->parsedat[i] > 30) break; // RAB BetterTelnet 2.0b3 // we shouldn't panic on bad data // if (tw->parsedat[i] > 30) // DebugStr("\pAck! Bad option number"); if(tw->parsedat[i+1] & SLC_AWK) sprintf(munger," %s %s|AWK %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]); else sprintf(munger," %s %s %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]); opts_debug_print(munger); } sprintf(munger,"RECV: IAC SE"); opts_debug_print(munger); #endif for (i=2, lmslcflag=0; i <= tw->parseIndex - 3; i+=3) { short optionNumber = tw->parsedat[i]; Boolean awked = (tw->parsedat[i+1] & SLC_AWK); unsigned char requestedValue = tw->parsedat[i+2]; unsigned char requestedLevel = tw->parsedat[i+1] & SLC_LEVELBITS; Boolean flushin = tw->parsedat[i+1] & SLC_FLUSHIN; Boolean flushout = tw->parsedat[i+1] & SLC_FLUSHOUT; if ((ourValues[optionNumber] != requestedValue)||(ourLevels[optionNumber] != tw->parsedat[i+1])) //if we are sent what we already have, ignore it { if (requestedLevel == SLC_NOSUPPORT) { if (ourLevels[optionNumber] & SLC_LEVELBITS != SLC_NOSUPPORT) { ourValues[optionNumber] = 255; ourLevels[optionNumber] = SLC_NOSUPPORT;//ok, we wont support this if (!awked) respondSLC(optionNumber,&lmslcflag, tw, TRUE);//awk only if he didnt awk #ifdef OPTS_DEBUG else { sprintf(munger,"\t %s %s %d accepted; no response sent because it was AWKED", LMoptions[optionNumber],LMflags[requestedLevel],requestedValue); opts_debug_print(munger); } #endif } #ifdef OPTS_DEBUG else { sprintf(munger, "\t %s %s %d Ignored because we are already at nosupport", LMoptions[optionNumber],LMflags[requestedLevel],ourValues[optionNumber]); opts_debug_print(munger); } #endif } else if (requestedLevel == SLC_DEFAULT) { ourValues[optionNumber] = default_slc[optionNumber]; //get our default if (ourValues[optionNumber] == 255) ourLevels[optionNumber] = SLC_NOSUPPORT; else ourLevels[optionNumber] = SLC_VALUE; respondSLC(optionNumber, &lmslcflag, tw, FALSE); //tell him about our choice } else if (requestedLevel > ourLevels[optionNumber]) respondSLC(optionNumber, &lmslcflag, tw, FALSE); //keep lower setting else { ourValues[optionNumber] = requestedValue; ourLevels[optionNumber] = requestedLevel; if (flushin) ourLevels[optionNumber] |= SLC_FLUSHIN; if (flushout) ourLevels[optionNumber] |= SLC_FLUSHOUT; if (!awked) respondSLC(optionNumber, &lmslcflag, tw, TRUE); //agree to his new setting } } #ifdef OPTS_DEBUG else { sprintf(munger, "\t %s %s Ignored because %d is already the current value", LMoptions[optionNumber],LMflags[requestedLevel],ourValues[optionNumber]); opts_debug_print(munger); } #endif }//end for on parseindex if (lmslcflag) { unsigned char toSend[2] = {IAC,TEL_SE}; netpush(tw->port); netwrite(tw->port,toSend,2); opts_debug_print("SENT: IAC SE"); } }
/* * parse * Do the telnet negotiation parsing. * * look at the string which has just come in from outside and * check for special sequences that we are interested in. * * Tries to pass through routine strings immediately, waiting for special * characters ESC and IAC to change modes. */ void parse(CONNECTION *con,unsigned char *st,int cnt) { static int sub_pos; /* the position we are in the subnegotiation parsing */ static int end_sub; /* index of last byte in parsedat in a subnegotiation */ unsigned char *mark, *orig; char buf[256]; kstream ks; ks = con->ks; #ifdef PRINT_EVERYTHING hexdump("Options to process:", st, cnt); #endif /* PRINT_EVERYTHING */ orig = st; /* remember beginning point */ mark = st + cnt; /* set to end of input string */ #ifdef HUH netpush(tw->pnum); #endif /* * traverse string, looking for any special characters which indicate that * we need to change modes. */ while(st < mark) { while(con->telstate != STNORM && st < mark) { switch(con->telstate) { case IACFOUND: /* telnet option negotiation */ if(*st == IAC) { /* real data=255 */ st++; /* real 255 will get sent */ con->telstate = STNORM; break; } /* end if */ if(*st > 239) { con->telstate = *st++; /* by what the option is */ break; } /* end if */ #ifdef NEGOTIATEDEBUG wsprintf(buf, "\r\n strange telnet option"); OutputDebugString(buf); #endif orig=++st; con->telstate=STNORM; break; case EL: /* received a telnet erase line command */ case EC: /* received a telnet erase character command */ case AYT: /* received a telnet Are-You-There command */ case AO: /* received a telnet Abort Output command */ case IP: /* received a telnet Interrupt Process command */ case BREAK: /* received a telnet Break command */ case DM: /* received a telnet Data Mark command */ case NOP: /* received a telnet No Operation command */ case SE: /* received a telnet Subnegotiation End command */ case ABORT: /* received a telnet Abort Process command */ case SUSP: /* received a telnet Suspend Process command */ case xEOF: /* received a telnet EOF command */ #ifdef NEGOTIATEDEBUG wsprintf(buf,"RECV: %s\r\n", telstates[con->telstate-TELCMD_FIRST]); OutputDebugString(buf); #endif con->telstate=STNORM; orig=++st; break; case GA: /* telnet go ahead option*/ #ifdef NEGOTIATEDEBUG wsprintf(buf,"RECV: %s\r\n", telstates[con->telstate-TELCMD_FIRST]); OutputDebugString(buf); #endif con->telstate=STNORM; orig=++st; break; case DO: /* received a telnet DO negotiation */ #ifdef NEGOTIATEDEBUG wsprintf(buf,"RECV: %s %s\r\n", telstates[con->telstate-TELCMD_FIRST],teloptions[*st]); OutputDebugString(buf); #endif switch(*st) { #ifdef NOT case TELOPT_BINARY: /* DO: binary transmission */ if(!tw->ibinary) { /* binary */ if(!tw->iwantbinary) { netprintf(tw->pnum,"%c%c%c", IAC,WILL,BINARY); if(tw->condebug>0) tprintf(cv,"SEND: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[BINARY]); } /* end if */ else tw->iwantbinary=0; /* turn off this now */ tw->ibinary=1; } /* end if */ else { if(tw->condebug>0) tprintf(cv,"NO REPLY NEEDED: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[BINARY]); } /* end else */ break; #endif case TELOPT_SGA: /* DO: Suppress go-ahead */ if(!con->igoahead) { /* suppress go-ahead */ wsprintf(buf,"%c%c%c",IAC,WILL,TELOPT_SGA); TelnetSend(ks,buf,lstrlen(buf),0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_SGA]); OutputDebugString(strTmp); OutputDebugString("igoahead"); #endif con->igoahead=1; } /* end if */ else { #ifdef NEGOTIATEDEBUG wsprintf(strTmp, "NO REPLY NEEDED: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_SGA]); OutputDebugString(strTmp); #endif } /* end else */ break; case TELOPT_TTYPE: /* DO: terminal type negotiation */ if(!con->termsent) { con->termsent=TRUE; wsprintf(buf,"%c%c%c",IAC,WILL,TELOPT_TTYPE); TelnetSend(ks,buf,lstrlen(buf),0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_TTYPE]); OutputDebugString(strTmp); #endif } /* end if */ else { #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"NO REPLY NEEDED: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_TTYPE]); OutputDebugString(strTmp); #endif } /* end else */ break; #ifdef LATER case TELOPT_LINEMODE: /* DO: linemode negotiation */ tw->lmflag=1; /* set the linemode flag */ netprintf(tw->pnum,"%c%c%c",IAC,WILL,TELOPT_LINEMODE); /* * Tell the other side to send us * its default character set */ netprintf(tw->pnum,"%c%c%c%c", IAC,SB,TELOPT_LINEMODE,SLC,0,SLC_DEFAULT,0,IAC,SE); if(tw->condebug>0) { tprintf(cv,"SEND: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_LINEMODE]); tprintf(cv, "SEND: SB LINEMODE SLC 0 SLC_DEFAULT 0 IAC SE\r\n"); } /* end if */ break; #endif case TELOPT_NAWS: /* DO: Negotiate About Window Size */ con->bResizeable=TRUE; send_naws(con); break; case TELOPT_AUTHENTICATION: /* DO: Authentication requested */ wsprintf(buf, "%c%c%c", IAC, WILL, TELOPT_AUTHENTICATION); TelnetSend(ks, buf, lstrlen(buf), 0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_AUTHENTICATION]); OutputDebugString(strTmp); #endif break; #ifdef ENCRYPTION case TELOPT_ENCRYPT: /* DO: Remote is willing to receive encrypted */ wsprintf(buf, "%c%c%c", IAC, (encrypt_flag ? WILL : WONT), TELOPT_ENCRYPT); TelnetSend(ks, buf, lstrlen(buf), 0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[(encrypt_flag ? WILL : WONT) - TELCMD_FIRST], teloptions[TELOPT_ENCRYPT]); OutputDebugString(strTmp); #endif break; #endif /* ENCRYPTION */ default: /* DO: */ wsprintf(buf, "%c%c%c", IAC, WONT, *st); TelnetSend(ks, buf, lstrlen(buf), 0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[WONT - TELCMD_FIRST], teloptions[*st]); OutputDebugString(strTmp); #endif break; } /* end switch */ con->telstate = STNORM; orig = ++st; break; case DONT: /* Received a telnet DONT option */ switch (*st) { case TELOPT_NAWS: con->bResizeable=FALSE; #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"RECV: %s %s\r\n", telstates[con->telstate-TELCMD_FIRST],teloptions[*st]); OutputDebugString(strTmp); #endif break; #ifdef NOT case BINARY: /* DONT: check for binary neg. */ if(tw->ibinary) { /* binary */ if(!tw->iwantbinary) { netprintf(tw->pnum,"%c%c%c",IAC,WONT,BINARY); if(tw->condebug>0) tprintf(cv,"SEND: %s %s\r\n", telstates[WONT-TELCMD_FIRST], teloptions[BINARY]); } /* end if */ else tw->iwantbinary=0; /* turn off this now */ tw->ibinary=0; tw->mapoutput=0; /* turn output mapping off */ } /* end if */ #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"NO REPLY NEEDED: %s %s\r\n", telstates[WONT-TELCMD_FIRST], teloptions[BINARY]); OutputDebugString(strTmp); #endif break; #endif #ifdef ENCRYPTION case ENCRYPTION: break; #endif } /* all these just fall through to here... */ con->telstate=STNORM; orig=++st; break; case WILL: /* received a telnet WILL option */ #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"RECV: %s %s\r\n", telstates[con->telstate-TELCMD_FIRST], teloptions[*st]); OutputDebugString(strTmp); #endif switch(*st) { #ifdef NOT case TELOPT_BINARY: /* WILL: binary */ if(!tw->ubinary) { /* binary */ if(!tw->uwantbinary) { netprintf(tw->pnum,"%c%c%c", IAC,DO,TELOPT_BINARY); if(tw->condebug>0) tprintf(cv,"SEND: %s %s\r\n", telstates[DO - TELCMD_FIRST], teloptions[TELOPT_BINARY]); } /* end if */ else tw->uwantbinary=0; /* turn off this now */ tw->ubinary=1; } /* end if */ else { if(tw->condebug>0) tprintf(cv,"NO REPLY NEEDED: %s %s\r\n", telstates[DO - TELCMD_FIRST], teloptions[TELOPT_BINARY]); } /* end else */ break; #endif case TELOPT_SGA: /* WILL: suppress go-ahead */ if(!con->ugoahead) { con->ugoahead=1; wsprintf(buf,"%c%c%c",IAC,DO,TELOPT_SGA); /* ack */ TelnetSend(ks,buf,lstrlen(buf),0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[DO - TELCMD_FIRST], teloptions[TELOPT_SGA]); OutputDebugString(strTmp); #endif } /* end if */ break; case TELOPT_ECHO: /* WILL: echo */ if(!con->echo) { con->echo = 1; wsprintf(buf, "%c%c%c", IAC, DO, TELOPT_ECHO); /* ack */ TelnetSend(ks, buf, lstrlen(buf), 0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[DO - TELCMD_FIRST], teloptions[TELOPT_ECHO]); OutputDebugString(strTmp); #endif } /* end if */ break; case TELOPT_TM: /* WILL: Timing mark */ con->timing=0; break; #ifdef ENCRYPTION case TELOPT_ENCRYPT: /* WILL: decrypt our input */ wsprintf(buf, "%c%c%c", IAC, (encrypt_flag ? DO : DONT), TELOPT_ENCRYPT); TelnetSend(ks, buf, lstrlen(buf), 0); if (encrypt_flag) encrypt_send_support(); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[(encrypt_flag ? DO : DONT) - TELCMD_FIRST], teloptions[TELOPT_ENCRYPT]); OutputDebugString(strTmp); #endif break; #endif default: wsprintf(buf,"%c%c%c",IAC,DONT,*st); TelnetSend(ks,buf,lstrlen(buf),0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[DONT-TELCMD_FIRST],teloptions[*st]); OutputDebugString(strTmp); #endif break; } /* end switch */ con->telstate=STNORM; orig=++st; break; case WONT: /* Received a telnet WONT option */ #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"RECV: %s %s\r\n", telstates[con->telstate-TELCMD_FIRST],teloptions[*st]); OutputDebugString((LPSTR)strTmp); #endif con->telstate=STNORM; switch(*st++) { /* which option? */ #ifdef NOT case BINARY: /* WONT: binary */ if(tw->ubinary) { /* binary */ if(!tw->uwantbinary) { netprintf(tw->pnum,"%c%c%c", IAC,DONT,BINARY); if(tw->condebug>0) tprintf(cv,"SEND: %s %s\r\n", telstates[DONT-TELCMD_FIRST], teloptions[BINARY]); } /* end if */ else tw->uwantbinary=0; /* turn off this now */ tw->ubinary=0; tw->mapoutput=0; /* turn output mapping off */ } /* end if */ else { if(tw->condebug>0) tprintf(cv,"NO REPLY NEEDED: %s %s\r\n", telstates[DONT-TELCMD_FIRST], teloptions[BINARY]); } /* end else */ break; #endif case TELOPT_ECHO: /* WONT: echo */ if(con->echo) { con->echo=0; wsprintf(buf,"%c%c%c",IAC,DONT,TELOPT_ECHO); TelnetSend(ks,buf,lstrlen(buf),0); #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n", telstates[DONT-TELCMD_FIRST], teloptions[TELOPT_ECHO]); OutputDebugString(strTmp); OutputDebugString("Other side won't echo!"); #endif } /* end if */ break; case TELOPT_TM: /* WONT: Telnet timing mark option */ con->timing=0; break; #ifdef ENCRYPTION case TELOPT_ENCRYPT: /* WONT: don't encrypt our input */ break; #endif default: break; } /* end switch */ orig=st; break; case SB: /* telnet sub-options negotiation */ con->telstate=NEGOTIATE; orig=st; end_sub=0; sub_pos=con->substate=0; /* Defined for each */ #ifdef OLD_WAY break; #endif case NEGOTIATE: /* until we change sub-negotiation states, accumulate bytes */ if(con->substate==0) { if(*st==IAC) { /* check if we found an IAC byte */ if(*(st+1)==IAC) { /* skip over double IAC's */ st++; parsedat[sub_pos++]=*st++; } /* end if */ else { end_sub=sub_pos; con->substate=*st++; } /* end else */ } /* end if */ else /* otherwise, just stash the byte */ parsedat[sub_pos++]=*st++; } /* end if */ else { con->substate=*st++; /* check if we've really ended the sub-negotiations */ if(con->substate==SE) parse_subnegotiat(ks,end_sub); orig=st; /* * XXX hack to decrypt the rest of the buffer */ if (encrypt_flag == 2) { decrypt_ks_hack(orig, mark - orig); encrypt_flag = 1; } con->telstate=STNORM; } /* end else */ break; default: con->telstate=STNORM; break; } /* end switch */ } /* end while */ /* * quick scan of the remaining string, skip chars while they are * uninteresting */ if(con->telstate==STNORM && st<mark) { /* * skip along as fast as possible until an interesting character is found */ while(st<mark && *st!=27 && *st!=IAC) { #if 0 if(!tw->ubinary) *st&=127; /* mask off high bit */ #endif st++; } /* end while */ #if 0 if(!tw->timing) parsewrite(tw,orig,st-orig); #endif orig=st; /* forget what we have sent already */ if(st<mark) switch(*st) { case IAC: /* telnet IAC */ con->telstate=IACFOUND; st++; break; default: #ifdef NEGOTIATEDEBUG wsprintf(buf," strange char>128 0x%x\r\n", *st); OutputDebugString(buf); #endif st++; break; } /* end switch */ } /* end if */ } /* end while */ } /* end parse() */