void willoption(int option) { int new_state_ok = 0; if (do_dont_resp[option]) { --do_dont_resp[option]; if (do_dont_resp[option] && my_state_is_do(option)) --do_dont_resp[option]; } if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { switch (option) { case TELOPT_ECHO: case TELOPT_BINARY: case TELOPT_SGA: settimer(modenegotiated); /* FALL THROUGH */ case TELOPT_STATUS: #ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: #endif /* ENCRYPTION */ new_state_ok = 1; break; case TELOPT_TM: if (flushout) flushout = 0; /* * Special case for TM. If we get back a WILL, * pretend we got back a WONT. */ set_my_want_state_dont(option); set_my_state_dont(option); return; /* Never reply to TM will's/wont's */ case TELOPT_LINEMODE: default: break; } if (new_state_ok) { set_my_want_state_do(option); send_do(option, 0); setconnmode(0); /* possibly set new tty mode */ } else { do_dont_resp[option]++; send_dont(option, 0); } } set_my_state_do(option); #ifdef ENCRYPTION if (option == TELOPT_ENCRYPT) encrypt_send_support(); #endif /* ENCRYPTION */ }
/* * 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() */