ckctel.c
资源名称:cku197.tar.Z [点击查看]
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:158k
源码类别:
通讯/手机编程
开发平台:
Windows_Unix
- char *cktelv = "Telnet support, 7.0.191, 30 Dec 1999";
- #define CKCTEL_C
- int sstelnet = 0; /* Do server-side Telnet negotiation */
- /* C K C T E L -- Telnet support */
- /*
- Authors:
- Telnet protocol by Frank da Cruz and Jeffrey Altman.
- Other contributions as indicated in the code.
- Copyright (C) 1985, 2000,
- Trustees of Columbia University in the City of New York.
- All rights reserved. See the C-Kermit COPYING.TXT file or the
- copyright text in the ckcmai.c module for disclaimer and permissions.
- */
- /*
- NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
- C-Kermit source files, must be compatible with C preprocessors that support
- only #ifdef, #else, #endif, #define, and #undef. Please do not use #if,
- logical operators, or other preprocessor features in this module. Also,
- don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
- */
- #include "ckcsym.h"
- #include "ckcdeb.h"
- #include "ckcker.h"
- #define TELCMDS /* to define name array */
- #define TELOPTS /* to define name array */
- #define SLC_NAMES /* to define name array */
- #define ENCRYPT_NAMES
- #define AUTH_NAMES
- #define TELOPT_STATES
- #define TELOPT_MODES
- #include "ckcnet.h"
- #include "ckctel.h"
- #ifdef CK_SSL
- #include "ck_ssl.h"
- #endif /* CK_SSL */
- #ifdef TNCODE
- #ifdef OS2 /* For terminal type name string */
- #include "ckuusr.h"
- #ifndef NT
- #include <os2.h>
- #undef COMMENT
- #endif /* NT */
- #include "ckocon.h"
- extern int tt_type, max_tt;
- extern struct tt_info_rec tt_info[];
- extern char ttname[];
- #endif /* OS2 */
- #ifdef OS2
- #include <assert.h>
- #ifdef NT
- #include <setjmpex.h>
- #else /* NT */
- #include <setjmp.h>
- #endif /* NT */
- #include <signal.h>
- #include "ckcsig.h"
- #endif /* OS2 */
- #define HEXDISP
- #ifdef CK_NAWS /* Negotiate About Window Size */
- #ifdef RLOGCODE
- _PROTOTYP( int rlog_naws, (void) );
- #endif /* RLOGCODE */
- #endif /* CK_NAWS */
- int tn_init = 0; /* Telnet protocol initialized flag */
- static int tn_first = 1; /* First time init flag */
- extern int tn_exit; /* Exit on disconnect */
- extern int inserver; /* Running as IKSD */
- char *tn_term = NULL; /* Terminal type override */
- #ifdef CK_SNDLOC
- char *tn_loc = NULL; /* Location override */
- #endif /* CK_SNDLOC */
- int tn_nlm = TNL_CRLF; /* Telnet CR -> CR LF mode */
- int tn_b_nlm = TNL_CR; /* Telnet Binary CR RAW mode */
- int tn_b_meu = 0; /* Telnet Binary ME means U too */
- int tn_b_ume = 0; /* Telnet Binary U means ME too */
- int tn_wait_flg = 1; /* Telnet Wait for Negotiations */
- int tn_infinite = 0; /* Telnet Bug Infinite-Loop-Check */
- int tn_rem_echo = 1; /* We will echo if WILL ECHO */
- int tn_b_xfer = 0; /* Telnet Binary for Xfers? */
- int tn_sb_bug = 1; /* Telnet BUG - SB w/o WILL or DO */
- int tn_no_encrypt_xfer = 0; /* Turn off Telnet Encrypt? */
- int tn_auth_how = TN_AUTH_HOW_ANY;
- int tn_auth_enc = TN_AUTH_ENC_ANY;
- int tn_deb = 0; /* Telnet Debug mode */
- #ifdef OS2
- int ttnum = -1; /* Last Telnet Terminal Type sent */
- int ttnumend = 0; /* Has end of list been found */
- #endif /* OS2 */
- #define TN_MSG_LEN 8196
- char tn_msg[TN_MSG_LEN]; /* Telnet data can be rather long */
- char hexbuf[TN_MSG_LEN];
- /*
- In order to prevent an infinite telnet negotiation loop we maintain a
- count of the number of times the same telnet negotiation message is
- sent. When this count hits MAXTNCNT, we do not send any more of the
- message. The count is stored in the tncnts[][] array.
- The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
- TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
- negotiation message types (WILL, WONT, DO, DONT). All telnet negotiations
- are kept track of in this way.
- The count for a message is zeroed when the "opposite" message is sent.
- WILL is the opposite of WONT, and DO is the opposite of DONT.
- For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
- and zeroes tncnts[TELOPT_SGA][1].
- The code that does this is in tn_sopt().
- rogersh@fsj.co.jp, 18/3/1995
- 8/16/1998 - with the recent rewrite of the telnet state machine I don't
- think this code is necessary anymore. However, it can't do any harm so
- I am leaving it in. - Jeff
- 12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
- because the Telnet option list is no longer contiguous. We also must
- allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
- for an invalid option number.
- */
- #define MAXTNCNT 4 /* Permits 4 intermediate telnet firewalls/gateways */
- char tncnts[NTELOPTS+1][4]; /* Counts */
- char tnopps[4] = { 1,0,3,2 }; /* Opposites */
- #ifdef CK_ENVIRONMENT
- #define TSBUFSIZ 1024
- char tn_env_acct[64];
- char tn_env_disp[64];
- char tn_env_job[64];
- char tn_env_prnt[64];
- char tn_env_sys[64];
- int tn_env_flg = 1;
- #else /* CK_ENVIRONMENT */
- #define TSBUFSIZ 41
- int tn_env_flg = 0;
- #endif /* CK_ENVIRONMENT */
- #ifndef NOSIGWINCH
- #ifdef CK_NAWS /* Window size business */
- #ifdef UNIX
- #include <signal.h>
- #endif /* UNIX */
- #endif /* CK_NAWS */
- #endif /* NOSIGWINCH */
- unsigned char sb[TSBUFSIZ+8]; /* Buffer for subnegotiations */
- int tn_duplex = 1; /* Local echo */
- extern char uidbuf[]; /* User ID buffer */
- extern int quiet, ttnet, ttnproto, debses, what, duplex;
- extern int seslog, sessft, whyclosed;
- #ifdef OS2
- extern int tt_rows[], tt_cols[];
- extern int tt_status;
- extern int scrninitialized[];
- #else /* OS2 */
- extern int tt_rows, tt_cols; /* Everybody has this */
- #endif /* OS2 */
- extern int cmd_cols, cmd_rows;
- extern char namecopy[];
- extern char myipaddr[]; /* Global copy of my IP address */
- int sw_armed = 0; /* SIGWINCH armed flag */
- #ifndef NOSIGWINCH
- #ifdef CK_NAWS /* Window size business */
- #ifdef SIGWINCH
- #ifdef UNIX
- SIGTYP
- winchh(foo) int foo; {
- int x = 0;
- #ifdef CK_TTYFD
- #ifndef VMS
- extern int ttyfd;
- #endif /* VMS */
- #endif /* CK_TTYFD */
- debug(F100,"SIGWINCH caught","",0);
- signal(SIGWINCH,winchh); /* Re-arm the signal */
- #ifdef CK_TTYFD
- if
- #ifdef VMS
- (vmsttyfd() == -1)
- #else
- (ttyfd == -1)
- #endif /* VMS */
- #else
- (!local)
- #endif /* CK_TTYFD */
- return;
- x = ttgwsiz(); /* Get new window size */
- /*
- This should be OK. It might seem that sending this from
- interrupt level could interfere with another TELNET IAC string
- that was in the process of being sent. But we always send
- TELNET strings with a single write(), which should prevent mixups.
- */
- if (x > 0 && tt_rows > 0 && tt_cols > 0) {
- tn_snaws();
- #ifdef RLOGCODE
- rlog_naws();
- #endif /* RLOGCODE */
- }
- return;
- }
- #endif /* UNIX */
- #endif /* SIGWINCH */
- #endif /* CK_NAWS */
- #endif /* NOSIGWINCH */
- #ifndef TELOPT_MACRO
- int
- telopt_index(opt) int opt; {
- if (opt >= 0 && opt <= TELOPT_FORWARD_X)
- return(opt);
- else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
- return(opt-89);
- else if (opt == TELOPT_IBM_SAK)
- return(opt-148);
- else
- return(NTELOPTS);
- }
- int
- telopt_ok(opt) int opt; {
- return((opt >= TELOPT_BINARY && opt <= TELOPT_FORWARD_X) ||
- (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
- (opt == TELOPT_IBM_SAK));
- }
- CHAR *
- telopt(opt) int opt; {
- if (telopt_ok(opt))
- return((CHAR *)telopts[telopt_index(opt)]);
- else
- return((CHAR *)"UNKNOWN");
- }
- int
- telopt_mode_ok(opt) int opt; {
- return((unsigned int)(opt) <= TN_NG_MU);
- }
- CHAR *
- telopt_mode(opt) int opt; {
- if (telopt_mode_ok(opt))
- return((CHAR *)telopt_modes[opt-TN_NG_RF]);
- else
- return((CHAR *)"UNKNOWN");
- }
- #endif /* TELOPT_MACRO */
- static int
- tn_outst(notquiet) int notquiet; {
- int outstanding = 0;
- int x = 0;
- #ifdef CK_ENCRYPTION
- int e = 0;
- int d = 0;
- #endif /* CK_ENCRYPTION */
- if (tn_wait_flg) {
- for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
- if (TELOPT_OK(x)) {
- if (TELOPT_UNANSWERED_WILL(x)) {
- if ( notquiet )
- printf("?Telnet waiting for response to WILL %srn",
- TELOPT(x));
- debug(F111,"tn_outst","unanswered WILL",x);
- outstanding = 1;
- if ( !notquiet )
- break;
- }
- if (TELOPT_UNANSWERED_DO(x)) {
- if ( notquiet )
- printf("?Telnet waiting for response to DO %srn",
- TELOPT(x));
- debug(F111,"tn_outst","unanswered DO",x);
- outstanding = 1;
- if ( !notquiet )
- break;
- }
- if (TELOPT_UNANSWERED_WONT(x)) {
- if ( notquiet )
- printf("?Telnet waiting for response to WONT %srn",
- TELOPT(x));
- debug(F111,"tn_outst","unanswered WONT",x);
- outstanding = 1;
- if ( !notquiet )
- break;
- }
- if (TELOPT_UNANSWERED_DONT(x)) {
- if ( notquiet )
- printf("?Telnet waiting for response to DONT %srn",
- TELOPT(x));
- debug(F111,"tn_outst","unanswered DONT",x);
- outstanding = 1;
- if ( !notquiet )
- break;
- }
- if (TELOPT_UNANSWERED_SB(x)) {
- if ( notquiet )
- printf("?Telnet waiting for response to SB %srn",
- TELOPT(x));
- debug(F111,"tn_outst","unanswered SB",x);
- outstanding = 1;
- if ( !notquiet )
- break;
- }
- }
- }
- if (!outstanding && !notquiet) {
- #ifdef CK_ENCRYPTION
- e = ck_tn_encrypting();
- d = ck_tn_decrypting();
- if (TELOPT_ME(TELOPT_ENCRYPTION)) {
- if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
- !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
- ) {
- if ( notquiet )
- printf("?Telnet waiting for WILL %s subnegotiationrn",
- TELOPT(TELOPT_ENCRYPTION));
- debug(F111,
- "tn_outst",
- "encryption mode switch",
- TELOPT_ENCRYPTION
- );
- outstanding = 1;
- }
- }
- if (TELOPT_U(TELOPT_ENCRYPTION)) {
- if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
- !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
- ) {
- if ( notquiet )
- printf("?Telnet waiting for DO %s subnegotiationrn",
- TELOPT(TELOPT_ENCRYPTION));
- debug(F111,
- "tn_outst",
- "decryption mode switch",
- TELOPT_ENCRYPTION
- );
- outstanding = 1;
- }
- }
- #endif /* CK_ENCRYPTION */
- #ifdef CK_AUTHENTICATION
- if (TELOPT_ME(TELOPT_AUTHENTICATION) &&
- ck_tn_auth_in_progress()
- ) {
- if ( notquiet )
- printf("?Telnet waiting for WILL %s subnegotiationrn",
- TELOPT(TELOPT_AUTHENTICATION));
- debug(F111,
- "tn_outst",
- "ME authentication in progress",
- TELOPT_AUTHENTICATION
- );
- outstanding = 1;
- } else if (TELOPT_U(TELOPT_AUTHENTICATION) &&
- ck_tn_auth_in_progress()
- ) {
- if ( notquiet )
- printf("?Telnet waiting for DO %s subnegotiationrn",
- TELOPT(TELOPT_AUTHENTICATION));
- debug(F111,
- "tn_outst",
- "U authentication in progress",
- TELOPT_AUTHENTICATION
- );
- outstanding = 1;
- }
- #endif /* CK_AUTHENTICATION */
- }
- } /* if (tn_wait_flg) */
- #ifdef IKS_OPTION
- /* Even if we are not waiting for Telnet options we must wait for */
- /* Kermit Telnet Subnegotiations if we have sent a request to the */
- /* other guy. Otherwise we will get out of sync. */
- if (!outstanding) {
- if (TELOPT_U(TELOPT_KERMIT) &&
- (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
- !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
- ) {
- if ( notquiet )
- printf("?Telnet waiting for DO %s subnegotiationrn",
- TELOPT(TELOPT_KERMIT));
- debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
- outstanding = 1;
- }
- }
- #endif /* IKS_OPTION */
- return(outstanding);
- }
- /* tn_wait() -- Wait for response to Telnet negotiation. */
- /*
- Wait for up to <timeout> seconds for the response to arrive.
- Place all non-telnet data into Telnet Wait Buffer.
- If response does arrive return 1, else return 0.
- */
- #ifndef TN_WAIT_BUF_SZ
- #define TN_WAIT_BUF_SZ 4096
- #endif /* TN_WAIT_BUF_SZ */
- static char tn_wait_buf[TN_WAIT_BUF_SZ];
- static int tn_wait_idx = 0;
- #ifndef TN_TIMEOUT
- #define TN_TIMEOUT 120
- #endif /* TN_TIMEOUT */
- static int tn_wait_tmo = TN_TIMEOUT;
- #ifdef CKSPINNER
- VOID
- prtwait(state) int state; {
- switch (state % 4) {
- case 0:
- printf("/");
- break;
- case 1:
- printf("-");
- break;
- case 2:
- printf("\");
- break;
- case 3:
- printf("|");
- break;
- }
- }
- #endif /* CKSPINNER */
- static int nflag = 0;
- int
- #ifdef CK_ANSIC
- tn_wait(char * where)
- #else
- tn_wait(where) char * where;
- #endif /* CK_ANSIC */
- /* tn_wait */ {
- extern int ckxech, local;
- int ch = 0, try = 0, count = 0;
- int outstanding;
- debug(F110,"tn_wait waiting for",where,0);
- tn_wait_tmo = TN_TIMEOUT;
- debug(F111,"tn_wait","timeout",tn_wait_tmo);
- outstanding = tn_outst(0);
- /* The following is meant to be !(||). We only want to return */
- /* immediately if both the tn_wait_flg && tn_outst() are false */
- if (!(outstanding || tn_wait_flg)) /* If no need to wait */
- return(1); /* Don't. */
- if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
- if (!sstelnet && !quiet) {
- #ifdef CKSPINNER
- prtwait(try);
- #endif /* CKSPINNER */
- }
- /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
- while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
- (count || ((outstanding || try == 0) && ttchk() >= 0))
- ) {
- #ifdef NTSIG
- ck_ih();
- #endif /* NTSIG */
- ch = ttinc(1);
- if (ch == -1) { /* Timed out */
- try++;
- if (!sstelnet && !quiet) { /* Let user know... */
- #ifdef CKSPINNER
- printf("b");
- prtwait(try);
- #else
- if (nflag == 0) {
- printf(" Negotiations.");
- nflag++;
- }
- if (nflag > 0) {
- printf(".");
- nflag++;
- fflush(stdout);
- }
- #endif /* CKSPINNER */
- }
- if ( try > tn_wait_tmo ) {
- if (!sstelnet) {
- printf(
- "rn?Telnet Protocol Timeout - connection closedrn");
- if (tn_deb || debses)
- tn_debug(
- "<telnet protocol timeout - connection closed>");
- tn_outst(1);
- }
- /* if we do not close the connection, then we will block */
- /* the next time we hit a wait. and if we don't we will */
- /* do the wrong thing if the host sends 0xFF and does */
- /* not intend it to be an IAC. */
- ttclos(0);
- whyclosed = WC_TELOPT;
- return(-1);
- }
- continue;
- } else if (ch < -1) {
- printf("rn?Connection closed by peer.rn");
- if (tn_deb || debses) tn_debug("<connection closed by peer>");
- return(-1);
- }
- switch (ch) {
- case IAC:
- #ifdef CKSPINNER
- if (!sstelnet && !quiet)
- printf("b");
- #endif /* CKSPINNER */
- ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
- #ifdef CKSPINNER
- if (!sstelnet && !quiet)
- prtwait(try);
- #endif /* CKSPINNER */
- debug(F101,"tn_wait tn_doop","",ch);
- switch (ch) {
- case 1:
- duplex = 1; /* Turn on echoing */
- if (inserver)
- ckxech = 1;
- break;
- case 2:
- duplex = 0; /* Turn off echoing */
- if (inserver)
- ckxech = 0;
- break;
- case 3:
- tn_wait_buf[tn_wait_idx++] = IAC;
- break;
- case 4: /* IKS event */
- case 6: /* Logout */
- break;
- case -1:
- printf("?Telnet Option negotiation error.n");
- if (tn_deb || debses)
- tn_debug("<Telnet Option negotiation error>");
- return(-1);
- case -2:
- printf("?Connection closed by peer.n");
- if (tn_deb || debses) tn_debug("<Connection closed by peer>");
- return(-2);
- default:
- if (ch < 0) {
- if (tn_deb || debses) tn_debug("<Unknown connection error>");
- return(ch);
- }
- } /* switch */
- break;
- default:
- tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
- } /* switch */
- outstanding = tn_outst(0);
- count = ttchk();
- if (!try)
- try++;
- } /* while */
- if (tn_wait_idx == TN_WAIT_BUF_SZ) {
- if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
- return(0);
- }
- if (!sstelnet && !quiet) {
- #ifdef CKSPINNER
- printf("b b");
- #else
- if (nflag > 0) {
- printf(" (OK)n");
- nflag = -1;
- }
- #endif /* CKSPINNER */
- }
- if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
- return(0);
- }
- /* Push data from the Telnet Wait Buffer into the I/O Queue */
- /* Return 1 on success */
- int
- tn_push() {
- #ifdef NETLEBUF
- extern int tt_push_inited;
- #endif /* NETLEBUF */
- if (tn_wait_idx) {
- hexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
- #ifdef NETLEBUF
- if (!tt_push_inited) /* Local handling */
- le_init();
- le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
- #else /* External handling... */
- #ifdef OS2 /* K95 has its own way */
- le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
- #else
- #ifdef TTLEBUF /* UNIX, etc */
- le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
- #else
- /*
- If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
- the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
- places in your ck?tio.c module.
- */
- printf("tn_push called but not implemented - data lost.n");
- #endif /* NETLEBUF */
- #endif /* UNIX */
- #endif /* OS2 */
- tn_wait_idx = 0;
- }
- tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
- return(1);
- }
- /* T N _ S O P T */
- /*
- Sends a telnet option, avoids loops.
- Returns 1 if command was sent, 0 if not, -1 on error.
- */
- int
- tn_sopt(cmd,opt) int cmd, opt; { /* TELNET SEND OPTION */
- CHAR buf[5];
- if (ttnet != NET_TCPB) return(-1); /* Must be TCP/IP */
- if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
- if (!TELCMD_OK(cmd)) return(-1);
- if (TELOPT_OK(opt)) {
- if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
- if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
- if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
- if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
- }
- #ifdef CK_SSL
- if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
- return(0);
- }
- #endif /* CK_SSL */
- if (cmd == DO && opt == TELOPT_AUTHENTICATION)
- buf[0] = 0;
- if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about */
- int index = TELOPT_INDEX(opt); /* preventing infinite loops */
- int m = cmd - WILL;
- if (tncnts[index][m] > MAXTNCNT) {
- if (tn_deb || debses || deblog) {
- sprintf(tn_msg,"TELNET negotiation loop %s %s",
- TELCMD(cmd),
- TELOPT(opt));
- debug(F101,tn_msg,"",opt);
- if (tn_deb || debses) tn_debug(tn_msg);
- }
- return(0);
- }
- tncnts[index][m]++;
- tncnts[index][tnopps[m]] = 0;
- }
- buf[0] = (CHAR) IAC;
- buf[1] = (CHAR) (cmd & 0xff);
- buf[2] = (CHAR) (opt & 0xff);
- buf[3] = (CHAR) 0;
- if ((tn_deb || debses || deblog) && cmd != SB) {
- sprintf(tn_msg,"TELNET SENT %s %s",TELCMD(cmd),
- TELOPT(opt));
- debug(F101,tn_msg,"",opt);
- }
- if (ttol(buf,3) < 3) {
- return(-1);
- }
- /* Only display the command if it was actually sent. */
- if ((tn_deb || debses) && cmd != SB) tn_debug(tn_msg);
- if (TELOPT_OK(opt)) {
- if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
- TELOPT_UNANSWERED_DO(opt) = 0;
- if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
- TELOPT_UNANSWERED_WILL(opt) = 0;
- if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
- TELOPT_UNANSWERED_DONT(opt) = 0;
- if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
- TELOPT_UNANSWERED_WONT(opt) = 0;
- }
- return(1);
- }
- /* Send a telnet sub-option */
- /* Returns 1 if command was sent, 0 if not, -1 on error */
- int
- tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
- CHAR buf[256];
- int n,m;
- if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
- if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
- if (!TELOPT_OK(opt)) return(-1);
- if (len < 0 || len > 250) {
- debug(F111,"Unable to Send TELNET SB - data too long","len",len);
- return(-1); /* Data too long */
- }
- #ifdef CK_SSL
- if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
- if (ttchk() < 0)
- return(-1);
- else
- return(1);
- }
- #endif /* CK_SSL */
- if (!data) len = 0;
- buf[0] = (CHAR) IAC;
- buf[1] = (CHAR) (SB & 0xff);
- buf[2] = (CHAR) (opt & 0xff);
- buf[3] = (CHAR) (sub & 0xff);
- if (data && len > 0) {
- memcpy(&buf[4],data,len);
- }
- buf[4+len] = (CHAR) IAC;
- buf[5+len] = (CHAR) SE;
- if (tn_deb || debses || deblog) {
- if (opt == TELOPT_START_TLS && sub == 1)
- sprintf(tn_msg,"TELNET SENT SB %s FOLLOWS IAC SE",
- TELOPT(opt)
- );
- else if (opt == TELOPT_TTYPE && sub == 1)
- sprintf(tn_msg,"TELNET SENT SB %s SEND IAC SE", TELOPT(opt));
- else if (opt == TELOPT_TTYPE && sub == 0)
- sprintf(tn_msg,"TELNET SENT SB %s IS %s IAC SE", TELOPT(opt),data);
- else if (opt == TELOPT_NEWENVIRON) {
- int i, quote;
- sprintf(tn_msg,"TELNET SENT SB %s %s",
- TELOPT(TELOPT_NEWENVIRON),
- sub == TELQUAL_SEND ? "SEND" :
- sub == TELQUAL_IS ? "IS" :
- sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
- for (i = 0, quote = 0; i < len; i++) {
- if (quote) {
- sprintf(hexbuf,"%02x",data[i]);
- strcat(tn_msg,hexbuf);
- quote = 0;
- } else {
- switch (data[i]) {
- case TEL_ENV_USERVAR:
- strcat(tn_msg," USERVAR ");
- break;
- case TEL_ENV_VAR:
- strcat(tn_msg," VAR ");
- break;
- case TEL_ENV_VALUE:
- strcat(tn_msg," VALUE ");
- break;
- case TEL_ENV_ESC:
- strcat(tn_msg," ESC ");
- quote = 1;
- break;
- case IAC:
- strcat(tn_msg," IAC ");
- break;
- default:
- sprintf(hexbuf,"%c",data[i]);
- strcat(tn_msg,hexbuf);
- }
- }
- }
- strcat(tn_msg," IAC SE");
- } else
- sprintf(tn_msg,
- "TELNET SENT SB %s %02x <data> IAC SE",
- TELOPT(opt),
- sub
- );
- debug(F101,tn_msg,"",opt);
- if (tn_deb || debses) tn_debug(tn_msg);
- }
- if (ttol(buf,6+len) < 6+len)
- return(-1);
- return(1);
- }
- /*
- tn_flui() -- Processes all waiting data for Telnet commands.
- All non-Telnet data is to be stored into the Telnet Wait Buffer.
- Returns 1 on success.
- */
- int
- tn_flui() {
- extern int ckxech;
- int x = 0;
- /* Wait up to 5 sec for responses to outstanding telnet negotiations */
- while (x >= 0 && ttchk() > 0 && tn_wait_idx < TN_WAIT_BUF_SZ) {
- x = ttinc(1);
- switch (x) {
- case IAC:
- x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
- debug(F101,"tn_flui tn_doop","",x);
- switch (x) {
- case 1: /* Turn on echoing */
- duplex = 1;
- if (inserver)
- ckxech = 1;
- break;
- case 2: /* Turn off echoing */
- duplex = 0;
- if (inserver)
- ckxech = 0;
- break;
- case 3:
- tn_wait_buf[tn_wait_idx++] = IAC;
- break;
- case 4: /* IKS event */
- case 6: /* Logout */
- break;
- }
- break;
- default:
- if (x >= 0)
- tn_wait_buf[tn_wait_idx++] = x;
- }
- }
- return(1);
- }
- #ifdef CK_FORWARD_X
- int
- #ifdef CK_ANSIC
- fwdx_tn_sb( unsigned char * sb, int n )
- #else
- fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
- #endif /* CK_ANSIC */
- {
- unsigned short hchannel, nchannel;
- unsigned char * p;
- int rc = -1;
- /* as a security precaution should add a test here to check to make sure */
- /* we have negotiated FORWARD_X with the peer. */
- switch (sb[0]) {
- case FWDX_SCREEN:
- if (sstelnet && n == 4)
- rc = fwdx_create_listen_socket(sb[1]);
- break;
- case FWDX_OPEN:
- if ( !sstelnet && n == 5 ) {
- p = (unsigned char *) &nchannel;
- p[0] = sb[1];
- p[1] = sb[2];
- hchannel = ntohs(nchannel);
- rc = fwdx_open_client_channel(hchannel);
- if ( rc < 0 ) {
- /* Failed; Send CLOSE channel */
- fwdx_send_close(hchannel);
- }
- #ifdef NT
- if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
- ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
- }
- #endif /* NT */
- }
- break;
- case FWDX_CLOSE:
- p = (unsigned char *) &nchannel;
- p[0] = sb[1];
- p[1] = sb[2];
- hchannel = ntohs(nchannel);
- rc = fwdx_close_channel(hchannel);
- break;
- case FWDX_DATA:
- p = (unsigned char *) &nchannel;
- p[0] = sb[1];
- p[1] = sb[2];
- hchannel = ntohs(nchannel);
- rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3],n-5);
- break;
- }
- if ( rc < 0 ) {
- if ( sstelnet ) {
- if (tn_sopt(WONT,TELOPT_FORWARD_X) < 0)
- return(-1);
- TELOPT_UNANSWERED_WONT(TELOPT_FORWARD_X) = 1;
- return(-1);
- } else {
- if (tn_sopt(DONT,TELOPT_FORWARD_X) < 0)
- return(-1);
- TELOPT_UNANSWERED_DONT(TELOPT_FORWARD_X) = 1;
- return(-1);
- }
- }
- return(0);
- }
- int
- fwdx_send_close(channel) int channel; {
- int nchannel;
- CHAR * p;
- nchannel = htons(channel);
- p = (unsigned char *) &nchannel;
- sb[0] = (CHAR) IAC; /* I Am a Command */
- sb[1] = (CHAR) SB; /* Subnegotiation */
- sb[2] = TELOPT_FORWARD_X; /* Forward X */
- sb[3] = FWDX_CLOSE; /* Open */
- sb[4] = p[0];
- sb[5] = p[1];
- sb[6] = (CHAR) IAC; /* End of Subnegotiation */
- sb[7] = (CHAR) SE; /* marked by IAC SE */
- if (ttol((CHAR *)sb,8) < 0) { /* Send it. */
- return(-1);
- }
- #ifdef DEBUG
- if (deblog || tn_deb || debses) {
- sprintf(tn_msg,"TELNET SENT SB %s CLOSE %02x %02x IAC SE",
- TELOPT(TELOPT_FORWARD_X),p[0],p[1]);
- debug(F100,tn_msg,"",0);
- if (tn_deb || debses) tn_debug(tn_msg);
- }
- #endif /* DEBUG */
- return(0);
- }
- int
- fwdx_send_open(channel) int channel; {
- int nchannel;
- CHAR * p;
- nchannel = htons(channel);
- p = (unsigned char *) &nchannel;
- sb[0] = (CHAR) IAC; /* I Am a Command */
- sb[1] = (CHAR) SB; /* Subnegotiation */
- sb[2] = TELOPT_FORWARD_X; /* Forward X */
- sb[3] = FWDX_OPEN; /* Open */
- sb[4] = p[0];
- sb[5] = p[1];
- sb[6] = (CHAR) IAC; /* End of Subnegotiation */
- sb[7] = (CHAR) SE; /* marked by IAC SE */
- if (ttol((CHAR *)sb,8) < 0) { /* Send it. */
- return(-1);
- }
- #ifdef DEBUG
- if (deblog || tn_deb || debses) {
- sprintf(tn_msg,"TELNET SENT SB %s OPEN %02x %02x IAC SE",
- TELOPT(TELOPT_FORWARD_X),p[0],p[1]);
- debug(F100,tn_msg,"",0);
- if (tn_deb || debses) tn_debug(tn_msg);
- }
- #endif /* DEBUG */
- return(0);
- }
- #endif /* CK_FORWARD_X */
- #ifdef IKS_OPTION
- /*
- iks_wait() -- Wait for an IKS subnegotiation response.
- sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
- state of the peer's Kermit server.
- flushok - specifies whether it is ok to throw away non-Telnet data
- if so, then we call ttflui() instead of tn_flui().
- Returns:
- 1 if the desired state is achieved or if it is unknown.
- 0 if the desired state is not achieved.
- */
- int
- #ifdef CK_ANSIC
- iks_wait(int sb, int flushok)
- #else /* CK_ANSIC */
- iks_wait(sb,flushok) int sb; int flushok;
- #endif /* CK_ANSIC */
- {
- int tn_wait_save = tn_wait_flg;
- int x;
- if (TELOPT_U(TELOPT_KERMIT)) {
- switch (sb) {
- case KERMIT_REQ_START:
- debug(F111,
- "iks_wait KERMIT_REQ_START",
- "u_start",
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start
- );
- tn_siks(KERMIT_REQ_START);
- tn_wait_flg = 1; /* Kermit Option MUST wait */
- do {
- if (flushok)
- tn_wait_idx = 0;
- x = tn_wait("iks_wait() me_iks_req_start");
- } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
- tn_wait_flg = tn_wait_save;
- if (flushok)
- tn_wait_idx = 0;
- if (tn_wait_idx == TN_WAIT_BUF_SZ) {
- /*
- * We are attempting to start a kermit server on the peer
- * the most likely reason is because we want to perform a
- * file transfer. But there is a huge amount of non telnet
- * negotiation data coming in and so we have not been able
- * to find the response. So we will lie and assume that
- * response is 'yes'. The worse that will happen is that
- * a RESP_STOP is received after we enter protocol mode.
- * And the protocol operation will be canceled.
- */
- tn_push();
- return(1);
- } else {
- tn_push();
- return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
- }
- case KERMIT_REQ_STOP:
- debug(F111,
- "iks_wait KERMIT_REQ_STOP",
- "u_start",
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start
- );
- tn_siks(KERMIT_REQ_STOP);
- tn_wait_flg = 1; /* Kermit Option MUST wait */
- do {
- if (flushok)
- tn_wait_idx = 0;
- x = tn_wait("iks_wait() me_iks_req_stop");
- } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
- tn_wait_flg = tn_wait_save;
- if (flushok)
- tn_wait_idx = 0;
- if (tn_wait_idx == TN_WAIT_BUF_SZ) {
- /*
- * We are attempting to stop a kermit server on the peer
- * the most likely reason being that we want to enter
- * CONNECT mode. But there is a huge amount of non telnet
- * negotiation data coming in and so we have not been able
- * to find the response. So we will lie and assume that
- * the answer is 'yes' and allow the CONNECT command to
- * succeed. The worst that happens is that CONNECT mode
- * swallows the incoming data displaying it to the user
- * and then it resumes Kermit client mode.
- */
- tn_push();
- return(1);
- } else {
- tn_push();
- return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
- }
- }
- tn_push();
- }
- return(1);
- }
- int
- #ifdef CK_ANSIC
- iks_tn_sb( char * sb, int n )
- #else
- iks_tn_sb( sb, n ) char * sb; int n;
- #endif /* CK_ANSIC */
- {
- #ifndef NOXFER
- extern int server;
- #ifdef NOICP
- extern int autodl;
- int inautodl = 0, cmdadl = 1;
- extern int local;
- #else
- #ifdef CK_AUTODL
- extern int autodl, inautodl, cmdadl;
- extern int local;
- #endif /* CK_AUTODL */
- #endif /* NOICP */
- switch (sb[0]) {
- case KERMIT_START: /* START */
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
- return(4);
- case KERMIT_STOP: /* STOP */
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
- return(4);
- case KERMIT_REQ_START: /* REQ-START */
- if (inserver) {
- #ifdef CK_AUTODL
- cmdadl = 1; /* Turn on packet detection */
- #endif /* CK_AUTODL */
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
- tn_siks(KERMIT_RESP_START);
- } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
- tn_siks(KERMIT_RESP_START);
- } else {
- #ifdef CK_AUTODL
- if ((local && what == W_CONNECT && autodl) ||
- (local && what != W_CONNECT && inautodl)
- )
- tn_siks(KERMIT_RESP_START); /* STOP */
- else
- #endif /* CK_AUTODL */
- tn_siks(KERMIT_RESP_STOP);
- }
- return(4);
- case KERMIT_REQ_STOP: /* REQ-STOP */
- /* The protocol requires that the request be responded to */
- /* either by changing states or by reporting the current */
- /* state. */
- /* We need to provide the user some way of dictating what */
- /* the policies should be. For instance, if we are in */
- /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
- /* what should the proper response be? */
- if (inserver
- #ifdef CK_AUTODL
- || !local && cmdadl
- #endif /* CK_AUTODL */
- ) {
- #ifdef CK_AUTODL
- cmdadl = 0; /* Turn off packet detection */
- #endif /* CK_AUTODL */
- tn_siks(KERMIT_RESP_STOP);
- } else if (server) {
- extern int en_fin;
- if (en_fin) { /* If the server is allowed to stop */
- tn_siks(KERMIT_RESP_STOP);
- } else { /* We are not allowed to stop */
- tn_siks(KERMIT_RESP_START);
- }
- #ifdef CK_AUTODL
- } else if ((local && what == W_CONNECT && autodl) ||
- (local && what != W_CONNECT && inautodl)
- ) {
- /* If we are a pseudo-server and the other side requests */
- /* that we stop, tell then that we have even though we */
- /* have not. Otherwise, the other side might refuse to */
- /* enter SERVER mode. */
- tn_siks(KERMIT_RESP_STOP); /* STOP */
- #endif /* CK_AUTODL */
- } else {
- /* If we are not currently in any mode that accepts */
- /* Kermit packets then of course report that we are */
- /* not being a Kermit server. */
- tn_siks(KERMIT_RESP_STOP); /* STOP */
- }
- return(4);
- case KERMIT_SOP: { /* SOP */
- extern CHAR stchr; /* Incoming SOP character */
- stchr = sb[1];
- TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
- return(4);
- }
- case KERMIT_RESP_START: /* START */
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
- if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
- } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
- /* If we have issued a request to stop a Kermit Server */
- /* and the response is Start, then we must report this */
- /* to the caller. */
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
- }
- return(4);
- case KERMIT_RESP_STOP: /* STOP */
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
- if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
- /* If we have issued a request to start a Kermit Server */
- /* and the response is Stop, then we must report this */
- /* to the caller. */
- } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
- }
- return(4);
- default:
- return(0);
- } /* switch (sb[0]) */
- #else
- return(0);
- #endif /* NOXFER */
- }
- #endif /* IKS_OPTION */
- /* Initialize telnet settings - set default values for ME and U modes */
- int
- tn_set_modes() {
- int opt,cmd;
- /* initialize all options to refuse in both directions */
- for (opt = 0; opt < NTELOPTS; opt++) {
- TELOPT_ME(opt) = 0;
- TELOPT_U(opt) = 0;
- TELOPT_UNANSWERED_WILL(opt) = 0;
- TELOPT_UNANSWERED_DO(opt) = 0;
- TELOPT_UNANSWERED_WONT(opt) = 0;
- TELOPT_UNANSWERED_DONT(opt) = 0;
- TELOPT_UNANSWERED_SB(opt) = 0;
- TELOPT_ME_MODE(opt) = TN_NG_RF;
- TELOPT_U_MODE(opt) = TN_NG_RF;
- TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
- TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
- TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
- TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
- for (cmd = 0; cmd < 4; cmd ++)
- tncnts[TELOPT_INDEX(opt)][cmd] = 0;
- }
- #ifdef IKS_OPTION
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
- #endif /* IKS_OPTION */
- #ifdef CK_ENCRYPTION
- TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
- #endif /* CK_ENCRYPTION */
- #ifdef CK_NAWS
- TELOPT_SB(TELOPT_NAWS).naws.x = 0;
- TELOPT_SB(TELOPT_NAWS).naws.y = 0;
- #endif /* CK_NAWS */
- #ifdef CK_SSL
- TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
- TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
- #endif /* CK_SSL */
- /* Now set the ones we want to accept to the proper values */
- TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
- TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
- TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
- TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
- TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
- TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
- TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
- TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
- TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
- TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
- TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
- TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
- #ifdef IKS_OPTION
- TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
- TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
- TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
- TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
- #endif /* IKS_OPTION */
- #ifdef CK_ENCRYPTION
- TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
- TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
- TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
- TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
- #endif /* CK_ENCRYPTION */
- TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
- TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
- #ifdef CK_ENVIRONMENT
- TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_AUTHENTICATION
- TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
- #endif /* CK_AUTHENTICATION */
- #ifdef CK_SSL
- if (ck_ssleay_is_installed()) {
- TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
- TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
- }
- #endif /* CK_SSL */
- #ifdef CK_NAWS
- TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
- #endif /* CK_NAWS */
- TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
- TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
- #ifdef CK_ENVIRONMENT
- TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_AUTHENTICATION
- TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
- #endif /* CK_AUTHENTICATION */
- #ifdef CK_NAWS
- TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
- #endif /* CK_NAWS */
- #ifdef CK_SNDLOC
- TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
- #endif /* CK_SNDLOC */
- #ifdef CK_FORWARD_X
- TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_RQ;
- #endif /* CK_FORWARD_X */
- /* Set the initial values for currently known mode */
- for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
- if (TELOPT_OK(opt)) {
- TELOPT_ME_MODE(opt) = sstelnet ?
- TELOPT_DEF_S_ME_MODE(opt) :
- TELOPT_DEF_C_ME_MODE(opt);
- TELOPT_U_MODE(opt) = sstelnet ?
- TELOPT_DEF_S_U_MODE(opt) :
- TELOPT_DEF_C_U_MODE(opt);
- }
- }
- return(1);
- }
- /* Send Delayed Subnegotiations */
- VOID
- tn_sdsb() {
- if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
- tn_sttyp();
- TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
- }
- #ifdef CK_ENVIRONMENT
- if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
- TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
- tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
- TELOPT_SB(TELOPT_NEWENVIRON).env.len);
- free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
- TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
- TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
- TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
- }
- #ifdef CK_XDISPLOC
- if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
- tn_sxdisploc();
- TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
- }
- #endif /* CK_XDISPLOC */
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_NAWS
- if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
- tn_snaws();
- TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
- }
- #endif /* CK_NAWS */
- #ifdef CK_SNDLOC
- if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
- tn_sndloc();
- TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
- }
- #endif /* CK_SNDLOC */
- #ifdef CK_FORWARD_X
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
- tn_sndfwdx();
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
- }
- #endif /* CK_FORWARD_X */
- }
- int
- tn_reset() {
- int x,opt,cmd;
- tn_wait_idx = 0; /* Clear the tn_push() buffer */
- tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
- nflag = 0;
- /* Reset the TELNET OPTIONS counts */
- for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
- if (TELOPT_OK(opt)) {
- TELOPT_ME(opt) = 0;
- TELOPT_U(opt) = 0;
- TELOPT_UNANSWERED_WILL(opt) = 0;
- TELOPT_UNANSWERED_DO(opt) = 0;
- TELOPT_UNANSWERED_WONT(opt) = 0;
- TELOPT_UNANSWERED_DONT(opt) = 0;
- TELOPT_UNANSWERED_SB(opt) = 0;
- TELOPT_ME_MODE(opt) = sstelnet ?
- TELOPT_DEF_S_ME_MODE(opt) :
- TELOPT_DEF_C_ME_MODE(opt);
- TELOPT_U_MODE(opt) = sstelnet ?
- TELOPT_DEF_S_U_MODE(opt) :
- TELOPT_DEF_C_U_MODE(opt);
- #ifdef DEBUG
- if (deblog) {
- switch (TELOPT_ME_MODE(opt)) {
- case TN_NG_RF:
- debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
- break;
- case TN_NG_AC:
- debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
- break;
- case TN_NG_RQ:
- debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
- break;
- case TN_NG_MU:
- debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
- break;
- }
- switch (TELOPT_U_MODE(opt)) {
- case TN_NG_RF:
- debug(F110,"tn_ini U REFUSE ",TELOPT(opt),0);
- break;
- case TN_NG_AC:
- debug(F110,"tn_ini U ACCEPT ",TELOPT(opt),0);
- break;
- case TN_NG_RQ:
- debug(F110,"tn_ini U REQUEST",TELOPT(opt),0);
- break;
- case TN_NG_MU:
- debug(F110,"tn_ini U REQUIRE",TELOPT(opt),0);
- break;
- }
- }
- #endif /* DEBUG */
- for (cmd = 0; cmd < 4; cmd ++)
- tncnts[TELOPT_INDEX(opt)][cmd] = 0;
- }
- }
- #ifdef CK_ENVIRONMENT
- if (!tn_env_flg) {
- TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
- TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
- }
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_SNDLOC
- if (!tn_loc)
- TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
- #endif /* CK_SNDLOC */
- #ifdef IKS_OPTION
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
- TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
- #endif /* IKS_OPTION */
- #ifdef CK_ENCRYPTION
- TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
- TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
- #endif /* CK_ENCRYPTION */
- #ifdef CK_NAWS
- TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
- TELOPT_SB(TELOPT_NAWS).naws.x = 0;
- TELOPT_SB(TELOPT_NAWS).naws.y = 0;
- #endif /* CK_NAWS */
- TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
- TELOPT_SB(TELOPT_TTYPE).term.type[0] = ' ';
- #ifdef CK_ENVIRONMENT
- TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
- if (tn_first)
- TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
- else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
- free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
- TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
- }
- TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
- #ifdef CK_XDISPLOC
- TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
- #endif /* CK_XDISPLOC */
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_SNDLOC
- TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
- #endif /* CK_SNDLOC */
- #ifdef CK_FORWARD_X
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
- if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1 ) {
- }
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
- for ( x=0 ; x<MAXFWDX ; x++ ) {
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
- }
- #ifdef NT
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
- #endif /* NT */
- #endif /* CK_FORWARD_X */
- #ifdef CK_SSL
- if (tls_only_flag || ssl_only_flag) {
- TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
- TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
- }
- TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
- TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
- #endif /* CK_SSL */
- #ifdef CK_ENCRYPTION
- if (!ck_crypt_is_installed()
- #ifdef CK_SSL
- || tls_only_flag || ssl_only_flag
- #endif /* CK_SSL */
- ) {
- TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
- TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
- }
- #endif /* CK_ENCRYPTION */
- tn_first = 0; /* No longer the first time init */
- #ifdef OS2
- ttnum = -1; /* Reset TermType negotiation */
- ttnumend = 0;
- #endif /* OS2 */
- return(0);
- }
- /* Start a telnet connection. */
- /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
- int
- tn_ini() {
- int wait, x, opt;
- debug(F101,"tn_ini ttnproto","",ttnproto);
- debug(F101,"tn_ini tn_init","",tn_init);
- if (ttnet != NET_TCPB) /* Make sure connection is TCP/IP */
- return(0);
- if (tn_init) /* Have we done this already? */
- return(0); /* Don't do it again. */
- tn_reset(); /* Reset telnet parameters */
- if (ttnproto == NP_RLOGIN) { /* Reset flags even when RLOGIN */
- tn_init = 1;
- return(0);
- } else if (ttnproto == NP_NONE) { /* If not talking to a telnet port, */
- ttnproto = NP_TELNET; /* pretend it's telnet anyway, */
- tn_init = 1; /* but don't send initial options. */
- debug(F100,"tn_ini skipping telnet negotiations","",0);
- return(0);
- } else if (ttnproto == NP_TCPRAW) { /* Raw socket requested. */
- return(0);
- } else if (ttnproto == NP_KERMIT) {
- /* switching to Telnet protocol */
- debug(F100,"tn_start switching from Kermit to Telnet","",0);
- ttnproto = NP_TELNET;
- }
- debug(F111,"tn_start","sstelnet",sstelnet);
- wait = 0;
- #ifdef CK_SSL
- if (!TELOPT_ME(TELOPT_START_TLS) &&
- TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
- wait = 1;
- }
- if (!TELOPT_U(TELOPT_START_TLS) &&
- TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_START_TLS) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
- wait = 1;
- }
- #ifdef COMMENT
- /*
- We can put off waiting for this until after we have requested AUTH. The
- next draft will specify how the WILL side is to decide between these
- conflicting options.
- */
- if (wait) {
- if (tn_wait("start_tls") < 0) {
- tn_push();
- return(-1);
- }
- wait = 0;
- }
- #endif /* COMMENT */
- #endif /* CK_SSL */
- #ifdef CK_AUTHENTICATION
- if (tn_init) /* tn_ini() might be called recursively */
- return(0);
- if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
- TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
- wait = 1;
- }
- if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
- TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
- wait = 1;
- }
- #ifdef CK_ENCRYPTION
- if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
- TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
- TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
- TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
- }
- #endif /* CK_ENCRYPTION */
- #endif /* CK_AUTHENTICATION */
- #ifdef CK_NAWS
- if (!sstelnet) {
- /* Console terminal screen rows and columns */
- #ifdef OS2
- debug(F101,
- "tn_ini tt_rows 1",
- "",
- VscrnGetHeight(VTERM)-(tt_status?1:0)
- );
- debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
- /* Not known yet */
- if (VscrnGetWidth(VTERM) < 0 ||
- VscrnGetHeight(VTERM)-(tt_status?1:0) < 0) {
- ttgwsiz(); /* Try to find out */
- }
- debug(F101,
- "tn_ini tt_rows 2",
- "",
- VscrnGetHeight(VTERM)-(tt_status?1:0)
- );
- debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
- /* Now do we know? */
- if (VscrnGetWidth(VTERM) > 0 &&
- VscrnGetHeight(VTERM)-(tt_status?1:0) > 0) {
- if (!TELOPT_ME(TELOPT_NAWS) &&
- TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_NAWS) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
- wait = 1;
- }
- }
- #else /* OS2 */
- debug(F101,"tn_ini tt_rows 1","",tt_rows);
- debug(F101,"tn_ini tt_cols 1","",tt_cols);
- if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
- ttgwsiz(); /* Try to find out */
- }
- debug(F101,"tn_ini tt_rows 2","",tt_rows);
- debug(F101,"tn_ini tt_cols 2","",tt_cols);
- if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
- if (!TELOPT_ME(TELOPT_NAWS) &&
- TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_NAWS) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
- wait = 1;
- }
- }
- #endif /* OS2 */
- } else {
- if (!TELOPT_U(TELOPT_NAWS) &&
- TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_NAWS) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
- wait = 1;
- }
- }
- #endif /* CK_NAWS */
- if (!TELOPT_ME(TELOPT_SGA) &&
- TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_SGA) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
- wait = 1;
- }
- if (!TELOPT_U(TELOPT_SGA) &&
- TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_SGA) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
- wait = 1;
- }
- if (!tn_duplex) {
- if (!TELOPT_U(TELOPT_ECHO) &&
- TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_ECHO) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
- wait = 1;
- }
- }
- if (!TELOPT_ME(TELOPT_ECHO) &&
- TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_ECHO) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
- wait = 1;
- }
- debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
- /*
- Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
- Also send WILL NAWS if we know our screen dimensions.
- */
- if (!TELOPT_ME(TELOPT_TTYPE) &&
- TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
- if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
- debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
- return(-1);
- }
- TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
- wait = 1;
- debug(F100,"tn_ini sent WILL TTYPE ok","",0);
- }
- if (!TELOPT_U(TELOPT_TTYPE) &&
- TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
- if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
- debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
- return(-1);
- }
- TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
- wait = 1;
- debug(F100,"tn_ini sent DO TTYPE ok","",0);
- }
- if (!TELOPT_ME(TELOPT_BINARY) &&
- TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_BINARY) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
- wait = 1;
- }
- if (!TELOPT_U(TELOPT_BINARY) &&
- TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_BINARY) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
- wait = 1;
- }
- #ifdef CK_SNDLOC
- if (tn_loc) {
- if (!TELOPT_ME(TELOPT_SNDLOC) &&
- TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
- wait = 1;
- }
- }
- #endif /* CK_SNDLOC */
- #ifdef CK_ENVIRONMENT
- #ifdef CK_XDISPLOC
- if (!TELOPT_ME(TELOPT_XDISPLOC) &&
- TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
- wait = 1;
- }
- #endif /* CK_XDISPLOC */
- /* Will send terminal environment. */
- if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
- TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
- wait = 1;
- }
- if (!TELOPT_U(TELOPT_NEWENVIRON) &&
- TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
- wait = 1;
- }
- #endif /* CK_ENVIRONMENT */
- /* Take care of any other telnet options that require handling. */
- for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
- switch (opt) {
- case TELOPT_AUTHENTICATION:
- case TELOPT_ENCRYPTION:
- case TELOPT_TTYPE:
- case TELOPT_NAWS:
- case TELOPT_BINARY:
- case TELOPT_NEWENVIRON:
- case TELOPT_SNDLOC:
- case TELOPT_XDISPLOC:
- case TELOPT_SGA:
- case TELOPT_ECHO:
- case TELOPT_KERMIT:
- case TELOPT_START_TLS:
- break;
- default:
- if (TELOPT_OK(opt)) {
- if (!TELOPT_ME(opt) &&
- TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
- if (tn_sopt(WILL, opt) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(opt) = 1;
- wait = 1;
- }
- if (!TELOPT_U(opt) &&
- TELOPT_U_MODE(opt) >= TN_NG_RQ) {
- if (tn_sopt(DO, opt) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(opt) = 1;
- wait = 1;
- }
- }
- }
- }
- if (wait) {
- if (tn_wait("pre-encrypt") < 0) {
- tn_push();
- return(-1);
- }
- wait = 0;
- }
- #ifdef CK_ENCRYPTION
- if (tn_init) /* tn_ini() may be called recursively */
- return(0);
- if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
- TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
- wait = 1;
- }
- if (!TELOPT_U(TELOPT_ENCRYPTION) &&
- TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
- wait = 1;
- }
- /* If we are going to encrypt, we want to do it before we send any more */
- /* data, especially the terminal type and environment variables. */
- if (wait) {
- if (tn_wait("post-encrypt") < 0) {
- tn_push();
- return(-1);
- }
- wait = 0;
- }
- #endif /* CK_ENCRYPTION */
- tn_sdsb();
- if (tn_init) /* tn_ini() may be called recursively */
- return(0);
- #ifdef IKS_OPTION
- /* Kermit Server negotiation must go last */
- /* Send U before ME */
- if (!TELOPT_U(TELOPT_KERMIT) &&
- TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
- if (tn_sopt(DO, TELOPT_KERMIT) < 0)
- return(-1);
- TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
- wait = 1;
- }
- if (!TELOPT_ME(TELOPT_KERMIT) &&
- TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
- if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
- return(-1);
- TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
- wait = 1;
- }
- #endif /* IKS_OPTION */
- if (wait) {
- if (tn_wait("end of telnet negotiations") < 0) {
- tn_push();
- return(-1);
- }
- wait = 0;
- }
- tn_sdsb(); /* Send delayed subnegotiations */
- tn_push();
- tn_init = 1; /* Remember successful completion. */
- /* Don't send anything else! */
- debug(F101,"tn_ini duplex","",duplex);
- debug(F101,"tn_ini done, tn_init","",tn_init);
- return(1);
- }
- VOID
- tn_debug(s) char *s; {
- #ifdef OS2
- void cwrite(unsigned short);
- char *p = s;
- _PROTOTYP (void os2bold, (void));
- #endif /* OS2 */
- if (!(tn_deb || debses))
- return;
- debug(F111,"tn_debug",s,what);
- #ifdef OS2
- if ( what == W_COMMAND ) {
- extern unsigned char colorcmd;
- colorcmd ^= 0x8 ;
- printf("%srn",s);
- colorcmd ^= 0x8 ;
- }
- if (!scrninitialized[VTERM]) {
- USHORT x,y;
- checkscreenmode();
- GetCurPos(&y, &x);
- SaveCmdMode(x+1,y+1);
- scrninit();
- RestoreCmdMode();
- }
- os2bold(); /* Toggle boldness */
- while (*p)
- cwrite((CHAR) *p++); /* Go boldly ... */
- os2bold(); /* Toggle boldness back */
- if (debses) {
- debses = 0;
- cwrite((CHAR) ' 15');
- cwrite((CHAR) ' 12');
- debses = 1;
- } else {
- cwrite((CHAR) ' 15');
- cwrite((CHAR) ' 12');
- }
- #else
- if (what != W_CONNECT && what != W_COMMAND)
- return; /* CONNECT/command must be active */
- conoll(s);
- #endif /* OS2 */
- }
- /*
- Process in-band Telnet negotiation characters from the remote host.
- Call with the telnet IAC character and the current duplex setting
- (0 = remote echo, 1 = local echo), and a pointer to a function to call
- to read more characters. Returns:
- 6 if DO LOGOUT was received and accepted
- 5 if the Kermit start of packet character has changed
- 4 if state of remote Internet Kermit Service has changed
- 3 if a quoted IAC was received
- 2 if local echo must be changed to remote
- 1 if remote echo must be changed to local
- 0 if nothing happens or no action necessary
- -1 on failure (= internal or i/o error)
- */
- #ifdef IKS_OPTION
- int
- tn_siks(cmd) int cmd; { /* TELNET SEND IKS SUB */
- #ifndef NOXFER
- CHAR buf[8];
- extern CHAR mystch; /* Outgoing Start of Packet Char */
- int n,m;
- if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
- if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
- if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
- return(-1);
- #ifdef CK_SSL
- if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
- return(0);
- }
- #endif /* CK_SSL */
- if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
- } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
- } else if (cmd == KERMIT_REQ_STOP)
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
- else if (cmd == KERMIT_REQ_START)
- TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
- if (cmd == KERMIT_SOP) {
- buf[0] = (CHAR) IAC;
- buf[1] = (CHAR) SB;
- buf[2] = (CHAR) TELOPT_KERMIT;
- buf[3] = (CHAR) (cmd & 0xff);
- buf[4] = (CHAR) mystch;
- buf[5] = (CHAR) IAC;
- buf[6] = (CHAR) SE;
- buf[7] = (CHAR) 0;
- if (tn_deb || debses || deblog) {
- sprintf(tn_msg,"TELNET SENT SB KERMIT SOP %02X IAC SE",mystch);
- debug(F101,tn_msg,"",cmd);
- if (tn_deb || debses) tn_debug(tn_msg);
- }
- if (ttol(buf,7) < 7)
- return(-1);
- } else {
- buf[0] = (CHAR) IAC;
- buf[1] = (CHAR) SB;
- buf[2] = (CHAR) TELOPT_KERMIT;
- buf[3] = (CHAR) (cmd & 0xff);
- buf[4] = (CHAR) IAC;
- buf[5] = (CHAR) SE;
- buf[6] = (CHAR) 0;
- if (tn_deb || debses || deblog) {
- char * s = 0;
- switch (cmd) {
- case KERMIT_START: s = "START"; break;
- case KERMIT_STOP: s = "STOP"; break;
- case KERMIT_REQ_START: s = "REQ-START"; break;
- case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
- case KERMIT_RESP_START: s = "RESP-START"; break;
- case KERMIT_RESP_STOP: s = "RESP-STOP"; break;
- }
- sprintf(tn_msg,"TELNET SENT SB kermit %s IAC SE",s);
- debug(F101,tn_msg,"",cmd);
- if (tn_deb || debses) tn_debug(tn_msg);
- }
- if (ttol(buf,6) < 6)
- return(-1);
- }
- return(1);
- #else
- return(-1);
- #endif /* NOXFER */
- }
- #endif /* IKS_OPTION */
- /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
- /* returns <= 0 on error, 1 on success */
- /* the length returned includes the IAC SE bytes */
- int
- #ifdef CK_ANSIC /* TELNET SB */
- tn_sb( int opt, int * len, int (*fn)(int) )
- #else
- tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
- #endif /* CK_ANSIC */
- /* tn_sb */ {
- int c, x, y, n, m, flag;
- debug(F100,"Entering tn_sb()","",0);
- *len = 0; /* Initialize Len to 0 */
- n = flag = 0; /* Flag for when done reading SB */
- while (n < TSBUFSIZ) { /* Loop looking for IAC SE */
- if ((y = (*fn)(0)) < 0) /* Read a byte */
- return(y);
- y &= 0xff; /* Make sure it's just 8 bits. */
- sb[n++] = (char) y; /* Deposit in buffer. */
- if (seslog && sessft == XYFT_D) { /* Take care of session log */
- logchar((char) y);
- }
- if (y == IAC) { /* If this is an IAC */
- if (flag) { /* If previous char was IAC */
- n--; /* it's quoted, keep one IAC */
- flag = 0; /* and turn off the flag. */
- } else flag = 1; /* Otherwise set the flag. */
- } else if (flag) { /* Something else following IAC */
- if (y == SE) /* If not SE, it's a protocol error */
- break;
- else if (y == DONT) { /* Used DONT instead of SE */
- debug(F100,
- "TELNET Subnegotiation error - used DONT instead of SE!",
- ""
- ,0
- );
- if (tn_deb || debses)
- tn_debug(
- "TELNET Subnegotiation error - used DONT instead of SE!");
- flag = 3;
- break;
- } else { /* Other protocol error */
- flag = 0;
- break;
- }
- }
- #ifdef COMMENT
- /* This test is sure to be triggered when we are using encryption */
- /* Therefore, we must take it out, otherwise, our subnegotiations */
- /* will be truncated and failure will result. */
- /* This bug was only seen on BeOS DR7 and has been fixed. */
- else if (!flag && y == SE) { /* Forgot the IAC ? */
- flag = 2;
- debug(F100,
- "TELNET Subnegotiation error - forgot the IAC before SE!",
- "",
- 0
- );
- if (tn_deb || debses)
- tn_debug(
- "TELNET Subnegotiation error - forgot the IAC before SE!");
- break;
- }
- #endif /* COMMENT */
- #ifdef CK_FORWARD_X
- if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
- n == (TSBUFSIZ-2) ) {
- /* do not let the buffer over flow */
- /* write the data to the channel and continue processing */
- /* the incoming data until IAC SE is reached. */
- sb[n++] = IAC;
- sb[n++] = SE;
- if ( deblog || tn_deb || debses ) {
- int i;
- sprintf(tn_msg,"TELNET RCVD SB %s DATA ",TELOPT(opt));
- #ifdef HEXDISP
- {
- int was_hex = 1;
- for (i=1; i < n-2; i++) {
- if (sb[i] < 32 || sb[i] >= 127) {
- sprintf(hexbuf,"%s%02X ",was_hex?"":"" ",sb[i]);
- was_hex = 1;
- } else {
- sprintf(hexbuf,"%s%c",was_hex?""":"",sb[i]);
- was_hex = 0;
- }
- strcat(tn_msg,hexbuf);
- }
- if (!was_hex)
- strcat(tn_msg,"" ");
- }
- #else /* HEXDISP */
- memcpy(hexbuf,&sb[i],n-i-2);
- hexbuf[n-i-2] = ' ';
- hexbuf[n-i-1] = ' ';
- strcat(tn_msg,hexbuf);
- #endif /* HEXDISP */
- if (flag == 2)
- strcat(tn_msg,"SE");
- else if (flag == 3)
- strcat(tn_msg," IAC DONT");
- else
- strcat(tn_msg," IAC SE");
- debug(F100,tn_msg,"",0);
- if (tn_deb || debses)
- tn_debug(tn_msg);
- }
- if ( fwdx_tn_sb(sb,n) < 0 )
- return(0);
- /* reset leave the msg type and channel number in place */
- n = 3;
- }
- #endif /* CK_FORWARD_X */
- }
- debug(F111,"tn_sb end of while loop","flag",flag);
- if (!flag) { /* Make sure we got a valid SB */
- debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
- if (tn_deb || debses)
- tn_debug("TELNET Subnegotiation prematurely broken");
- /* Was -1 but that would be an I/O error, so absorb it and go on. */
- return(0);
- }
- if (deblog || tn_deb || debses) {
- int i;
- char * s[16];
- for (i = 0; i < 16; i++)
- s[i] = "";
- if (opt == TELOPT_NAWS) {
- i = 0;
- } else {
- i = 1;
- s[0] = "UNKNOWN";
- switch (sb[0]) {
- case 0:
- if (opt == TELOPT_FORWARD_X)
- s[0] = "SCREEN";
- else if (opt == TELOPT_KERMIT)
- s[0] = "START";
- else if (opt == TELOPT_LFLOW)
- s[0] = "OFF";
- else
- s[0] = "IS";
- if (opt == TELOPT_ENCRYPTION) {
- i++;
- if (sb[1] < ENCTYPE_CNT) {
- s[1] = enctype_names[sb[1]];
- i++;
- switch(sb[2]) {
- case 1:
- s[2] = "FB64_IV";
- break;
- case 2:
- s[2] = "FB64_IV_OK";
- break;
- case 3:
- s[2] = "FB64_IV_BAD";
- break;
- case 4:
- s[2] = "FB64_CHALLENGE";
- break;
- case 5:
- s[2] = "FB64_RESPONSE";
- break;
- }
- } else {
- s[1] = "UNKNOWN";
- }
- }
- if (opt == TELOPT_AUTHENTICATION) {
- i += 2;
- s[1] = AUTHTYPE_NAME(sb[1]);
- s[2] = AUTHMODE_NAME(sb[2]);
- if (sb[1]) {
- i++;
- switch (sb[3]) {
- case 0:
- switch (sb[1]) {
- case AUTHTYPE_NTLM:
- s[3] = "NTLM_AUTH";
- break;
- default:
- s[3] = "AUTH";
- }
- break;
- case 1:
- switch (sb[1]) {
- case AUTHTYPE_SSL:
- s[3] = "START";
- break;
- case AUTHTYPE_NTLM:
- s[3] = "NTLM_CHALLENGE";
- break;
- default:
- s[3] = "REJECT";
- }
- break;
- case 2:
- switch (sb[1]) {
- case AUTHTYPE_NTLM:
- s[3] = "NTLM_RESPONSE";
- break;
- default:
- s[3] = "ACCEPT";
- }
- break;
- case 3:
- switch (sb[1]) {
- case AUTHTYPE_NTLM:
- s[3] = "NTLM_ACCEPT";
- break;
- case 1: /* KERBEROS_v4 */
- case 5: /* SRP */
- s[3] = "CHALLENGE";
- break;
- case 2: /* KERBEROS_v5 */
- s[3] = "RESPONSE";
- break;
- case AUTHTYPE_SSL:
- s[3] = "REJECT";
- break;
- }
- break;
- case 4:
- switch (sb[1]) {
- case AUTHTYPE_NTLM:
- s[3] = "NTLM_REJECT";
- break;
- case 1: /* KERBEROS_V4 */
- case 5: /* SRP */
- s[3] = "RESPONSE";
- break;
- case 2: /* KERBEROS_V5 */
- s[3] = "FORWARD";
- break;
- }
- break;
- case 5: