/* * Function : start_negotiation() * Purpose : Send the initial negotiations on the network and print * the negotitations to the console screen. * Parameters : * dat - the port number to write to * cvs - the console's virtual screen * Returns : none * Calls : tprintf(), netprintf() * Called by : dosessions() */ void start_negotiation(kstream ks) { char buf[128]; /* Send the initial telnet negotiations */ #ifdef ENCRYPTION /* XXX */ if (encrypt_flag) wsprintf(buf,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", IAC, WILL, TELOPT_AUTHENTICATION, IAC, WILL, TELOPT_ENCRYPT, IAC, DO, TELOPT_SGA, IAC, DO, TELOPT_ECHO, IAC, WILL, TELOPT_NAWS ); else #endif wsprintf(buf,"%c%c%c%c%c%c%c%c%c%c%c%c", IAC, WILL, TELOPT_AUTHENTICATION, IAC, DO, TELOPT_SGA, IAC, DO, TELOPT_ECHO, IAC, WILL, TELOPT_NAWS ); TelnetSend(ks,buf,lstrlen(buf),0); #ifdef NOT /* check whether we are going to be output mapping */ if(tw->mapoutput) { netprintf(tw->pnum,"%c%c%c",IAC,DO,TELOPT_BINARY); /* set the flag indicating we wanted server to start transmitting binary */ tw->uwantbinary=1; netprintf(tw->pnum,"%c%c%c",IAC,WILL,TELOPT_BINARY); /* set the flag indicating we want to start transmitting binary */ tw->iwantbinary=1; } /* end if */ #endif /* Print to the console what we just did */ #ifdef NEGOTIATEDEBUG wsprintf(strTmp,"SEND: %s %s\r\n",telstates[DO - TELCMD_FIRST], teloptions[TELOPT_ECHO]); OutputDebugString(strTmp); wsprintf(strTmp,"SEND: %s %s\r\n",telstates[DO - TELCMD_FIRST], teloptions[TELOPT_SGA]); OutputDebugString(strTmp); wsprintf(strTmp,"SEND: %s %s\r\n",telstates[WILL - TELCMD_FIRST], teloptions[TELOPT_NAWS]); OutputDebugString(strTmp); #ifdef NOT tprintf(cvs,"SEND: %s %s\r\n",telstates[DO - TELCMD_FIRST], teloptions[BINARY]); tprintf(cvs,"SEND: %s %s\r\n",telstates[WILL - TELCMD_FIRST], teloptions[BINARY]); #endif #endif } /* end start_negotiation() */
void console_print(const char *s) { int mtx_err = sceKernelTryLockMutex(console_mtx, 1); netprintf(s); if (mtx_err == SCE_KERNEL_OK) { sceKernelUnlockMutex(console_mtx, 1); } }
/* * 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() */
void telrcv() { register int c; static int state = TS_DATA; #if defined(CRAY2) && defined(UNICOS5) char *opfrontp = pfrontp; #endif while (ncc > 0) { if ((&ptyobuf[BUFSIZ] - pfrontp) < 1) break; c = *netip++ & 0377, ncc--; #ifdef ENCRYPTION if (decrypt_input) c = (*decrypt_input)(c); #endif /* ENCRYPTION */ switch (state) { case TS_CR: state = TS_DATA; /* Strip off \n or \0 after a \r */ if ((c == 0) || (c == '\n')) { break; } /* FALL THROUGH */ case TS_DATA: if (c == IAC) { state = TS_IAC; break; } /* * We now map \r\n ==> \r for pragmatic reasons. * Many client implementations send \r\n when * the user hits the CarriageReturn key. * * We USED to map \r\n ==> \n, since \r\n says * that we want to be in column 1 of the next * printable line, and \n is the standard * unix way of saying that (\r is only good * if CRMOD is set, which it normally is). */ if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { int nc = *netip; #ifdef ENCRYPTION if (decrypt_input) nc = (*decrypt_input)(nc & 0xff); #endif /* ENCRYPTION */ #ifdef LINEMODE /* * If we are operating in linemode, * convert to local end-of-line. */ if (linemode && (ncc > 0) && (('\n' == nc) || ((0 == nc) && tty_iscrnl())) ) { netip++; ncc--; c = '\n'; } else #endif { #ifdef ENCRYPTION if (decrypt_input) (void)(*decrypt_input)(-1); #endif /* ENCRYPTION */ state = TS_CR; } } *pfrontp++ = c; break; case TS_IAC: gotiac: switch (c) { /* * Send the process on the pty side an * interrupt. Do this with a NULL or * interrupt char; depending on the tty mode. */ case IP: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); interrupt(); break; case BREAK: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); sendbrk(); break; /* * Are You There? */ case AYT: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); recv_ayt(); break; /* * Abort Output */ case AO: { DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (slctab[SLC_AO].sptr && *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { *pfrontp++ = (unsigned char)*slctab[SLC_AO].sptr; } netclear(); /* clear buffer back */ netprintf_urg("%c%c", IAC, DM); DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); break; } /* * Erase Character and * Erase Line */ case EC: case EL: { cc_t ch; DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (c == EC) ch = *slctab[SLC_EC].sptr; else ch = *slctab[SLC_EL].sptr; if (ch != (cc_t)(_POSIX_VDISABLE)) *pfrontp++ = (unsigned char)ch; break; } /* * Check for urgent data... */ case DM: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); SYNCHing = stilloob(net); settimer(gotDM); break; /* * Begin option subnegotiation... */ case SB: state = TS_SB; SB_CLEAR(); continue; case WILL: state = TS_WILL; continue; case WONT: state = TS_WONT; continue; case DO: state = TS_DO; continue; case DONT: state = TS_DONT; continue; case EOR: if (his_state_is_will(TELOPT_EOR)) doeof(); break; /* * Handle RFC 10xx Telnet linemode option additions * to command stream (EOF, SUSP, ABORT). */ case xEOF: doeof(); break; case SUSP: sendsusp(); break; case ABORT: sendbrk(); break; case IAC: *pfrontp++ = c; break; } state = TS_DATA; break; case TS_SB: if (c == IAC) { state = TS_SE; } else { SB_ACCUM(c); } break; case TS_SE: if (c != SE) { if (c != IAC) { /* * bad form of suboption negotiation. * handle it in such a way as to avoid * damage to local state. Parse * suboption buffer found so far, * then treat remaining stream as * another command sequence. */ /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(c); subpointer -= 2; SB_TERM(); suboption(); state = TS_IAC; goto gotiac; } SB_ACCUM(c); state = TS_SB; } else { /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; SB_TERM(); suboption(); /* handle sub-option */ state = TS_DATA; } break; case TS_WILL: willoption(c); state = TS_DATA; continue; case TS_WONT: wontoption(c); state = TS_DATA; continue; case TS_DO: dooption(c); state = TS_DATA; continue; case TS_DONT: dontoption(c); state = TS_DATA; continue; default: syslog(LOG_ERR, "telnetd: panic state=%d", state); printf("telnetd: panic state=%d\n", state); exit(1); } } #if defined(CRAY2) && defined(UNICOS5) if (!linemode) { char xptyobuf[BUFSIZ+NETSLOP]; char xbuf2[BUFSIZ]; register char *cp; int n = pfrontp - opfrontp, oc; memcpy(xptyobuf, opfrontp, n); pfrontp = opfrontp; pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP, xbuf2, &oc, BUFSIZ); for (cp = xbuf2; oc > 0; --oc) { if (*cp == IAC) netprintf("%c%c", *cp++, IAC); else netprintf("%c", *cp++); } } #endif /* defined(CRAY2) && defined(UNICOS5) */ } /* end of telrcv */