home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ck9196.zip / ckctel.c < prev    next >
C/C++ Source or Header  |  1999-12-31  |  166KB  |  4,626 lines

  1. char *cktelv = "Telnet support, 7.0.191, 30 Dec 1999";
  2. #define CKCTEL_C
  3.  
  4. int sstelnet = 0;                       /* Do server-side Telnet negotiation */
  5.  
  6. /*  C K C T E L  --  Telnet support  */
  7.  
  8. /*
  9.   Authors:
  10.     Telnet protocol by Frank da Cruz and Jeffrey Altman.
  11.     Other contributions as indicated in the code.
  12.  
  13.   Copyright (C) 1985, 2000,
  14.     Trustees of Columbia University in the City of New York.
  15.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  16.     copyright text in the ckcmai.c module for disclaimer and permissions.
  17. */
  18.  
  19. /*
  20.   NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
  21.   C-Kermit source files, must be compatible with C preprocessors that support
  22.   only #ifdef, #else, #endif, #define, and #undef.  Please do not use #if,
  23.   logical operators, or other preprocessor features in this module.  Also,
  24.   don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
  25. */
  26.  
  27. #include "ckcsym.h"
  28. #include "ckcdeb.h"
  29.  
  30. #include "ckcker.h"
  31. #define TELCMDS                         /* to define name array */
  32. #define TELOPTS                         /* to define name array */
  33. #define SLC_NAMES                       /* to define name array */
  34. #define ENCRYPT_NAMES
  35. #define AUTH_NAMES
  36. #define TELOPT_STATES
  37. #define TELOPT_MODES
  38. #include "ckcnet.h"
  39. #include "ckctel.h"
  40. #ifdef CK_SSL
  41. #include "ck_ssl.h"
  42. #endif /* CK_SSL */
  43.  
  44. #ifdef TNCODE
  45.  
  46. #ifdef OS2                              /* For terminal type name string */
  47. #include "ckuusr.h"
  48. #ifndef NT
  49. #include <os2.h>
  50. #undef COMMENT
  51. #endif /* NT */
  52. #include "ckocon.h"
  53. extern int tt_type, max_tt;
  54. extern struct tt_info_rec tt_info[];
  55. extern char ttname[];
  56. #endif /* OS2 */
  57.  
  58. #ifdef OS2
  59. #include <assert.h>
  60. #ifdef NT
  61. #include <setjmpex.h>
  62. #else /* NT */
  63. #include <setjmp.h>
  64. #endif /* NT */
  65. #include <signal.h>
  66. #include "ckcsig.h"
  67. #endif /* OS2 */
  68.  
  69. #define HEXDISP
  70.  
  71. #ifdef CK_NAWS                          /* Negotiate About Window Size */
  72. #ifdef RLOGCODE
  73. _PROTOTYP( int rlog_naws, (void) );
  74. #endif /* RLOGCODE */
  75. #endif /* CK_NAWS */
  76.  
  77. int tn_init = 0;                        /* Telnet protocol initialized flag */
  78. static int tn_first = 1;                /* First time init flag */
  79. extern int tn_exit;                     /* Exit on disconnect */
  80. extern int inserver;                    /* Running as IKSD */
  81. char *tn_term = NULL;                   /* Terminal type override */
  82.  
  83. #ifdef CK_SNDLOC
  84. char *tn_loc = NULL;                    /* Location override */
  85. #endif /* CK_SNDLOC */
  86. int tn_nlm = TNL_CRLF;                  /* Telnet CR -> CR LF mode */
  87. int tn_b_nlm = TNL_CR;                  /* Telnet Binary CR RAW mode */
  88. int tn_b_meu = 0;                       /* Telnet Binary ME means U too */
  89. int tn_b_ume = 0;                       /* Telnet Binary U means ME too */
  90. int tn_wait_flg = 1;                    /* Telnet Wait for Negotiations */
  91. int tn_infinite = 0;                    /* Telnet Bug Infinite-Loop-Check */
  92. int tn_rem_echo = 1;                    /* We will echo if WILL ECHO */
  93. int tn_b_xfer = 0;                      /* Telnet Binary for Xfers? */
  94. int tn_sb_bug = 1;                      /* Telnet BUG - SB w/o WILL or DO */
  95. int tn_no_encrypt_xfer = 0;             /* Turn off Telnet Encrypt? */
  96. int tn_auth_how = TN_AUTH_HOW_ANY;
  97. int tn_auth_enc = TN_AUTH_ENC_ANY;
  98. int tn_deb = 0;                         /* Telnet Debug mode */
  99.  
  100. #ifdef OS2
  101. int ttnum = -1;                         /* Last Telnet Terminal Type sent */
  102. int ttnumend = 0;                       /* Has end of list been found */
  103. #endif /* OS2 */
  104.  
  105. #define TN_MSG_LEN 8196
  106. char tn_msg[TN_MSG_LEN];                /* Telnet data can be rather long */
  107. char hexbuf[TN_MSG_LEN];
  108.  
  109. /*
  110.   In order to prevent an infinite telnet negotiation loop we maintain a
  111.   count of the number of times the same telnet negotiation message is
  112.   sent. When this count hits MAXTNCNT, we do not send any more of the
  113.   message. The count is stored in the tncnts[][] array.
  114.  
  115.   The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
  116.   TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
  117.   negotiation message types (WILL, WONT, DO, DONT).  All telnet negotiations
  118.   are kept track of in this way.
  119.  
  120.   The count for a message is zeroed when the "opposite" message is sent.
  121.   WILL is the opposite of WONT, and DO is the opposite of DONT.
  122.   For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
  123.   and zeroes tncnts[TELOPT_SGA][1].
  124.  
  125.   The code that does this is in tn_sopt().
  126.  
  127.   rogersh@fsj.co.jp, 18/3/1995
  128.  
  129.   8/16/1998 - with the recent rewrite of the telnet state machine I don't
  130.   think this code is necessary anymore.  However, it can't do any harm so
  131.   I am leaving it in.    - Jeff
  132.  
  133.   12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
  134.   because the Telnet option list is no longer contiguous.  We also must
  135.   allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
  136.   for an invalid option number.
  137. */
  138.  
  139. #define MAXTNCNT 4      /* Permits 4 intermediate telnet firewalls/gateways */
  140.  
  141. char tncnts[NTELOPTS+1][4];             /* Counts */
  142. char tnopps[4] = { 1,0,3,2 };           /* Opposites */
  143.  
  144. #ifdef CK_ENVIRONMENT
  145. #define TSBUFSIZ 1024
  146. char tn_env_acct[64];
  147. char tn_env_disp[64];
  148. char tn_env_job[64];
  149. char tn_env_prnt[64];
  150. char tn_env_sys[64];
  151. int tn_env_flg = 1;
  152. #else /* CK_ENVIRONMENT */
  153. #define TSBUFSIZ 41
  154. int tn_env_flg = 0;
  155. #endif /* CK_ENVIRONMENT */
  156.  
  157. #ifndef NOSIGWINCH
  158. #ifdef CK_NAWS                          /* Window size business */
  159. #ifdef UNIX
  160. #include <signal.h>
  161. #endif /* UNIX */
  162. #endif /* CK_NAWS */
  163. #endif /* NOSIGWINCH */
  164.  
  165. unsigned char sb[TSBUFSIZ+8];           /* Buffer for subnegotiations */
  166.  
  167. int tn_duplex = 1;                      /* Local echo */
  168.  
  169. extern char uidbuf[];                   /* User ID buffer */
  170. extern int quiet, ttnet, ttnproto, debses, what, duplex;
  171. extern int seslog, sessft, whyclosed;
  172. #ifdef OS2
  173. extern int tt_rows[], tt_cols[];
  174. extern int tt_status;
  175. extern int scrninitialized[];
  176. #else /* OS2 */
  177. extern int tt_rows, tt_cols;            /* Everybody has this */
  178. #endif /* OS2 */
  179. extern int cmd_cols, cmd_rows;
  180. extern char namecopy[];
  181. extern char myipaddr[];             /* Global copy of my IP address */
  182.  
  183. int sw_armed = 0;                       /* SIGWINCH armed flag */
  184.  
  185. #ifndef NOSIGWINCH
  186. #ifdef CK_NAWS                          /* Window size business */
  187. #ifdef SIGWINCH
  188. #ifdef UNIX
  189.  
  190. SIGTYP
  191. winchh(foo) int foo; {
  192.     int x = 0;
  193. #ifdef CK_TTYFD
  194. #ifndef VMS
  195.     extern int ttyfd;
  196. #endif /* VMS */
  197. #endif /* CK_TTYFD */
  198.     debug(F100,"SIGWINCH caught","",0);
  199.     signal(SIGWINCH,winchh);            /* Re-arm the signal */
  200. #ifdef CK_TTYFD
  201.     if
  202. #ifdef VMS
  203.       (vmsttyfd() == -1)
  204. #else
  205.       (ttyfd == -1)
  206. #endif /* VMS */
  207. #else
  208.       (!local)
  209. #endif /* CK_TTYFD */
  210.     return;
  211.  
  212.     x = ttgwsiz();                      /* Get new window size */
  213. /*
  214.   This should be OK.  It might seem that sending this from
  215.   interrupt level could interfere with another TELNET IAC string
  216.   that was in the process of being sent.  But we always send
  217.   TELNET strings with a single write(), which should prevent mixups.
  218. */
  219.     if (x > 0 && tt_rows > 0 && tt_cols > 0) {
  220.         tn_snaws();
  221. #ifdef RLOGCODE
  222.         rlog_naws();
  223. #endif /* RLOGCODE */
  224.     }
  225.     return;
  226. }
  227. #endif /* UNIX */
  228. #endif /* SIGWINCH */
  229. #endif /* CK_NAWS */
  230. #endif /* NOSIGWINCH */
  231.  
  232. #ifndef TELOPT_MACRO
  233. int
  234. telopt_index(opt) int opt; {
  235.     if (opt >= 0 && opt <= TELOPT_FORWARD_X)
  236.       return(opt);
  237.     else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
  238.       return(opt-89);
  239.     else if (opt == TELOPT_IBM_SAK)
  240.       return(opt-148);
  241.     else
  242.       return(NTELOPTS);
  243. }
  244.  
  245. int
  246. telopt_ok(opt) int opt; {
  247.     return((opt >= TELOPT_BINARY && opt <= TELOPT_FORWARD_X) ||
  248.            (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
  249.            (opt == TELOPT_IBM_SAK));
  250. }
  251.  
  252. CHAR *
  253. telopt(opt) int opt; {
  254.     if (telopt_ok(opt))
  255.       return((CHAR *)telopts[telopt_index(opt)]);
  256.     else
  257.       return((CHAR *)"UNKNOWN");
  258. }
  259.  
  260. int
  261. telopt_mode_ok(opt) int opt; {
  262.     return((unsigned int)(opt) <= TN_NG_MU);
  263. }
  264.  
  265. CHAR *
  266. telopt_mode(opt) int opt; {
  267.     if (telopt_mode_ok(opt))
  268.       return((CHAR *)telopt_modes[opt-TN_NG_RF]);
  269.     else
  270.       return((CHAR *)"UNKNOWN");
  271. }
  272. #endif /* TELOPT_MACRO */
  273.  
  274. static int
  275. tn_outst(notquiet) int notquiet; {
  276.     int outstanding = 0;
  277.     int x = 0;
  278. #ifdef CK_ENCRYPTION
  279.     int e = 0;
  280.     int d = 0;
  281. #endif /* CK_ENCRYPTION */
  282.  
  283.     if (tn_wait_flg) {
  284.         for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
  285.             if (TELOPT_OK(x)) {
  286.                 if (TELOPT_UNANSWERED_WILL(x)) {
  287.                     if ( notquiet )
  288.                       printf("?Telnet waiting for response to WILL %s\r\n",
  289.                              TELOPT(x));
  290.                     debug(F111,"tn_outst","unanswered WILL",x);
  291.                     outstanding = 1;
  292.                     if ( !notquiet )
  293.                       break;
  294.                 }
  295.                 if (TELOPT_UNANSWERED_DO(x)) {
  296.                     if ( notquiet )
  297.                       printf("?Telnet waiting for response to DO %s\r\n",
  298.                              TELOPT(x));
  299.                     debug(F111,"tn_outst","unanswered DO",x);
  300.                     outstanding = 1;
  301.                     if ( !notquiet )
  302.                       break;
  303.                 }
  304.                 if (TELOPT_UNANSWERED_WONT(x)) {
  305.                     if ( notquiet )
  306.                       printf("?Telnet waiting for response to WONT %s\r\n",
  307.                              TELOPT(x));
  308.                     debug(F111,"tn_outst","unanswered WONT",x);
  309.                     outstanding = 1;
  310.                     if ( !notquiet )
  311.                       break;
  312.                 }
  313.                 if (TELOPT_UNANSWERED_DONT(x)) {
  314.                     if ( notquiet )
  315.                       printf("?Telnet waiting for response to DONT %s\r\n",
  316.                              TELOPT(x));
  317.                     debug(F111,"tn_outst","unanswered DONT",x);
  318.                     outstanding = 1;
  319.                     if ( !notquiet )
  320.                       break;
  321.                 }
  322.                 if (TELOPT_UNANSWERED_SB(x)) {
  323.                     if ( notquiet )
  324.                       printf("?Telnet waiting for response to SB %s\r\n",
  325.                              TELOPT(x));
  326.                     debug(F111,"tn_outst","unanswered SB",x);
  327.                     outstanding = 1;
  328.                     if ( !notquiet )
  329.                       break;
  330.                 }
  331.             }
  332.         }
  333.         if (!outstanding && !notquiet) {
  334. #ifdef CK_ENCRYPTION
  335.             e = ck_tn_encrypting();
  336.             d = ck_tn_decrypting();
  337.             if (TELOPT_ME(TELOPT_ENCRYPTION)) {
  338.                 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
  339.                     !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
  340.                     ) {
  341.                     if ( notquiet )
  342.                       printf("?Telnet waiting for WILL %s subnegotiation\r\n",
  343.                              TELOPT(TELOPT_ENCRYPTION));
  344.                     debug(F111,
  345.                           "tn_outst",
  346.                           "encryption mode switch",
  347.                           TELOPT_ENCRYPTION
  348.                           );
  349.                     outstanding = 1;
  350.                 }
  351.             }
  352.             if (TELOPT_U(TELOPT_ENCRYPTION)) {
  353.                 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
  354.                     !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
  355.                     ) {
  356.                     if ( notquiet )
  357.                       printf("?Telnet waiting for DO %s subnegotiation\r\n",
  358.                              TELOPT(TELOPT_ENCRYPTION));
  359.                     debug(F111,
  360.                           "tn_outst",
  361.                           "decryption mode switch",
  362.                            TELOPT_ENCRYPTION
  363.                           );
  364.                     outstanding = 1;
  365.                 }
  366.             }
  367. #endif /* CK_ENCRYPTION */
  368. #ifdef CK_AUTHENTICATION
  369.             if (TELOPT_ME(TELOPT_AUTHENTICATION) &&
  370.                 ck_tn_auth_in_progress()
  371.                 ) {
  372.                 if ( notquiet )
  373.                   printf("?Telnet waiting for WILL %s subnegotiation\r\n",
  374.                          TELOPT(TELOPT_AUTHENTICATION));
  375.                 debug(F111,
  376.                       "tn_outst",
  377.                       "ME authentication in progress",
  378.                        TELOPT_AUTHENTICATION
  379.                       );
  380.                 outstanding = 1;
  381.             } else if (TELOPT_U(TELOPT_AUTHENTICATION) &&
  382.                        ck_tn_auth_in_progress()
  383.                        ) {
  384.                 if ( notquiet )
  385.                   printf("?Telnet waiting for DO %s subnegotiation\r\n",
  386.                          TELOPT(TELOPT_AUTHENTICATION));
  387.                 debug(F111,
  388.                       "tn_outst",
  389.                       "U authentication in progress",
  390.                       TELOPT_AUTHENTICATION
  391.                       );
  392.                 outstanding = 1;
  393.             }
  394. #endif /* CK_AUTHENTICATION */
  395.         }
  396.     } /* if (tn_wait_flg) */
  397.  
  398. #ifdef IKS_OPTION
  399.     /* Even if we are not waiting for Telnet options we must wait for */
  400.     /* Kermit Telnet Subnegotiations if we have sent a request to the */
  401.     /* other guy.  Otherwise we will get out of sync.                 */
  402.     if (!outstanding) {
  403.         if (TELOPT_U(TELOPT_KERMIT) &&
  404.             (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
  405.              TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
  406.              !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
  407.             ) {
  408.             if ( notquiet )
  409.               printf("?Telnet waiting for DO %s subnegotiation\r\n",
  410.                      TELOPT(TELOPT_KERMIT));
  411.             debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
  412.             outstanding = 1;
  413.         }
  414.     }
  415. #endif /* IKS_OPTION */
  416.     return(outstanding);
  417. }
  418.  
  419. /* tn_wait() -- Wait for response to Telnet negotiation. */
  420. /*
  421.   Wait for up to <timeout> seconds for the response to arrive.
  422.   Place all non-telnet data into Telnet Wait Buffer.
  423.   If response does arrive return 1, else return 0.
  424. */
  425. #ifndef TN_WAIT_BUF_SZ
  426. #define TN_WAIT_BUF_SZ 4096
  427. #endif /* TN_WAIT_BUF_SZ */
  428. static char tn_wait_buf[TN_WAIT_BUF_SZ];
  429. static int  tn_wait_idx = 0;
  430. #ifndef TN_TIMEOUT
  431. #define TN_TIMEOUT 120
  432. #endif /* TN_TIMEOUT */
  433. static int tn_wait_tmo = TN_TIMEOUT;
  434.  
  435. #ifdef CKSPINNER
  436. VOID
  437. prtwait(state) int state; {
  438.     switch (state % 4) {
  439.       case 0:
  440.         printf("/");
  441.         break;
  442.       case 1:
  443.         printf("-");
  444.         break;
  445.       case 2:
  446.         printf("\\");
  447.         break;
  448.       case 3:
  449.         printf("|");
  450.         break;
  451.     }
  452. }
  453. #endif /* CKSPINNER */
  454.  
  455. static int nflag = 0;
  456.  
  457. int
  458. #ifdef CK_ANSIC
  459. tn_wait(char * where)
  460. #else
  461. tn_wait(where) char * where;
  462. #endif /* CK_ANSIC */
  463. /* tn_wait */ {
  464.     extern int ckxech, local;
  465.     int ch = 0, try = 0, count = 0;
  466.     int outstanding;
  467.  
  468.     debug(F110,"tn_wait waiting for",where,0);
  469.     tn_wait_tmo = TN_TIMEOUT;
  470.     debug(F111,"tn_wait","timeout",tn_wait_tmo);
  471.     outstanding = tn_outst(0);
  472.  
  473.     /* The following is meant to be !(||).  We only want to return */
  474.     /* immediately if both the tn_wait_flg && tn_outst() are false */
  475.     if (!(outstanding || tn_wait_flg))  /* If no need to wait */
  476.       return(1);                        /* Don't. */
  477.  
  478.     if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
  479.  
  480.     if (!sstelnet && !quiet) {
  481. #ifdef CKSPINNER
  482.         prtwait(try);
  483. #endif /* CKSPINNER */
  484.     }
  485.  
  486.     /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
  487.     while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
  488.            (count || ((outstanding || try == 0) && ttchk() >= 0))
  489.            ) {
  490. #ifdef NTSIG
  491.         ck_ih();
  492. #endif /* NTSIG */
  493.         ch = ttinc(1);
  494.         if (ch == -1) {                 /* Timed out */
  495.             try++;
  496.             if (!sstelnet && !quiet) {  /* Let user know... */
  497. #ifdef CKSPINNER
  498.                 printf("\b");
  499.                 prtwait(try);
  500. #else
  501.                 if (nflag == 0) {
  502.                     printf(" Negotiations.");
  503.                     nflag++;
  504.                 }
  505.                 if (nflag > 0) {
  506.                     printf(".");
  507.                     nflag++;
  508.                     fflush(stdout);
  509.                 }
  510. #endif /* CKSPINNER */
  511.             }
  512.             if ( try > tn_wait_tmo ) {
  513.                 if (!sstelnet) {
  514.                     printf(
  515.                        "\r\n?Telnet Protocol Timeout - connection closed\r\n");
  516.                     if (tn_deb || debses)
  517.                       tn_debug(
  518.                        "<telnet protocol timeout - connection closed>");
  519.                     tn_outst(1);
  520.                 }
  521.                 /* if we do not close the connection, then we will block */
  522.                 /* the next time we hit a wait.  and if we don't we will */
  523.                 /* do the wrong thing if the host sends 0xFF and does    */
  524.                 /* not intend it to be an IAC.                           */
  525.                 ttclos(0);
  526.                 whyclosed = WC_TELOPT;
  527.                 return(-1);
  528.             }
  529.             continue;
  530.         } else if (ch < -1) {
  531.             printf("\r\n?Connection closed by peer.\r\n");
  532.             if (tn_deb || debses) tn_debug("<connection closed by peer>");
  533.             return(-1);
  534.         }
  535.         switch (ch) {
  536.           case IAC:
  537. #ifdef CKSPINNER
  538.             if (!sstelnet && !quiet)
  539.               printf("\b");
  540. #endif /* CKSPINNER */
  541.             ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
  542. #ifdef CKSPINNER
  543.             if (!sstelnet && !quiet)
  544.               prtwait(try);
  545. #endif /* CKSPINNER */
  546.             debug(F101,"tn_wait tn_doop","",ch);
  547.             switch (ch) {
  548.               case 1:
  549.                 duplex = 1;             /* Turn on echoing */
  550.                 if (inserver)
  551.                   ckxech = 1;
  552.                 break;
  553.               case 2:
  554.                 duplex = 0;             /* Turn off echoing */
  555.                 if (inserver)
  556.                   ckxech = 0;
  557.                 break;
  558.               case 3:
  559.                 tn_wait_buf[tn_wait_idx++] = IAC;
  560.                 break;
  561.               case 4:                   /* IKS event */
  562.               case 6:                   /* Logout */
  563.                 break;
  564.               case -1:
  565.                 printf("?Telnet Option negotiation error.\n");
  566.                 if (tn_deb || debses)
  567.                   tn_debug("<Telnet Option negotiation error>");
  568.                 return(-1);
  569.               case -2:
  570.                 printf("?Connection closed by peer.\n");
  571.                 if (tn_deb || debses) tn_debug("<Connection closed by peer>");
  572.                 return(-2);
  573.               default:
  574.                 if (ch < 0) {
  575.                   if (tn_deb || debses) tn_debug("<Unknown connection error>");
  576.                   return(ch);
  577.                 }
  578.             } /* switch */
  579.             break;
  580.           default:
  581.             tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
  582.         } /* switch */
  583.         outstanding = tn_outst(0);
  584.         count = ttchk();
  585.         if (!try)
  586.           try++;
  587.     } /* while */
  588.  
  589.     if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  590.       if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
  591.       return(0);
  592.     }
  593.  
  594.     if (!sstelnet && !quiet) {
  595. #ifdef CKSPINNER
  596.         printf("\b \b");
  597. #else
  598.         if (nflag > 0) {
  599.             printf(" (OK)\n");
  600.             nflag = -1;
  601.         }
  602. #endif /* CKSPINNER */
  603.     }
  604.     if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
  605.     return(0);
  606. }
  607.  
  608. /* Push data from the Telnet Wait Buffer into the I/O Queue */
  609. /* Return 1 on success                                      */
  610.  
  611. int
  612. tn_push() {
  613. #ifdef NETLEBUF
  614.     extern int tt_push_inited;
  615. #endif /* NETLEBUF */
  616.     if (tn_wait_idx) {
  617.         hexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
  618. #ifdef NETLEBUF
  619.         if (!tt_push_inited)            /* Local handling */
  620.           le_init();
  621.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  622. #else                                   /* External handling... */
  623. #ifdef OS2                              /* K95 has its own way */
  624.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  625. #else
  626. #ifdef TTLEBUF                          /* UNIX, etc */
  627.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  628. #else
  629. /*
  630.   If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
  631.   the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
  632.   places in your ck?tio.c module.
  633. */
  634.         printf("tn_push called but not implemented - data lost.\n");
  635. #endif /* NETLEBUF */
  636. #endif /* UNIX */
  637. #endif /* OS2 */
  638.         tn_wait_idx = 0;
  639.     }
  640.     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
  641.     return(1);
  642. }
  643.  
  644. /*  T N _ S O P T  */
  645. /*
  646.    Sends a telnet option, avoids loops.
  647.    Returns 1 if command was sent, 0 if not, -1 on error.
  648. */
  649. int
  650. tn_sopt(cmd,opt) int cmd, opt; {        /* TELNET SEND OPTION */
  651.     CHAR buf[5];
  652.  
  653.     if (ttnet != NET_TCPB) return(-1);  /* Must be TCP/IP */
  654.     if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
  655.     if (!TELCMD_OK(cmd)) return(-1);
  656.     if (TELOPT_OK(opt)) {
  657.         if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
  658.         if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
  659.         if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
  660.         if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
  661.     }
  662. #ifdef CK_SSL
  663.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  664.         return(0);
  665.     }
  666. #endif /* CK_SSL */
  667.  
  668.     if (cmd == DO && opt == TELOPT_AUTHENTICATION)
  669.       buf[0] = 0;
  670.  
  671.     if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about   */
  672.         int index = TELOPT_INDEX(opt);   /* preventing infinite loops */
  673.         int m = cmd - WILL;
  674.  
  675.         if (tncnts[index][m] > MAXTNCNT) {
  676.             if (tn_deb || debses || deblog) {
  677.                 sprintf(tn_msg,"TELNET negotiation loop %s %s",
  678.                         TELCMD(cmd),
  679.                         TELOPT(opt));
  680.                 debug(F101,tn_msg,"",opt);
  681.                 if (tn_deb || debses) tn_debug(tn_msg);
  682.             }
  683.             return(0);
  684.         }
  685.         tncnts[index][m]++;
  686.         tncnts[index][tnopps[m]] = 0;
  687.     }
  688.     buf[0] = (CHAR) IAC;
  689.     buf[1] = (CHAR) (cmd & 0xff);
  690.     buf[2] = (CHAR) (opt & 0xff);
  691.     buf[3] = (CHAR) 0;
  692.     if ((tn_deb || debses || deblog) && cmd != SB) {
  693.         sprintf(tn_msg,"TELNET SENT %s %s",TELCMD(cmd),
  694.                 TELOPT(opt));
  695.         debug(F101,tn_msg,"",opt);
  696.     }
  697.  
  698.     if (ttol(buf,3) < 3) {
  699.         return(-1);
  700.     }
  701.  
  702.     /* Only display the command if it was actually sent. */
  703.     if ((tn_deb || debses) && cmd != SB) tn_debug(tn_msg);
  704.  
  705.     if (TELOPT_OK(opt)) {
  706.         if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
  707.           TELOPT_UNANSWERED_DO(opt) = 0;
  708.         if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
  709.           TELOPT_UNANSWERED_WILL(opt) = 0;
  710.         if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
  711.           TELOPT_UNANSWERED_DONT(opt) = 0;
  712.         if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
  713.           TELOPT_UNANSWERED_WONT(opt) = 0;
  714.     }
  715.     return(1);
  716. }
  717.  
  718. /* Send a telnet sub-option */
  719. /* Returns 1 if command was sent, 0 if not, -1 on error */
  720.  
  721. int
  722. tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
  723.     CHAR buf[256];
  724.     int n,m;
  725.  
  726.     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
  727.     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
  728.     if (!TELOPT_OK(opt)) return(-1);
  729.     if (len < 0 || len > 250) {
  730.         debug(F111,"Unable to Send TELNET SB - data too long","len",len);
  731.         return(-1);                     /* Data too long */
  732.     }
  733. #ifdef CK_SSL
  734.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  735.         if (ttchk() < 0)
  736.           return(-1);
  737.         else
  738.           return(1);
  739.     }
  740. #endif /* CK_SSL */
  741.  
  742.     if (!data) len = 0;
  743.  
  744.     buf[0] = (CHAR) IAC;
  745.     buf[1] = (CHAR) (SB & 0xff);
  746.     buf[2] = (CHAR) (opt & 0xff);
  747.     buf[3] = (CHAR) (sub & 0xff);
  748.     if (data && len > 0) {
  749.         memcpy(&buf[4],data,len);
  750.     }
  751.     buf[4+len] = (CHAR) IAC;
  752.     buf[5+len] = (CHAR) SE;
  753.  
  754.     if (tn_deb || debses || deblog) {
  755.         if (opt == TELOPT_START_TLS && sub == 1)
  756.           sprintf(tn_msg,"TELNET SENT SB %s FOLLOWS IAC SE",
  757.                   TELOPT(opt)
  758.                   );
  759.         else if (opt == TELOPT_TTYPE && sub == 1)
  760.           sprintf(tn_msg,"TELNET SENT SB %s SEND IAC SE", TELOPT(opt));
  761.         else if (opt == TELOPT_TTYPE && sub == 0)
  762.           sprintf(tn_msg,"TELNET SENT SB %s IS %s IAC SE", TELOPT(opt),data);
  763.         else if (opt == TELOPT_NEWENVIRON) {
  764.             int i, quote;
  765.             sprintf(tn_msg,"TELNET SENT SB %s %s",
  766.                     TELOPT(TELOPT_NEWENVIRON),
  767.                     sub == TELQUAL_SEND ? "SEND" :
  768.                     sub == TELQUAL_IS ? "IS" :
  769.                     sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
  770.             for (i = 0, quote = 0; i < len; i++) {
  771.                 if (quote) {
  772.                     sprintf(hexbuf,"%02x",data[i]);
  773.                     strcat(tn_msg,hexbuf);
  774.                     quote = 0;
  775.                 } else {
  776.                     switch (data[i]) {
  777.                       case TEL_ENV_USERVAR:
  778.                         strcat(tn_msg," USERVAR ");
  779.                         break;
  780.                       case TEL_ENV_VAR:
  781.                         strcat(tn_msg," VAR ");
  782.                         break;
  783.                       case TEL_ENV_VALUE:
  784.                         strcat(tn_msg," VALUE ");
  785.                         break;
  786.                       case TEL_ENV_ESC:
  787.                         strcat(tn_msg," ESC ");
  788.                         quote = 1;
  789.                         break;
  790.                       case IAC:
  791.                         strcat(tn_msg," IAC ");
  792.                         break;
  793.                       default:
  794.                         sprintf(hexbuf,"%c",data[i]);
  795.                         strcat(tn_msg,hexbuf);
  796.                     }
  797.                 }
  798.             }
  799.             strcat(tn_msg," IAC SE");
  800.         } else
  801.           sprintf(tn_msg,
  802.                   "TELNET SENT SB %s %02x <data> IAC SE",
  803.                   TELOPT(opt),
  804.                   sub
  805.                   );
  806.         debug(F101,tn_msg,"",opt);
  807.         if (tn_deb || debses) tn_debug(tn_msg);
  808.     }
  809.     if (ttol(buf,6+len) < 6+len)
  810.       return(-1);
  811.     return(1);
  812. }
  813.  
  814. /*
  815.   tn_flui() -- Processes all waiting data for Telnet commands.
  816.   All non-Telnet data is to be stored into the Telnet Wait Buffer.
  817.   Returns 1 on success.
  818. */
  819. int
  820. tn_flui() {
  821.     extern int ckxech;
  822.     int x = 0;
  823.  
  824.     /* Wait up to 5 sec for responses to outstanding telnet negotiations */
  825.     while (x >= 0 && ttchk() > 0  && tn_wait_idx < TN_WAIT_BUF_SZ) {
  826.         x = ttinc(1);
  827.         switch (x) {
  828.           case IAC:
  829.             x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
  830.             debug(F101,"tn_flui tn_doop","",x);
  831.             switch (x) {
  832.               case 1:                   /* Turn on echoing */
  833.                 duplex = 1;
  834.                 if (inserver)
  835.                   ckxech = 1;
  836.                 break;
  837.               case 2:                   /* Turn off echoing */
  838.                 duplex = 0;
  839.                 if (inserver)
  840.                   ckxech = 0;
  841.                 break;
  842.               case 3:
  843.                 tn_wait_buf[tn_wait_idx++] = IAC;
  844.                 break;
  845.               case 4:                   /* IKS event */
  846.               case 6:                   /* Logout */
  847.                 break;
  848.             }
  849.             break;
  850.           default:
  851.             if (x >= 0)
  852.               tn_wait_buf[tn_wait_idx++] = x;
  853.         }
  854.     }
  855.     return(1);
  856. }
  857.  
  858. #ifdef CK_FORWARD_X
  859. int
  860. #ifdef CK_ANSIC
  861. fwdx_tn_sb( unsigned char * sb, int n )
  862. #else
  863. fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
  864. #endif /* CK_ANSIC */
  865. {
  866.     unsigned short hchannel, nchannel;
  867.     unsigned char * p;
  868.     int rc = -1;
  869.  
  870.     /* as a security precaution should add a test here to check to make sure */
  871.     /* we have negotiated FORWARD_X with the peer.                           */
  872.  
  873.     switch (sb[0]) {
  874.     case FWDX_SCREEN:
  875.         if (sstelnet && n == 4)
  876.             rc = fwdx_create_listen_socket(sb[1]);
  877.         break;
  878.     case FWDX_OPEN:
  879.         if ( !sstelnet && n == 5 ) {
  880.             p = (unsigned char *) &nchannel;
  881.             p[0] = sb[1];
  882.             p[1] = sb[2];
  883.  
  884.             hchannel = ntohs(nchannel);
  885.             rc = fwdx_open_client_channel(hchannel);
  886.             if ( rc < 0 ) {
  887.                 /* Failed; Send CLOSE channel */
  888.                 fwdx_send_close(hchannel);
  889.             }
  890. #ifdef NT
  891.             if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
  892.                 ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
  893.                 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
  894.             }
  895. #endif /* NT */
  896.         }
  897.         break;
  898.     case FWDX_CLOSE:
  899.         p = (unsigned char *) &nchannel;
  900.         p[0] = sb[1];
  901.         p[1] = sb[2];
  902.  
  903.         hchannel = ntohs(nchannel);
  904.         rc = fwdx_close_channel(hchannel);
  905.         break;
  906.     case FWDX_DATA:
  907.         p = (unsigned char *) &nchannel;
  908.         p[0] = sb[1];
  909.         p[1] = sb[2];
  910.  
  911.         hchannel = ntohs(nchannel);
  912.         rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3],n-5);
  913.         break;
  914.     }
  915.  
  916.     if ( rc < 0 ) {
  917.         if ( sstelnet ) {
  918.             if (tn_sopt(WONT,TELOPT_FORWARD_X) < 0)
  919.                 return(-1);
  920.             TELOPT_UNANSWERED_WONT(TELOPT_FORWARD_X) = 1;
  921.             return(-1);
  922.         } else {
  923.             if (tn_sopt(DONT,TELOPT_FORWARD_X) < 0)
  924.                 return(-1);
  925.             TELOPT_UNANSWERED_DONT(TELOPT_FORWARD_X) = 1;
  926.             return(-1);
  927.         }
  928.     }
  929.     return(0);
  930. }
  931.  
  932. int
  933. fwdx_send_close(channel) int channel; {
  934.     int nchannel;
  935.     CHAR * p;
  936.  
  937.     nchannel = htons(channel);
  938.     p = (unsigned char *) &nchannel;
  939.  
  940.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  941.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  942.     sb[2] = TELOPT_FORWARD_X;           /* Forward X */
  943.     sb[3] = FWDX_CLOSE;                  /* Open */
  944.     sb[4] = p[0];
  945.     sb[5] = p[1];
  946.     sb[6] = (CHAR) IAC;                 /* End of Subnegotiation */
  947.     sb[7] = (CHAR) SE;                  /* marked by IAC SE */
  948.     if (ttol((CHAR *)sb,8) < 0) {       /* Send it. */
  949.         return(-1);
  950.     }
  951. #ifdef DEBUG
  952.     if (deblog || tn_deb || debses) {
  953.         sprintf(tn_msg,"TELNET SENT SB %s CLOSE %02x %02x IAC SE",
  954.         TELOPT(TELOPT_FORWARD_X),p[0],p[1]);
  955.         debug(F100,tn_msg,"",0);
  956.         if (tn_deb || debses) tn_debug(tn_msg);
  957.     }
  958. #endif /* DEBUG */
  959.     return(0);
  960. }
  961.  
  962. int
  963. fwdx_send_open(channel) int channel; {
  964.     int nchannel;
  965.     CHAR * p;
  966.  
  967.     nchannel = htons(channel);
  968.     p = (unsigned char *) &nchannel;
  969.  
  970.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  971.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  972.     sb[2] = TELOPT_FORWARD_X;           /* Forward X */
  973.     sb[3] = FWDX_OPEN;                  /* Open */
  974.     sb[4] = p[0];
  975.     sb[5] = p[1];
  976.     sb[6] = (CHAR) IAC;                 /* End of Subnegotiation */
  977.     sb[7] = (CHAR) SE;                  /* marked by IAC SE */
  978.     if (ttol((CHAR *)sb,8) < 0) {       /* Send it. */
  979.         return(-1);
  980.     }
  981. #ifdef DEBUG
  982.     if (deblog || tn_deb || debses) {
  983.         sprintf(tn_msg,"TELNET SENT SB %s OPEN %02x %02x IAC SE",
  984.         TELOPT(TELOPT_FORWARD_X),p[0],p[1]);
  985.         debug(F100,tn_msg,"",0);
  986.         if (tn_deb || debses) tn_debug(tn_msg);
  987.     }
  988. #endif /* DEBUG */
  989.     return(0);
  990. }
  991.  
  992.  
  993. #endif /* CK_FORWARD_X */
  994.  
  995. #ifdef IKS_OPTION
  996. /*
  997.   iks_wait() -- Wait for an IKS subnegotiation response.
  998.   sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
  999.        state of the peer's Kermit server.
  1000.   flushok - specifies whether it is ok to throw away non-Telnet data
  1001.        if so, then we call ttflui() instead of tn_flui().
  1002.   Returns:
  1003.    1 if the desired state is achieved or if it is unknown.
  1004.    0 if the desired state is not achieved.
  1005. */
  1006. int
  1007. #ifdef CK_ANSIC
  1008. iks_wait(int sb, int flushok)
  1009. #else /* CK_ANSIC */
  1010. iks_wait(sb,flushok) int sb; int flushok;
  1011. #endif /* CK_ANSIC */
  1012. {
  1013.     int tn_wait_save = tn_wait_flg;
  1014.     int x;
  1015.  
  1016.     if (TELOPT_U(TELOPT_KERMIT)) {
  1017.         switch (sb) {
  1018.           case KERMIT_REQ_START:
  1019.             debug(F111,
  1020.                   "iks_wait KERMIT_REQ_START",
  1021.                   "u_start",
  1022.                   TELOPT_SB(TELOPT_KERMIT).kermit.u_start
  1023.                   );
  1024.             tn_siks(KERMIT_REQ_START);
  1025.             tn_wait_flg = 1;            /* Kermit Option MUST wait */
  1026.             do {
  1027.                 if (flushok)
  1028.                   tn_wait_idx = 0;
  1029.                 x = tn_wait("iks_wait() me_iks_req_start");
  1030.             } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
  1031.             tn_wait_flg = tn_wait_save;
  1032.             if (flushok)
  1033.               tn_wait_idx = 0;
  1034.         if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  1035.         /*
  1036.          * We are attempting to start a kermit server on the peer
  1037.          * the most likely reason is because we want to perform a
  1038.          * file transfer.  But there is a huge amount of non telnet
  1039.          * negotiation data coming in and so we have not been able
  1040.          * to find the response.  So we will lie and assume that
  1041.          * response is 'yes'.  The worse that will happen is that
  1042.          * a RESP_STOP is received after we enter protocol mode.
  1043.          * And the protocol operation will be canceled.
  1044.          */
  1045.         tn_push();
  1046.         return(1);
  1047.         } else {
  1048.         tn_push();
  1049.         return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
  1050.         }
  1051.           case KERMIT_REQ_STOP:
  1052.             debug(F111,
  1053.                   "iks_wait KERMIT_REQ_STOP",
  1054.                   "u_start",
  1055.                   TELOPT_SB(TELOPT_KERMIT).kermit.u_start
  1056.                   );
  1057.             tn_siks(KERMIT_REQ_STOP);
  1058.             tn_wait_flg = 1;            /* Kermit Option MUST wait */
  1059.             do {
  1060.                 if (flushok)
  1061.                   tn_wait_idx = 0;
  1062.                 x = tn_wait("iks_wait() me_iks_req_stop");
  1063.             } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
  1064.             tn_wait_flg = tn_wait_save;
  1065.             if (flushok)
  1066.               tn_wait_idx = 0;
  1067.  
  1068.         if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  1069.         /*
  1070.          * We are attempting to stop a kermit server on the peer
  1071.          * the most likely reason being that we want to enter
  1072.          * CONNECT mode.  But there is a huge amount of non telnet
  1073.          * negotiation data coming in and so we have not been able
  1074.          * to find the response.  So we will lie and assume that
  1075.          * the answer is 'yes' and allow the CONNECT command to
  1076.          * succeed.  The worst that happens is that CONNECT mode
  1077.          * swallows the incoming data displaying it to the user
  1078.          * and then it resumes Kermit client mode.
  1079.          */
  1080.         tn_push();
  1081.         return(1);
  1082.         } else {
  1083.         tn_push();
  1084.         return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
  1085.         }
  1086.         }
  1087.         tn_push();
  1088.     }
  1089.     return(1);
  1090. }
  1091.  
  1092. int
  1093. #ifdef CK_ANSIC
  1094. iks_tn_sb( char * sb, int n )
  1095. #else
  1096. iks_tn_sb( sb, n ) char * sb; int n;
  1097. #endif /* CK_ANSIC */
  1098. {
  1099. #ifndef NOXFER
  1100.     extern int server;
  1101. #ifdef NOICP
  1102.     extern int autodl;
  1103.     int inautodl = 0, cmdadl = 1;
  1104.     extern int local;
  1105. #else
  1106. #ifdef CK_AUTODL
  1107.     extern int autodl, inautodl, cmdadl;
  1108.     extern int local;
  1109. #endif /* CK_AUTODL */
  1110. #endif /* NOICP */
  1111.     switch (sb[0]) {
  1112.       case KERMIT_START:                /* START */
  1113.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
  1114.         return(4);
  1115.  
  1116.       case KERMIT_STOP:                 /* STOP */
  1117.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1118.         return(4);
  1119.  
  1120.       case KERMIT_REQ_START:            /* REQ-START */
  1121.         if (inserver) {
  1122. #ifdef CK_AUTODL
  1123.             cmdadl = 1;                 /* Turn on packet detection */
  1124. #endif /* CK_AUTODL */
  1125.             TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
  1126.             tn_siks(KERMIT_RESP_START);
  1127.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
  1128.             tn_siks(KERMIT_RESP_START);
  1129.         } else {
  1130. #ifdef CK_AUTODL
  1131.             if ((local && what == W_CONNECT && autodl) ||
  1132.                 (local && what != W_CONNECT && inautodl)
  1133.                 )
  1134.               tn_siks(KERMIT_RESP_START); /* STOP */
  1135.             else
  1136. #endif /* CK_AUTODL */
  1137.               tn_siks(KERMIT_RESP_STOP);
  1138.         }
  1139.         return(4);
  1140.  
  1141.       case KERMIT_REQ_STOP:             /* REQ-STOP */
  1142.         /* The protocol requires that the request be responded to */
  1143.         /* either by changing states or by reporting the current  */
  1144.         /* state.  */
  1145.  
  1146.         /* We need to provide the user some way of dictating what */
  1147.         /* the policies should be.  For instance, if we are in    */
  1148.         /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
  1149.         /* what should the proper response be?                    */
  1150.  
  1151.         if (inserver
  1152. #ifdef CK_AUTODL
  1153.             || !local && cmdadl
  1154. #endif /* CK_AUTODL */
  1155.             ) {
  1156. #ifdef CK_AUTODL
  1157.             cmdadl = 0;                 /* Turn off packet detection */
  1158. #endif /* CK_AUTODL */
  1159.             tn_siks(KERMIT_RESP_STOP);
  1160.         } else if (server) {
  1161.             extern int en_fin;
  1162.             if (en_fin) {               /* If the server is allowed to stop */
  1163.                 tn_siks(KERMIT_RESP_STOP);
  1164.             } else {                    /* We are not allowed to stop */
  1165.                 tn_siks(KERMIT_RESP_START);
  1166.             }
  1167. #ifdef CK_AUTODL
  1168.         } else if ((local && what == W_CONNECT && autodl) ||
  1169.                    (local && what != W_CONNECT && inautodl)
  1170.                    ) {
  1171.             /* If we are a pseudo-server and the other side requests */
  1172.             /* that we stop, tell then that we have even though we   */
  1173.             /* have not.  Otherwise, the other side might refuse to  */
  1174.             /* enter SERVER mode.                                    */
  1175.  
  1176.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  1177. #endif /* CK_AUTODL */
  1178.  
  1179.         } else {
  1180.             /* If we are not currently in any mode that accepts */
  1181.             /* Kermit packets then of course report that we are */
  1182.             /* not being a Kermit server.                       */
  1183.  
  1184.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  1185.         }
  1186.         return(4);
  1187.  
  1188.       case KERMIT_SOP: {                /* SOP */
  1189.           extern CHAR stchr;            /* Incoming SOP character */
  1190.           stchr = sb[1];
  1191.           TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
  1192.           return(4);
  1193.       }
  1194.  
  1195.       case KERMIT_RESP_START:           /* START */
  1196.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
  1197.         if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
  1198.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1199.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
  1200.             /* If we have issued a request to stop a Kermit Server */
  1201.             /* and the response is Start, then we must report this */
  1202.             /* to the caller.                                      */
  1203.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1204.         }
  1205.         return(4);
  1206.  
  1207.       case KERMIT_RESP_STOP:            /* STOP */
  1208.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1209.         if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
  1210.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1211.             /* If we have issued a request to start a Kermit Server */
  1212.             /* and the response is Stop, then we must report this   */
  1213.             /* to the caller.                                       */
  1214.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
  1215.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1216.         }
  1217.         return(4);
  1218.  
  1219.       default:
  1220.         return(0);
  1221.  
  1222.     } /* switch (sb[0]) */
  1223. #else
  1224.     return(0);
  1225. #endif /* NOXFER */
  1226. }
  1227. #endif /* IKS_OPTION */
  1228.  
  1229. /* Initialize telnet settings - set default values for ME and U modes */
  1230. int
  1231. tn_set_modes() {
  1232.     int opt,cmd;
  1233.  
  1234.     /* initialize all options to refuse in both directions */
  1235.     for (opt = 0; opt < NTELOPTS; opt++) {
  1236.         TELOPT_ME(opt) = 0;
  1237.         TELOPT_U(opt)  = 0;
  1238.         TELOPT_UNANSWERED_WILL(opt) = 0;
  1239.         TELOPT_UNANSWERED_DO(opt)   = 0;
  1240.         TELOPT_UNANSWERED_WONT(opt) = 0;
  1241.         TELOPT_UNANSWERED_DONT(opt)   = 0;
  1242.         TELOPT_UNANSWERED_SB(opt)   = 0;
  1243.         TELOPT_ME_MODE(opt) = TN_NG_RF;
  1244.         TELOPT_U_MODE(opt) = TN_NG_RF;
  1245.         TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
  1246.         TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
  1247.         TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
  1248.         TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
  1249.         for (cmd = 0; cmd < 4; cmd ++)
  1250.           tncnts[TELOPT_INDEX(opt)][cmd] = 0;
  1251.     }
  1252. #ifdef IKS_OPTION
  1253.     TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  1254.     TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1255.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1256.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1257.     TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
  1258. #endif /* IKS_OPTION */
  1259.  
  1260. #ifdef CK_ENCRYPTION
  1261.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1262. #endif /* CK_ENCRYPTION */
  1263.  
  1264. #ifdef  CK_NAWS
  1265.     TELOPT_SB(TELOPT_NAWS).naws.x = 0;
  1266.     TELOPT_SB(TELOPT_NAWS).naws.y = 0;
  1267. #endif /* CK_NAWS */
  1268.  
  1269. #ifdef CK_SSL
  1270.     TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
  1271.     TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
  1272. #endif /* CK_SSL */
  1273.  
  1274.     /* Now set the ones we want to accept to the proper values */
  1275.     TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
  1276.     TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
  1277.     TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
  1278.     TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
  1279.  
  1280.     TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
  1281.     TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
  1282.     TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
  1283.     TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
  1284.  
  1285.     TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1286.     TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1287.     TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1288.     TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1289.  
  1290. #ifdef IKS_OPTION
  1291.     TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1292.     TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1293.     TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1294.     TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1295. #endif /* IKS_OPTION */
  1296.  
  1297. #ifdef CK_ENCRYPTION
  1298.     TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1299.     TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1300.     TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1301.     TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1302. #endif /* CK_ENCRYPTION */
  1303.  
  1304.     TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
  1305.     TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
  1306.  
  1307. #ifdef CK_ENVIRONMENT
  1308.     TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
  1309. #endif /* CK_ENVIRONMENT */
  1310.  
  1311. #ifdef CK_AUTHENTICATION
  1312.     TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  1313. #endif /* CK_AUTHENTICATION */
  1314.  
  1315. #ifdef CK_SSL
  1316.     if (ck_ssleay_is_installed()) {
  1317.         TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
  1318.         TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
  1319.     }
  1320. #endif /* CK_SSL */
  1321.  
  1322. #ifdef CK_NAWS
  1323.     TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
  1324. #endif /* CK_NAWS */
  1325.  
  1326.     TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
  1327.     TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
  1328.  
  1329. #ifdef CK_ENVIRONMENT
  1330.     TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
  1331. #endif /* CK_ENVIRONMENT */
  1332.  
  1333. #ifdef CK_AUTHENTICATION
  1334.     TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  1335. #endif /* CK_AUTHENTICATION */
  1336.  
  1337. #ifdef CK_NAWS
  1338.     TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
  1339. #endif /* CK_NAWS */
  1340.  
  1341. #ifdef CK_SNDLOC
  1342.     TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
  1343. #endif /* CK_SNDLOC */
  1344.  
  1345. #ifdef CK_FORWARD_X
  1346.     TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_RQ;
  1347. #endif /* CK_FORWARD_X */
  1348.  
  1349.     /* Set the initial values for currently known mode */
  1350.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  1351.         if (TELOPT_OK(opt)) {
  1352.             TELOPT_ME_MODE(opt) = sstelnet ?
  1353.               TELOPT_DEF_S_ME_MODE(opt) :
  1354.                 TELOPT_DEF_C_ME_MODE(opt);
  1355.             TELOPT_U_MODE(opt) = sstelnet ?
  1356.               TELOPT_DEF_S_U_MODE(opt) :
  1357.                 TELOPT_DEF_C_U_MODE(opt);
  1358.         }
  1359.     }
  1360.     return(1);
  1361. }
  1362.  
  1363.  
  1364. /* Send Delayed Subnegotiations */
  1365.  
  1366. VOID
  1367. tn_sdsb() {
  1368.     if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
  1369.         tn_sttyp();
  1370.         TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
  1371.     }
  1372. #ifdef CK_ENVIRONMENT
  1373.     if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
  1374.         TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  1375.         tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
  1376.                  TELOPT_SB(TELOPT_NEWENVIRON).env.len);
  1377.         free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
  1378.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  1379.         TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
  1380.         TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
  1381.     }
  1382. #ifdef CK_XDISPLOC
  1383.     if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
  1384.         tn_sxdisploc();
  1385.         TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
  1386.     }
  1387. #endif /* CK_XDISPLOC */
  1388. #endif /* CK_ENVIRONMENT */
  1389. #ifdef CK_NAWS
  1390.     if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
  1391.         tn_snaws();
  1392.         TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
  1393.     }
  1394. #endif /* CK_NAWS */
  1395. #ifdef CK_SNDLOC
  1396.     if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
  1397.         tn_sndloc();
  1398.         TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
  1399.     }
  1400. #endif /* CK_SNDLOC */
  1401. #ifdef CK_FORWARD_X
  1402.     if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
  1403.         tn_sndfwdx();
  1404.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
  1405.     }
  1406. #endif /* CK_FORWARD_X */
  1407. }
  1408.  
  1409. int
  1410. tn_reset() {
  1411.     int x,opt,cmd;
  1412.  
  1413.     tn_wait_idx = 0;                    /* Clear the tn_push() buffer */
  1414.     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
  1415.  
  1416.     nflag = 0;
  1417.  
  1418.     /* Reset the TELNET OPTIONS counts */
  1419.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  1420.         if (TELOPT_OK(opt)) {
  1421.             TELOPT_ME(opt) = 0;
  1422.             TELOPT_U(opt)  = 0;
  1423.             TELOPT_UNANSWERED_WILL(opt) = 0;
  1424.             TELOPT_UNANSWERED_DO(opt)   = 0;
  1425.             TELOPT_UNANSWERED_WONT(opt) = 0;
  1426.             TELOPT_UNANSWERED_DONT(opt)   = 0;
  1427.             TELOPT_UNANSWERED_SB(opt)   = 0;
  1428.             TELOPT_ME_MODE(opt) = sstelnet ?
  1429.               TELOPT_DEF_S_ME_MODE(opt) :
  1430.                 TELOPT_DEF_C_ME_MODE(opt);
  1431.             TELOPT_U_MODE(opt) = sstelnet ?
  1432.               TELOPT_DEF_S_U_MODE(opt) :
  1433.                 TELOPT_DEF_C_U_MODE(opt);
  1434.  
  1435. #ifdef DEBUG
  1436.             if (deblog) {
  1437.                 switch (TELOPT_ME_MODE(opt)) {
  1438.                   case TN_NG_RF:
  1439.                     debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
  1440.                     break;
  1441.                   case TN_NG_AC:
  1442.                     debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
  1443.                     break;
  1444.                   case TN_NG_RQ:
  1445.                     debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
  1446.                     break;
  1447.                   case TN_NG_MU:
  1448.                     debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
  1449.                     break;
  1450.                 }
  1451.                 switch (TELOPT_U_MODE(opt)) {
  1452.                   case TN_NG_RF:
  1453.                     debug(F110,"tn_ini U  REFUSE ",TELOPT(opt),0);
  1454.                     break;
  1455.                   case TN_NG_AC:
  1456.                     debug(F110,"tn_ini U  ACCEPT ",TELOPT(opt),0);
  1457.                     break;
  1458.                   case TN_NG_RQ:
  1459.                     debug(F110,"tn_ini U  REQUEST",TELOPT(opt),0);
  1460.                     break;
  1461.                   case TN_NG_MU:
  1462.                     debug(F110,"tn_ini U  REQUIRE",TELOPT(opt),0);
  1463.                     break;
  1464.                 }
  1465.             }
  1466. #endif /* DEBUG */
  1467.             for (cmd = 0; cmd < 4; cmd ++)
  1468.               tncnts[TELOPT_INDEX(opt)][cmd] = 0;
  1469.         }
  1470.     }
  1471. #ifdef CK_ENVIRONMENT
  1472.     if (!tn_env_flg) {
  1473.         TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
  1474.         TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
  1475.     }
  1476. #endif /* CK_ENVIRONMENT */
  1477. #ifdef CK_SNDLOC
  1478.     if (!tn_loc)
  1479.         TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
  1480. #endif /* CK_SNDLOC */
  1481. #ifdef IKS_OPTION
  1482.     TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  1483.     TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1484.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1485.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1486.     TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
  1487. #endif /* IKS_OPTION */
  1488. #ifdef CK_ENCRYPTION
  1489.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1490.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
  1491. #endif /* CK_ENCRYPTION */
  1492. #ifdef  CK_NAWS
  1493.     TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
  1494.     TELOPT_SB(TELOPT_NAWS).naws.x = 0;
  1495.     TELOPT_SB(TELOPT_NAWS).naws.y = 0;
  1496. #endif /* CK_NAWS */
  1497.     TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
  1498.     TELOPT_SB(TELOPT_TTYPE).term.type[0] = '\0';
  1499. #ifdef CK_ENVIRONMENT
  1500.     TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
  1501.     if (tn_first)
  1502.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  1503.     else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  1504.         free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
  1505.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  1506.     }
  1507.     TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
  1508. #ifdef CK_XDISPLOC
  1509.     TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
  1510. #endif /* CK_XDISPLOC */
  1511. #endif /* CK_ENVIRONMENT */
  1512. #ifdef CK_SNDLOC
  1513.     TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
  1514. #endif /* CK_SNDLOC */
  1515. #ifdef CK_FORWARD_X
  1516.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
  1517.     if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1 ) {
  1518.  
  1519.     }
  1520.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
  1521.     for ( x=0 ; x<MAXFWDX ; x++ ) {
  1522.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
  1523.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
  1524.     }
  1525. #ifdef NT
  1526.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
  1527. #endif /* NT */
  1528. #endif /* CK_FORWARD_X */
  1529. #ifdef CK_SSL
  1530.     if (tls_only_flag || ssl_only_flag) {
  1531.         TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  1532.         TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  1533.     }
  1534.     TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
  1535.     TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
  1536. #endif /* CK_SSL */
  1537.  
  1538. #ifdef CK_ENCRYPTION
  1539.     if (!ck_crypt_is_installed()
  1540. #ifdef CK_SSL
  1541.         || tls_only_flag || ssl_only_flag
  1542. #endif /* CK_SSL */
  1543.         ) {
  1544.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1545.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1546.     }
  1547. #endif /* CK_ENCRYPTION */
  1548.  
  1549.     tn_first = 0;                       /* No longer the first time init */
  1550.  
  1551. #ifdef OS2
  1552.     ttnum = -1;                         /* Reset TermType negotiation */
  1553.     ttnumend = 0;
  1554. #endif /* OS2 */
  1555.  
  1556.     return(0);
  1557. }
  1558.  
  1559. /* Start a telnet connection. */
  1560. /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
  1561.  
  1562. int
  1563. tn_ini() {
  1564.     int wait, x, opt;
  1565.     debug(F101,"tn_ini ttnproto","",ttnproto);
  1566.     debug(F101,"tn_ini tn_init","",tn_init);
  1567.  
  1568.     if (ttnet != NET_TCPB)              /* Make sure connection is TCP/IP */
  1569.       return(0);
  1570.     if (tn_init)                        /* Have we done this already? */
  1571.       return(0);                        /* Don't do it again. */
  1572.  
  1573.     tn_reset();                         /* Reset telnet parameters */
  1574.  
  1575.     if (ttnproto == NP_RLOGIN) {        /* Reset flags even when RLOGIN */
  1576.         tn_init = 1;
  1577.         return(0);
  1578.     } else if (ttnproto == NP_NONE) {   /* If not talking to a telnet port, */
  1579.         ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
  1580.         tn_init = 1;                    /* but don't send initial options. */
  1581.         debug(F100,"tn_ini skipping telnet negotiations","",0);
  1582.         return(0);
  1583.     } else if (ttnproto == NP_TCPRAW) { /* Raw socket requested. */
  1584.         return(0);
  1585.     } else if (ttnproto == NP_KERMIT) {
  1586.         /* switching to Telnet protocol */
  1587.         debug(F100,"tn_start switching from Kermit to Telnet","",0);
  1588.         ttnproto = NP_TELNET;
  1589.     }
  1590.     debug(F111,"tn_start","sstelnet",sstelnet);
  1591.     wait = 0;
  1592.  
  1593. #ifdef CK_SSL
  1594.     if (!TELOPT_ME(TELOPT_START_TLS) &&
  1595.         TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
  1596.         if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
  1597.           return(-1);
  1598.         TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
  1599.         wait = 1;
  1600.     }
  1601.     if (!TELOPT_U(TELOPT_START_TLS) &&
  1602.         TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
  1603.         if (tn_sopt(DO, TELOPT_START_TLS) < 0)
  1604.           return(-1);
  1605.         TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
  1606.         wait = 1;
  1607.     }
  1608. #ifdef COMMENT
  1609. /*
  1610.   We can put off waiting for this until after we have requested AUTH.  The
  1611.   next draft will specify how the WILL side is to decide between these
  1612.   conflicting options.
  1613. */
  1614.     if (wait) {
  1615.         if (tn_wait("start_tls") < 0) {
  1616.             tn_push();
  1617.             return(-1);
  1618.         }
  1619.         wait = 0;
  1620.     }
  1621. #endif /* COMMENT */
  1622. #endif /* CK_SSL */
  1623.  
  1624. #ifdef CK_AUTHENTICATION
  1625.     if (tn_init)                /* tn_ini() might be called recursively */
  1626.       return(0);
  1627.     if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
  1628.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
  1629.         if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
  1630.           return(-1);
  1631.         TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
  1632.         wait = 1;
  1633.     }
  1634.     if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
  1635.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
  1636.         if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
  1637.           return(-1);
  1638.         TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
  1639.         wait = 1;
  1640.     }
  1641. #ifdef CK_ENCRYPTION
  1642.     if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
  1643.          TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
  1644.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1645.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1646.     }
  1647. #endif /* CK_ENCRYPTION */
  1648. #endif /* CK_AUTHENTICATION */
  1649.  
  1650. #ifdef CK_NAWS
  1651.     if (!sstelnet) {
  1652.         /* Console terminal screen rows and columns */
  1653. #ifdef OS2
  1654.         debug(F101,
  1655.               "tn_ini tt_rows 1",
  1656.               "",
  1657.               VscrnGetHeight(VTERM)-(tt_status?1:0)
  1658.               );
  1659.         debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
  1660.         /* Not known yet */
  1661.         if (VscrnGetWidth(VTERM) < 0 ||
  1662.             VscrnGetHeight(VTERM)-(tt_status?1:0) < 0) {
  1663.             ttgwsiz();                  /* Try to find out */
  1664.         }
  1665.         debug(F101,
  1666.               "tn_ini tt_rows 2",
  1667.               "",
  1668.               VscrnGetHeight(VTERM)-(tt_status?1:0)
  1669.               );
  1670.         debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
  1671.         /* Now do we know? */
  1672.         if (VscrnGetWidth(VTERM) > 0 &&
  1673.             VscrnGetHeight(VTERM)-(tt_status?1:0) > 0) {
  1674.             if (!TELOPT_ME(TELOPT_NAWS) &&
  1675.                 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  1676.                 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
  1677.                   return(-1);
  1678.                 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
  1679.                 wait = 1;
  1680.             }
  1681.         }
  1682. #else /* OS2 */
  1683.         debug(F101,"tn_ini tt_rows 1","",tt_rows);
  1684.         debug(F101,"tn_ini tt_cols 1","",tt_cols);
  1685.         if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
  1686.             ttgwsiz();                  /* Try to find out */
  1687.         }
  1688.         debug(F101,"tn_ini tt_rows 2","",tt_rows);
  1689.         debug(F101,"tn_ini tt_cols 2","",tt_cols);
  1690.         if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
  1691.             if (!TELOPT_ME(TELOPT_NAWS) &&
  1692.                 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  1693.                 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
  1694.                   return(-1);
  1695.                 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
  1696.                 wait = 1;
  1697.             }
  1698.         }
  1699. #endif /* OS2 */
  1700.     } else {
  1701.         if (!TELOPT_U(TELOPT_NAWS) &&
  1702.             TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  1703.             if (tn_sopt(DO, TELOPT_NAWS) < 0)
  1704.               return(-1);
  1705.             TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
  1706.             wait = 1;
  1707.         }
  1708.     }
  1709. #endif /* CK_NAWS */
  1710.  
  1711.     if (!TELOPT_ME(TELOPT_SGA) &&
  1712.         TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
  1713.         if (tn_sopt(WILL, TELOPT_SGA) < 0)
  1714.           return(-1);
  1715.         TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
  1716.         wait = 1;
  1717.     }
  1718.     if (!TELOPT_U(TELOPT_SGA) &&
  1719.         TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
  1720.         if (tn_sopt(DO, TELOPT_SGA) < 0)
  1721.           return(-1);
  1722.         TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
  1723.         wait = 1;
  1724.     }
  1725.     if (!tn_duplex) {
  1726.         if (!TELOPT_U(TELOPT_ECHO) &&
  1727.             TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
  1728.             if (tn_sopt(DO, TELOPT_ECHO) < 0)
  1729.               return(-1);
  1730.             TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
  1731.             wait = 1;
  1732.         }
  1733.     }
  1734.     if (!TELOPT_ME(TELOPT_ECHO) &&
  1735.         TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
  1736.         if (tn_sopt(WILL, TELOPT_ECHO) < 0)
  1737.           return(-1);
  1738.         TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
  1739.         wait = 1;
  1740.     }
  1741.  
  1742.     debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
  1743. /*
  1744.   Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
  1745.   Also send WILL NAWS if we know our screen dimensions.
  1746. */
  1747.     if (!TELOPT_ME(TELOPT_TTYPE) &&
  1748.         TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
  1749.         if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
  1750.             debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
  1751.             return(-1);
  1752.         }
  1753.         TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
  1754.         wait = 1;
  1755.         debug(F100,"tn_ini sent WILL TTYPE ok","",0);
  1756.     }
  1757.     if (!TELOPT_U(TELOPT_TTYPE) &&
  1758.         TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
  1759.         if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
  1760.             debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
  1761.             return(-1);
  1762.         }
  1763.         TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
  1764.         wait = 1;
  1765.         debug(F100,"tn_ini sent DO TTYPE ok","",0);
  1766.     }
  1767.     if (!TELOPT_ME(TELOPT_BINARY) &&
  1768.         TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
  1769.         if (tn_sopt(WILL, TELOPT_BINARY) < 0)
  1770.           return(-1);
  1771.         TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
  1772.         wait = 1;
  1773.     }
  1774.     if (!TELOPT_U(TELOPT_BINARY) &&
  1775.         TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
  1776.         if (tn_sopt(DO, TELOPT_BINARY) < 0)
  1777.           return(-1);
  1778.         TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
  1779.         wait = 1;
  1780.     }
  1781. #ifdef CK_SNDLOC
  1782.     if (tn_loc) {
  1783.         if (!TELOPT_ME(TELOPT_SNDLOC) &&
  1784.             TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
  1785.             if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
  1786.               return(-1);
  1787.             TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
  1788.             wait = 1;
  1789.         }
  1790.     }
  1791. #endif /* CK_SNDLOC */
  1792. #ifdef CK_ENVIRONMENT
  1793. #ifdef CK_XDISPLOC
  1794.     if (!TELOPT_ME(TELOPT_XDISPLOC) &&
  1795.          TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
  1796.         if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
  1797.             return(-1);
  1798.         TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
  1799.         wait = 1;
  1800.     }
  1801. #endif /* CK_XDISPLOC */
  1802.     /* Will send terminal environment. */
  1803.     if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
  1804.         TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
  1805.         if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
  1806.           return(-1);
  1807.         TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
  1808.         wait = 1;
  1809.     }
  1810.     if (!TELOPT_U(TELOPT_NEWENVIRON) &&
  1811.         TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
  1812.         if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
  1813.           return(-1);
  1814.         TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
  1815.         wait = 1;
  1816.     }
  1817. #endif /* CK_ENVIRONMENT */
  1818.  
  1819.     /* Take care of any other telnet options that require handling. */
  1820.  
  1821.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  1822.         switch (opt) {
  1823.           case TELOPT_AUTHENTICATION:
  1824.           case TELOPT_ENCRYPTION:
  1825.           case TELOPT_TTYPE:
  1826.           case TELOPT_NAWS:
  1827.           case TELOPT_BINARY:
  1828.           case TELOPT_NEWENVIRON:
  1829.           case TELOPT_SNDLOC:
  1830.           case TELOPT_XDISPLOC:
  1831.           case TELOPT_SGA:
  1832.           case TELOPT_ECHO:
  1833.           case TELOPT_KERMIT:
  1834.           case TELOPT_START_TLS:
  1835.             break;
  1836.           default:
  1837.             if (TELOPT_OK(opt)) {
  1838.                 if (!TELOPT_ME(opt) &&
  1839.                     TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
  1840.                     if (tn_sopt(WILL, opt) < 0)
  1841.                       return(-1);
  1842.                     TELOPT_UNANSWERED_WILL(opt) = 1;
  1843.                     wait = 1;
  1844.                 }
  1845.                 if (!TELOPT_U(opt) &&
  1846.                     TELOPT_U_MODE(opt) >= TN_NG_RQ) {
  1847.                     if (tn_sopt(DO, opt) < 0)
  1848.                       return(-1);
  1849.                     TELOPT_UNANSWERED_DO(opt) = 1;
  1850.                     wait = 1;
  1851.                 }
  1852.             }
  1853.         }
  1854.     }
  1855.     if (wait) {
  1856.         if (tn_wait("pre-encrypt") < 0) {
  1857.             tn_push();
  1858.             return(-1);
  1859.         }
  1860.         wait = 0;
  1861.     }
  1862.  
  1863. #ifdef CK_ENCRYPTION
  1864.     if (tn_init)                /* tn_ini() may be called recursively */
  1865.       return(0);
  1866.  
  1867.     if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
  1868.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
  1869.         if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
  1870.           return(-1);
  1871.         TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
  1872.         wait = 1;
  1873.     }
  1874.     if (!TELOPT_U(TELOPT_ENCRYPTION) &&
  1875.         TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
  1876.         if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
  1877.           return(-1);
  1878.         TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
  1879.         wait = 1;
  1880.     }
  1881.  
  1882.     /* If we are going to encrypt, we want to do it before we send any more */
  1883.     /* data, especially the terminal type and environment variables.        */
  1884.     if (wait) {
  1885.         if (tn_wait("post-encrypt") < 0) {
  1886.             tn_push();
  1887.             return(-1);
  1888.         }
  1889.         wait = 0;
  1890.     }
  1891. #endif /* CK_ENCRYPTION */
  1892.  
  1893.     tn_sdsb();
  1894.  
  1895.     if (tn_init)                   /* tn_ini() may be called recursively */
  1896.         return(0);
  1897.  
  1898. #ifdef IKS_OPTION
  1899.     /* Kermit Server negotiation must go last */
  1900.     /* Send U before ME */
  1901.  
  1902.     if (!TELOPT_U(TELOPT_KERMIT) &&
  1903.         TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
  1904.         if (tn_sopt(DO, TELOPT_KERMIT) < 0)
  1905.           return(-1);
  1906.         TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
  1907.         wait = 1;
  1908.     }
  1909.     if (!TELOPT_ME(TELOPT_KERMIT) &&
  1910.         TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
  1911.         if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
  1912.           return(-1);
  1913.         TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
  1914.         wait = 1;
  1915.     }
  1916. #endif /* IKS_OPTION */
  1917.  
  1918.     if (wait) {
  1919.         if (tn_wait("end of telnet negotiations") < 0) {
  1920.             tn_push();
  1921.             return(-1);
  1922.         }
  1923.         wait = 0;
  1924.     }
  1925.  
  1926.     tn_sdsb();                          /* Send delayed subnegotiations */
  1927.     tn_push();
  1928.     tn_init = 1;                        /* Remember successful completion. */
  1929.  
  1930.     /* Don't send anything else! */
  1931.  
  1932.     debug(F101,"tn_ini duplex","",duplex);
  1933.     debug(F101,"tn_ini done, tn_init","",tn_init);
  1934.     return(1);
  1935. }
  1936.  
  1937. VOID
  1938. tn_debug(s) char *s; {
  1939. #ifdef OS2
  1940.     void cwrite(unsigned short);
  1941.     char *p = s;
  1942.     _PROTOTYP (void os2bold, (void));
  1943. #endif /* OS2 */
  1944.  
  1945.     if (!(tn_deb || debses))
  1946.       return;
  1947.     debug(F111,"tn_debug",s,what);
  1948. #ifdef OS2
  1949.     if ( what == W_COMMAND ) {
  1950.         extern unsigned char colorcmd;
  1951.         colorcmd ^= 0x8 ;
  1952.         printf("%s\r\n",s);
  1953.         colorcmd ^= 0x8 ;
  1954.     }
  1955.     if (!scrninitialized[VTERM]) {
  1956.         USHORT x,y;
  1957.         checkscreenmode();
  1958.         GetCurPos(&y, &x);
  1959.         SaveCmdMode(x+1,y+1);
  1960.         scrninit();
  1961.         RestoreCmdMode();
  1962.     }
  1963.     os2bold();                          /* Toggle boldness */
  1964.     while (*p)
  1965.       cwrite((CHAR) *p++);              /* Go boldly ... */
  1966.     os2bold();                          /* Toggle boldness back */
  1967.     if (debses) {
  1968.         debses = 0;
  1969.         cwrite((CHAR) '\015');
  1970.         cwrite((CHAR) '\012');
  1971.         debses = 1;
  1972.     } else {
  1973.         cwrite((CHAR) '\015');
  1974.         cwrite((CHAR) '\012');
  1975.     }
  1976. #else
  1977.     if (what != W_CONNECT && what != W_COMMAND)
  1978.       return;                           /* CONNECT/command must be active */
  1979.     conoll(s);
  1980. #endif /* OS2 */
  1981. }
  1982.  
  1983. /*
  1984.   Process in-band Telnet negotiation characters from the remote host.
  1985.   Call with the telnet IAC character and the current duplex setting
  1986.   (0 = remote echo, 1 = local echo), and a pointer to a function to call
  1987.   to read more characters.  Returns:
  1988.     6 if DO LOGOUT was received and accepted
  1989.     5 if the Kermit start of packet character has changed
  1990.     4 if state of remote Internet Kermit Service has changed
  1991.     3 if a quoted IAC was received
  1992.     2 if local echo must be changed to remote
  1993.     1 if remote echo must be changed to local
  1994.     0 if nothing happens or no action necessary
  1995.    -1 on failure (= internal or i/o error)
  1996. */
  1997. #ifdef IKS_OPTION
  1998. int
  1999. tn_siks(cmd) int cmd; {         /* TELNET SEND IKS SUB */
  2000. #ifndef NOXFER
  2001.     CHAR buf[8];
  2002.     extern CHAR mystch;                 /* Outgoing Start of Packet Char */
  2003.     int n,m;
  2004.  
  2005.     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
  2006.     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
  2007.     if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
  2008.       return(-1);
  2009.  
  2010. #ifdef CK_SSL
  2011.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  2012.         return(0);
  2013.     }
  2014. #endif /* CK_SSL */
  2015.     if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
  2016.         TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
  2017.     } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
  2018.         TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  2019.     } else if (cmd == KERMIT_REQ_STOP)
  2020.       TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
  2021.     else if (cmd == KERMIT_REQ_START)
  2022.       TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
  2023.  
  2024.     if (cmd == KERMIT_SOP) {
  2025.         buf[0] = (CHAR) IAC;
  2026.         buf[1] = (CHAR) SB;
  2027.         buf[2] = (CHAR) TELOPT_KERMIT;
  2028.         buf[3] = (CHAR) (cmd & 0xff);
  2029.         buf[4] = (CHAR) mystch;
  2030.         buf[5] = (CHAR) IAC;
  2031.         buf[6] = (CHAR) SE;
  2032.         buf[7] = (CHAR) 0;
  2033.         if (tn_deb || debses || deblog) {
  2034.             sprintf(tn_msg,"TELNET SENT SB KERMIT SOP %02X IAC SE",mystch);
  2035.             debug(F101,tn_msg,"",cmd);
  2036.             if (tn_deb || debses) tn_debug(tn_msg);
  2037.         }
  2038.         if (ttol(buf,7) < 7)
  2039.           return(-1);
  2040.     } else {
  2041.         buf[0] = (CHAR) IAC;
  2042.         buf[1] = (CHAR) SB;
  2043.         buf[2] = (CHAR) TELOPT_KERMIT;
  2044.         buf[3] = (CHAR) (cmd & 0xff);
  2045.         buf[4] = (CHAR) IAC;
  2046.         buf[5] = (CHAR) SE;
  2047.         buf[6] = (CHAR) 0;
  2048.         if (tn_deb || debses || deblog) {
  2049.             char * s = 0;
  2050.             switch (cmd) {
  2051.               case KERMIT_START: s = "START"; break;
  2052.               case KERMIT_STOP: s = "STOP"; break;
  2053.               case KERMIT_REQ_START: s = "REQ-START"; break;
  2054.               case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
  2055.               case KERMIT_RESP_START: s = "RESP-START"; break;
  2056.               case KERMIT_RESP_STOP:  s = "RESP-STOP"; break;
  2057.             }
  2058.             sprintf(tn_msg,"TELNET SENT SB kermit %s IAC SE",s);
  2059.             debug(F101,tn_msg,"",cmd);
  2060.             if (tn_deb || debses) tn_debug(tn_msg);
  2061.         }
  2062.         if (ttol(buf,6) < 6)
  2063.           return(-1);
  2064.     }
  2065.     return(1);
  2066. #else
  2067.     return(-1);
  2068. #endif /* NOXFER */
  2069. }
  2070. #endif /* IKS_OPTION */
  2071.  
  2072. /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
  2073. /* returns <= 0 on error, 1 on success */
  2074. /* the length returned includes the IAC SE bytes */
  2075.  
  2076. int
  2077. #ifdef CK_ANSIC                         /* TELNET SB */
  2078. tn_sb( int opt, int * len, int (*fn)(int) )
  2079. #else
  2080. tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
  2081. #endif /* CK_ANSIC */
  2082. /* tn_sb */ {
  2083.     int c, x, y, n, m, flag;
  2084.     debug(F100,"Entering tn_sb()","",0);
  2085.     *len = 0;                   /* Initialize Len to 0 */
  2086.     n = flag = 0;               /* Flag for when done reading SB */
  2087.     while (n < TSBUFSIZ) {      /* Loop looking for IAC SE */
  2088.         if ((y = (*fn)(0)) < 0) /* Read a byte */
  2089.           return(y);
  2090.         y &= 0xff;              /* Make sure it's just 8 bits. */
  2091.         sb[n++] = (char) y;     /* Deposit in buffer. */
  2092.         if (seslog && sessft == XYFT_D) { /* Take care of session log */
  2093.             logchar((char) y);
  2094.         }
  2095.         if (y == IAC) {         /* If this is an IAC                */
  2096.             if (flag) {         /* If previous char was IAC         */
  2097.                 n--;            /* it's quoted, keep one IAC        */
  2098.                 flag = 0;       /* and turn off the flag.           */
  2099.             } else flag = 1;    /* Otherwise set the flag.          */
  2100.         } else if (flag) {      /* Something else following IAC     */
  2101.             if (y == SE)        /* If not SE, it's a protocol error */
  2102.               break;
  2103.             else if (y == DONT) { /* Used DONT instead of SE */
  2104.                 debug(F100,
  2105.                       "TELNET Subnegotiation error - used DONT instead of SE!",
  2106.                       ""
  2107.                       ,0
  2108.                       );
  2109.                 if (tn_deb || debses)
  2110.                   tn_debug(
  2111.                      "TELNET Subnegotiation error - used DONT instead of SE!");
  2112.                 flag = 3;
  2113.                 break;
  2114.             } else {            /* Other protocol error */
  2115.                 flag = 0;
  2116.                 break;
  2117.             }
  2118.         }
  2119. #ifdef COMMENT
  2120.         /* This test is sure to be triggered when we are using encryption */
  2121.         /* Therefore, we must take it out, otherwise, our subnegotiations */
  2122.         /* will be truncated and failure will result.                     */
  2123.         /* This bug was only seen on BeOS DR7 and has been fixed.         */
  2124.         else if (!flag && y == SE) { /* Forgot the IAC ? */
  2125.             flag = 2;
  2126.             debug(F100,
  2127.                    "TELNET Subnegotiation error - forgot the IAC before SE!",
  2128.                    "",
  2129.                   0
  2130.                   );
  2131.             if (tn_deb || debses)
  2132.               tn_debug(
  2133. "TELNET Subnegotiation error - forgot the IAC before SE!");
  2134.             break;
  2135.         }
  2136. #endif /* COMMENT */
  2137.  
  2138. #ifdef CK_FORWARD_X
  2139.         if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
  2140.              n == (TSBUFSIZ-2) ) {
  2141.             /* do not let the buffer over flow */
  2142.             /* write the data to the channel and continue processing */
  2143.             /* the incoming data until IAC SE is reached. */
  2144.             sb[n++] = IAC;
  2145.             sb[n++] = SE;
  2146.             if ( deblog || tn_deb || debses ) {
  2147.                 int i;
  2148.                 sprintf(tn_msg,"TELNET RCVD SB %s DATA ",TELOPT(opt));
  2149. #ifdef HEXDISP
  2150.                 {
  2151.                     int was_hex = 1;
  2152.                     for (i=1; i < n-2; i++) {
  2153.                         if (sb[i] < 32 || sb[i] >= 127) {
  2154.                             sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",sb[i]);
  2155.                             was_hex = 1;
  2156.                         } else {
  2157.                             sprintf(hexbuf,"%s%c",was_hex?"\"":"",sb[i]);
  2158.                             was_hex = 0;
  2159.                         }
  2160.                         strcat(tn_msg,hexbuf);
  2161.                     }
  2162.                     if (!was_hex)
  2163.                         strcat(tn_msg,"\" ");
  2164.                 }
  2165. #else /* HEXDISP */
  2166.                 memcpy(hexbuf,&sb[i],n-i-2);
  2167.                 hexbuf[n-i-2] = ' ';
  2168.                 hexbuf[n-i-1] = '\0';
  2169.                 strcat(tn_msg,hexbuf);
  2170. #endif /* HEXDISP */
  2171.                 if (flag == 2)
  2172.                     strcat(tn_msg,"SE");
  2173.                 else if (flag == 3)
  2174.                     strcat(tn_msg," IAC DONT");
  2175.                 else
  2176.                     strcat(tn_msg," IAC SE");
  2177.                 debug(F100,tn_msg,"",0);
  2178.                 if (tn_deb || debses)
  2179.                     tn_debug(tn_msg);
  2180.             }
  2181.  
  2182.             if ( fwdx_tn_sb(sb,n) < 0 )
  2183.                 return(0);
  2184.  
  2185.             /* reset leave the msg type and channel number in place */
  2186.             n = 3;
  2187.         }
  2188. #endif /* CK_FORWARD_X */
  2189.     }
  2190.     debug(F111,"tn_sb end of while loop","flag",flag);
  2191.     if (!flag) {                        /* Make sure we got a valid SB */
  2192.         debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
  2193.         if (tn_deb || debses)
  2194.           tn_debug("TELNET Subnegotiation prematurely broken");
  2195.         /* Was -1 but that would be an I/O error, so absorb it and go on. */
  2196.         return(0);
  2197.     }
  2198.     if (deblog || tn_deb || debses) {
  2199.         int i;
  2200.         char * s[16];
  2201.         for (i = 0; i < 16; i++)
  2202.           s[i] = "";
  2203.         if (opt == TELOPT_NAWS) {
  2204.             i = 0;
  2205.         } else {
  2206.             i = 1;
  2207.             s[0] = "UNKNOWN";
  2208.  
  2209.             switch (sb[0]) {
  2210.               case 0:
  2211.                 if (opt == TELOPT_FORWARD_X)
  2212.                   s[0] = "SCREEN";
  2213.                 else if (opt == TELOPT_KERMIT)
  2214.                   s[0] = "START";
  2215.                 else if (opt == TELOPT_LFLOW)
  2216.                   s[0] = "OFF";
  2217.                 else
  2218.                   s[0] = "IS";
  2219.                 if (opt == TELOPT_ENCRYPTION) {
  2220.                     i++;
  2221.                     if (sb[1] < ENCTYPE_CNT) {
  2222.                         s[1] = enctype_names[sb[1]];
  2223.                         i++;
  2224.                         switch(sb[2]) {
  2225.                           case 1:
  2226.                             s[2] = "FB64_IV";
  2227.                             break;
  2228.                           case 2:
  2229.                             s[2] = "FB64_IV_OK";
  2230.                             break;
  2231.                           case 3:
  2232.                             s[2] = "FB64_IV_BAD";
  2233.                             break;
  2234.                           case 4:
  2235.                             s[2] = "FB64_CHALLENGE";
  2236.                             break;
  2237.                           case 5:
  2238.                             s[2] = "FB64_RESPONSE";
  2239.                             break;
  2240.                         }
  2241.                     } else {
  2242.                         s[1] = "UNKNOWN";
  2243.                     }
  2244.                 }
  2245.                 if (opt == TELOPT_AUTHENTICATION) {
  2246.                     i += 2;
  2247.                     s[1] = AUTHTYPE_NAME(sb[1]);
  2248.                     s[2] = AUTHMODE_NAME(sb[2]);
  2249.                     if (sb[1]) {
  2250.                         i++;
  2251.                         switch (sb[3]) {
  2252.                           case 0:
  2253.                             switch (sb[1]) {
  2254.                               case AUTHTYPE_NTLM:
  2255.                                 s[3] = "NTLM_AUTH";
  2256.                                 break;
  2257.                               default:
  2258.                                 s[3] = "AUTH";
  2259.                             }
  2260.                             break;
  2261.                           case 1:
  2262.                             switch (sb[1]) {
  2263.                               case AUTHTYPE_SSL:
  2264.                                 s[3] = "START";
  2265.                                 break;
  2266.                               case AUTHTYPE_NTLM:
  2267.                                 s[3] = "NTLM_CHALLENGE";
  2268.                                 break;
  2269.                               default:
  2270.                                 s[3] = "REJECT";
  2271.                             }
  2272.                             break;
  2273.                           case 2:
  2274.                             switch (sb[1]) {
  2275.                               case AUTHTYPE_NTLM:
  2276.                                 s[3] = "NTLM_RESPONSE";
  2277.                                 break;
  2278.                               default:
  2279.                                 s[3] = "ACCEPT";
  2280.                             }
  2281.                             break;
  2282.                           case 3:
  2283.                             switch (sb[1]) {
  2284.                               case AUTHTYPE_NTLM:
  2285.                                 s[3] = "NTLM_ACCEPT";
  2286.                                 break;
  2287.                               case 1:   /* KERBEROS_v4 */
  2288.                               case 5:   /* SRP */
  2289.                                 s[3] = "CHALLENGE";
  2290.                                 break;
  2291.                               case 2:   /* KERBEROS_v5 */
  2292.                                 s[3] = "RESPONSE";
  2293.                                 break;
  2294.                               case AUTHTYPE_SSL:
  2295.                                 s[3] = "REJECT";
  2296.                                 break;
  2297.                             }
  2298.                             break;
  2299.                           case 4:
  2300.                             switch (sb[1]) {
  2301.                               case AUTHTYPE_NTLM:
  2302.                                 s[3] = "NTLM_REJECT";
  2303.                                 break;
  2304.                               case 1:   /* KERBEROS_V4 */
  2305.                               case 5:   /* SRP */
  2306.                                 s[3] = "RESPONSE";
  2307.                                 break;
  2308.                               case 2:   /* KERBEROS_V5 */
  2309.                                 s[3] = "FORWARD";
  2310.                                 break;
  2311.                             }
  2312.                             break;
  2313.                           case 5:
  2314.                             switch (sb[1]) {
  2315.                               case 5:   /* SRP */
  2316.                                 s[3] = "FORWARD";
  2317.                                 break;
  2318.                               case 2:   /* KERBEROS_V5 */
  2319.                                 s[3] = "FORWARD_ACCEPT";
  2320.                                 break;
  2321.                             }
  2322.                             break;
  2323.                           case 6:
  2324.                             switch (sb[1]) {
  2325.                               case 5:   /* SRP */
  2326.                                 s[3] = "FORWARD_ACCEPT";
  2327.                                 break;
  2328.                               case 2: /* KERBEROS_V5 */
  2329.                                 s[3] = "FORWARD_REJECT";
  2330.                                 break;
  2331.                             }
  2332.                             break;
  2333.                           case 7:
  2334.                             switch (sb[1]) {
  2335.                               case 5:   /* SRP */
  2336.                                 s[3] = "FORWARD_REJECT";
  2337.                                 break;
  2338.                             }
  2339.                             break;
  2340.                           case 8:
  2341.                             switch (sb[1]) {
  2342.                               case 5: /* SRP */
  2343.                                 s[3] = "EXP";
  2344.                                 break;
  2345.                             }
  2346.                             break;
  2347.                           case 9:
  2348.                             switch (sb[1]) {
  2349.                               case 5: /* SRP */
  2350.                                 s[3] = "PARAMS";
  2351.                                 break;
  2352.                             }
  2353.                             break;
  2354.                         }
  2355.                     }
  2356.                 }
  2357.                 break;
  2358.               case 1:
  2359.                 switch (opt) {
  2360.                   case TELOPT_FORWARD_X:
  2361.                     s[0] = "OPEN";
  2362.                     break;
  2363.                   case TELOPT_LFLOW:
  2364.                     s[0] = "ON";
  2365.                     break;
  2366.                   case TELOPT_KERMIT:
  2367.                     s[0] = "STOP";
  2368.                     break;
  2369.                   case TELOPT_AUTHENTICATION:
  2370.                     s[0] = "SEND";
  2371.                     hexbuf[0] = '\0';
  2372.                     for (; i < n-2; i += 2) {
  2373.                         sprintf(tn_msg,
  2374.                                 "%s %s ",
  2375.                                 authtype_names[sb[i]],
  2376.                                 authmode_names[sb[i+1]]
  2377.                                 );
  2378.                         strcat(hexbuf,tn_msg);
  2379.                     }
  2380.                     s[1] = hexbuf;
  2381.                     break;
  2382.  
  2383.                   case TELOPT_ENCRYPTION:
  2384.                     s[0] = "SUPPORT";
  2385.                     while (i < n-2) {
  2386.                         s[i] = enctype_names[sb[i]];
  2387.                         i++;
  2388.                     }
  2389.                     break;
  2390.  
  2391.                   case TELOPT_START_TLS:
  2392.                     s[0] = "FOLLOWS";
  2393.                     break;
  2394.                   default:
  2395.                     s[0] = "SEND";
  2396.                 }
  2397.                 break;
  2398.  
  2399.               case 2:
  2400.                 switch (opt) {
  2401.                 case TELOPT_FORWARD_X:
  2402.                     s[0] = "CLOSE";
  2403.                     break;
  2404.                   case TELOPT_LFLOW:
  2405.                     s[0] = "RESTART-ANY";
  2406.                     break;
  2407.                   case TELOPT_KERMIT:
  2408.                     s[0] = "REQ-START";
  2409.                     break;
  2410.                   case TELOPT_NEWENVIRON:
  2411.                     s[0] = "INFO";
  2412.                     break;
  2413.                   case TELOPT_AUTHENTICATION:
  2414.                     s[0] = "REPLY";
  2415.                     i=4;
  2416.                     s[1] = authtype_names[sb[1]];
  2417.                     s[2] = authmode_names[sb[2]];
  2418.                     switch (sb[3]) {
  2419.                       case 0:
  2420.                         switch (sb[1]) {
  2421.                           case AUTHTYPE_NTLM:
  2422.                             s[3] = "NTLM_AUTH";
  2423.                             break;
  2424.                           default:
  2425.                             s[3] = "AUTH";
  2426.                         }
  2427.                         break;
  2428.                       case 1:
  2429.                         switch (sb[1]) {
  2430.                           case AUTHTYPE_NTLM:
  2431.                             s[3] = "NTLM_CHALLENGE";
  2432.                             break;
  2433.                           default:
  2434.                             s[3] = "REJECT";
  2435.                         }
  2436.                         break;
  2437.                       case 2:
  2438.                         switch (sb[1]) {
  2439.                           case AUTHTYPE_NTLM:
  2440.                             s[3] = "NTLM_RESPONSE";
  2441.                             break;
  2442.                           default:
  2443.                             s[3] = "ACCEPT";
  2444.                         }
  2445.                         break;
  2446.                       case 3:
  2447.                         switch (sb[1]) {
  2448.                           case AUTHTYPE_NTLM:
  2449.                             s[3] = "NTLM_ACCEPT";
  2450.                             break;
  2451.                           case AUTHTYPE_KERBEROS_V4:
  2452.                           case AUTHTYPE_SRP:
  2453.                             s[3] = "CHALLENGE";
  2454.                             break;
  2455.                           case AUTHTYPE_KERBEROS_V5:
  2456.                             s[3] = "RESPONSE";
  2457.                             break;
  2458.                         }
  2459.                         break;
  2460.                       case 4:
  2461.                         switch (sb[1]) {
  2462.                           case AUTHTYPE_NTLM:
  2463.                             s[3] = "NTLM_REJECT";
  2464.                             break;
  2465.                           case AUTHTYPE_KERBEROS_V4:
  2466.                           case AUTHTYPE_SRP:
  2467.                             s[3] = "RESPONSE";
  2468.                             break;
  2469.                           case AUTHTYPE_KERBEROS_V5:
  2470.                             s[3] = "FORWARD";
  2471.                             break;
  2472.                         }
  2473.                         break;
  2474.                       case 5:
  2475.                         switch (sb[1]) {
  2476.                           case AUTHTYPE_SRP:
  2477.                             s[3] = "FORWARD";
  2478.                             break;
  2479.                           case AUTHTYPE_KERBEROS_V5:
  2480.                             s[3] = "FORWARD_ACCEPT";
  2481.                             break;
  2482.                         }
  2483.                         break;
  2484.                       case 6:
  2485.                         switch (sb[1]) {
  2486.                           case AUTHTYPE_SRP:
  2487.                             s[3] = "FORWARD_ACCEPT";
  2488.                             break;
  2489.                           case AUTHTYPE_KERBEROS_V5:
  2490.                             s[3] = "FORWARD_REJECT";
  2491.                             break;
  2492.                         }
  2493.                         break;
  2494.                       case 7:
  2495.                         switch (sb[1]) {
  2496.                           case AUTHTYPE_SRP:
  2497.                             s[3] = "FORWARD_REJECT";
  2498.                             break;
  2499.                         }
  2500.                         break;
  2501.                       case 8:
  2502.                         switch (sb[1]) {
  2503.                           case AUTHTYPE_SRP:
  2504.                             s[3] = "EXP";
  2505.                             break;
  2506.                         }
  2507.                         break;
  2508.                       case 9:
  2509.                         switch (sb[1]) {
  2510.                           case AUTHTYPE_SRP:
  2511.                             s[3] = "PARAMS";
  2512.                             break;
  2513.                         }
  2514.                         break;
  2515.                     }
  2516.                     break;
  2517.                   case TELOPT_ENCRYPTION:
  2518.                     s[0] = "REPLY";
  2519.                     s[1] = enctype_names[sb[1]];
  2520.                     i++;
  2521.                     switch (sb[2]) {
  2522.                       case 1:
  2523.                         i++;
  2524.                         s[2] = "FB64_IV";
  2525.                         break;
  2526.                       case 2:
  2527.                         i++;
  2528.                         s[2] = "FB64_IV_OK";
  2529.                         break;
  2530.                       case 3:
  2531.                         i++;
  2532.                         s[2] = "FB64_IV_BAD";
  2533.                         break;
  2534.                       case 4:
  2535.                         i++;
  2536.                         s[2] = "FB64_CHALLENGE";
  2537.                         break;
  2538.                       case 5:
  2539.                         i++;
  2540.                         s[2] = "FB64_RESPONSE";
  2541.                         break;
  2542.                     }
  2543.                     break;
  2544.                 }
  2545.                 break;
  2546.               case 3:
  2547.                 switch (opt) {
  2548.                   case TELOPT_FORWARD_X:
  2549.                     s[0] = "DATA";
  2550.                     break;
  2551.                   case TELOPT_LFLOW:
  2552.                     s[0] = "RESTART-XON";
  2553.                     break;
  2554.                   case TELOPT_KERMIT:
  2555.                     s[0] = "REQ-STOP";
  2556.                     break;
  2557.                   case TELOPT_AUTHENTICATION:
  2558.                     s[0] = "NAME";
  2559.                     break;
  2560.                   case TELOPT_ENCRYPTION:
  2561.                     s[0] = "START";
  2562.                     break;
  2563.                 }
  2564.                 break;
  2565.               case 4:
  2566.                 switch (opt) {
  2567.                   case TELOPT_KERMIT:
  2568.                     s[0] = "SOP";
  2569.                     break;
  2570.                   case TELOPT_ENCRYPTION:
  2571.                     s[0] = "END";
  2572.                     break;
  2573.                 }
  2574.                 break;
  2575.               case 5:
  2576.                 switch (opt) {
  2577.                 case TELOPT_ENCRYPTION:
  2578.                     s[0] = "REQUEST-START";
  2579.                     break;
  2580.                 }
  2581.                 break;
  2582.               case 6:
  2583.                 switch (opt) {
  2584.                   case TELOPT_ENCRYPTION:
  2585.                     s[0] = "REQUEST-END";
  2586.                     break;
  2587.                 }
  2588.                 break;
  2589.               case 7:
  2590.                 switch (opt) {
  2591.                   case TELOPT_ENCRYPTION:
  2592.                     s[0] = "ENC-KEYID";
  2593.                     break;
  2594.                 }
  2595.                 break;
  2596.               case 8:
  2597.                 switch (opt) {
  2598.                   case TELOPT_KERMIT:
  2599.                     s[0] = "RESP-START";
  2600.                     break;
  2601.                   case TELOPT_ENCRYPTION:
  2602.                     s[0] = "DEC-KEYID";
  2603.                     break;
  2604.                 }
  2605.                 break;
  2606.               case 9:
  2607.                 switch (opt) {
  2608.                   case TELOPT_KERMIT:
  2609.                     s[0] = "RESP-STOP";
  2610.                     break;
  2611.                 }
  2612.                 break;
  2613.             }
  2614.         }
  2615. #ifdef M_XENIX
  2616.         {
  2617.           int len, param, param_len;
  2618.           sprintf(tn_msg,
  2619.                 "TELNET RCVD SB %s ",
  2620.                 TELOPT(opt));
  2621.           len = strlen(tn_msg);
  2622.           for (param = 0; param <= 15; param++) {
  2623.             param_len = strlen(s[param]);
  2624.             if (param_len > 0) {
  2625.               strcpy(&tn_msg[len], s[param]);
  2626.               len += param_len;
  2627.               tn_msg[len++] = ' ';
  2628.             }
  2629.           }
  2630.           tn_msg[len] = '\0';
  2631.         }
  2632. #else
  2633.         sprintf(tn_msg,
  2634.                 "TELNET RCVD SB \
  2635. %s %s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  2636.                 TELOPT(opt),s[0],
  2637.                  s[ 1], s[ 1][0]?" ":"",
  2638.                  s[ 2], s[ 2][0]?" ":"",
  2639.                  s[ 3], s[ 3][0]?" ":"",
  2640.                  s[ 4], s[ 4][0]?" ":"",
  2641.                  s[ 5], s[ 5][0]?" ":"",
  2642.                  s[ 6], s[ 6][0]?" ":"",
  2643.                  s[ 7], s[ 7][0]?" ":"",
  2644.                  s[ 8], s[ 8][0]?" ":"",
  2645.                  s[ 9], s[ 9][0]?" ":"",
  2646.                  s[10], s[10][0]?" ":"",
  2647.                  s[11], s[11][0]?" ":"",
  2648.                  s[12], s[12][0]?" ":"",
  2649.                  s[13], s[13][0]?" ":"",
  2650.                  s[14], s[14][0]?" ":"",
  2651.                  s[15], s[15][0]?" ":"");
  2652. #endif /* M_XENIX */
  2653. #ifdef HEXDISP
  2654.         {
  2655.             int was_hex = 1;
  2656.             for (; i < n-2; i++) {
  2657.                 if (sb[i] < 32 || sb[i] >= 127) {
  2658.                     sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",sb[i]);
  2659.                     was_hex = 1;
  2660.                 } else {
  2661.                     sprintf(hexbuf,"%s%c",was_hex?"\"":"",sb[i]);
  2662.                     was_hex = 0;
  2663.                 }
  2664.                 strcat(tn_msg,hexbuf);
  2665.             }
  2666.             if (!was_hex)
  2667.               strcat(tn_msg,"\" ");
  2668.         }
  2669. #else /* HEXDISP */
  2670.         memcpy(hexbuf,&sb[i],n-i-2);
  2671.         hexbuf[n-i-2] = ' ';
  2672.         hexbuf[n-i-1] = '\0';
  2673.         strcat(tn_msg,hexbuf);
  2674. #endif /* HEXDISP */
  2675.         if (flag == 2)
  2676.           strcat(tn_msg,"SE");
  2677.         else if (flag == 3)
  2678.           strcat(tn_msg," IAC DONT");
  2679.         else
  2680.           strcat(tn_msg," IAC SE");
  2681.         debug(F100,tn_msg,"",0);
  2682.         if (tn_deb || debses)
  2683.           tn_debug(tn_msg);
  2684.     }
  2685.     *len = n;           /* return length */
  2686.     return(1);          /* success */
  2687. }
  2688.  
  2689. static char rows_buf[16] = { 0, 0 }; /* LINES Environment variable */
  2690. static char cols_buf[16] = { 0, 0 }; /* COLUMNS Enviornment variable */
  2691. static char term_buf[64] = { 0, 0 }; /* TERM Environment variable */
  2692.  
  2693. #ifdef CK_CURSES
  2694. #ifndef VMS
  2695. #ifndef COHERENT
  2696. _PROTOTYP(int tgetent,(char *, char *));
  2697. #endif /* COHERENT */
  2698. #else
  2699. #ifdef __DECC
  2700. _PROTOTYP(int tgetent,(char *, char *));
  2701. #endif /* __DECC */
  2702. #endif /* VMS */
  2703. extern char * trmbuf;                   /* Real curses */
  2704. #endif /* CK_CURSES */
  2705.  
  2706. #ifdef CK_ENCRYPTION
  2707. static int
  2708. tn_no_encrypt()
  2709. {
  2710.     /* Prevent Encryption from being negotiated */
  2711.     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2712.     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2713.  
  2714.     /* Cancel any negotiation that might have started */
  2715.     ck_tn_enc_stop();
  2716.  
  2717.     if (TELOPT_ME(TELOPT_ENCRYPTION) ||
  2718.          TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION)) {
  2719.         TELOPT_ME(TELOPT_ENCRYPTION) = 0;
  2720.         if (tn_sopt(WONT,TELOPT_ENCRYPTION) < 0)
  2721.             return(-1);
  2722.         TELOPT_UNANSWERED_WONT(TELOPT_ENCRYPTION) = 1;
  2723.     }
  2724.     if (TELOPT_U(TELOPT_ENCRYPTION) ||
  2725.          TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION)) {
  2726.         TELOPT_U(TELOPT_ENCRYPTION) = 0;
  2727.         if (tn_sopt(DONT,TELOPT_ENCRYPTION) < 0)
  2728.             return(-1);
  2729.         TELOPT_UNANSWERED_DONT(TELOPT_ENCRYPTION) = 1;
  2730.     }
  2731.     return(0);
  2732. }
  2733. #endif /* CK_ENCRYPTION */
  2734.  
  2735. /* The following note came from the old SGA negotiation code.  This should */
  2736. /* no longer be necessary with the New Telnet negotiation state machine.   */
  2737. /*
  2738.   Note: The following is proper behavior, and required for talking to the
  2739.   Apertus interface to the NOTIS library system, e.g. at Iowa State U:
  2740.   scholar.iastate.edu.  Without this reply, the server hangs forever.  This
  2741.   code should not be loop-inducing, since C-Kermit never sends WILL SGA as
  2742.   an initial bid, so if DO SGA comes, it is never an ACK.
  2743. */
  2744. /*
  2745.   Return values:
  2746.   -1 = Telnet Opton negotiation error
  2747.   -2 = Connection closed by peer
  2748.   -3 = Connection closed by us
  2749.   0  = Success
  2750.   1  = Echoing on
  2751.   2  = Echoing off
  2752.   3  = Quoted IAC
  2753.   4  = IKS Event
  2754.   5  = (unassigned)
  2755.   6  = Logout
  2756. */
  2757. int
  2758. #ifdef CK_ANSIC                         /* TELNET DO OPTION */
  2759. tn_doop(CHAR z, int echo, int (*fn)(int))
  2760. #else
  2761. tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
  2762. #endif /* CK_ANSIC */
  2763. /* tn_doop */ {
  2764.     int c, x, y, n, m, flag;
  2765. #ifdef IKS_OPTION
  2766.     extern int server;
  2767.     extern int local;
  2768. #ifdef NOICP
  2769.     extern int autodl;
  2770.     int inautodl = 0, cmdadl = 1;
  2771. #else
  2772. #ifdef CK_AUTODL
  2773.     extern int autodl, inautodl, cmdadl;
  2774. #endif /* CK_AUTODL */
  2775. #endif /* NOICP */
  2776. #endif /* IKS_OPTION */
  2777.  
  2778.     if (z != (CHAR) IAC) {
  2779.         debug(F101,"tn_doop bad call","",z);
  2780.         return(-1);
  2781.     }
  2782.     if (ttnet != NET_TCPB)              /* Check network type */
  2783.       return(0);
  2784.     if (ttnproto != NP_TELNET &&
  2785.          ttnproto != NP_NONE)           /* Check protocol */
  2786.       return(0);
  2787.  
  2788. /* Have IAC, read command character. */
  2789.  
  2790.     while ((c = (*fn)(0)) == -1);       /* Read command character */
  2791.     if (c < 0)
  2792.       return(c);
  2793.     c &= 0xFF;                          /* Strip high bits */
  2794.  
  2795.     if (!TELCMD_OK(c)) {
  2796.         sprintf(tn_msg,"TELNET RCVD UNKNOWN (%d)",c);
  2797.         debug(F101,tn_msg,"",c);
  2798.         if (tn_deb || debses) tn_debug(tn_msg);
  2799.         return(0);
  2800.     }
  2801.     if (ttnproto == NP_NONE) {
  2802.         debug(F100,"tn_doop discovered a Telnet command",
  2803.               "ttnproto = NP_TELNET",0);
  2804.         ttnproto = NP_TELNET;
  2805.     }
  2806.     if (seslog && sessft == XYFT_D) {   /* Copy to session log, if any. */
  2807.         logchar((char)z);
  2808.         logchar((char)c);
  2809.     }
  2810.  
  2811.     if (c == (CHAR) IAC)                /* Quoted IAC */
  2812.       return(3);
  2813.  
  2814.     if (c < SB) {                       /* Other command with no arguments. */
  2815.         if (deblog || tn_deb || debses) {
  2816.             sprintf(tn_msg,"TELNET RCVD %s",TELCMD(c));
  2817.             debug(F101,tn_msg,"",c);
  2818.             if (tn_deb || debses) tn_debug(tn_msg);
  2819.         }
  2820.         switch (c) {                    /* What we would like to do here    */
  2821.           case TN_GA:                   /* Is substitute ASCII characters   */
  2822.             break;                      /* for the Telnet Command so that   */
  2823.           case TN_EL:                   /* the command may be processed by  */
  2824.             break;                      /* either the internal emulator or  */
  2825.           case TN_EC:                   /* by the superior process or shell */
  2826.             break;
  2827.           case TN_AYT:
  2828.             ttol((CHAR *)"[Yes]\015\012",7);
  2829.             break;
  2830.           case TN_AO:
  2831. #ifdef BETATEST
  2832.             bleep(BP_NOTE);
  2833. #endif /* BETATEST */
  2834.             break;
  2835.           case TN_IP:
  2836.             break;
  2837.           case BREAK:
  2838.             break;
  2839.           case TN_DM:
  2840.             break;
  2841.           case TN_NOP:
  2842.             break;
  2843.           case SE:
  2844.             break;
  2845.           case TN_EOR:
  2846.             break;
  2847.           case TN_ABORT:
  2848.             break;
  2849.           case TN_SUSP:
  2850.             break;
  2851.           case TN_EOF:
  2852.             break;
  2853.           case TN_SAK:
  2854.             break;
  2855.         }
  2856.         return(0);
  2857.     }
  2858.  
  2859. /* SB, WILL, WONT, DO, or DONT need more bytes... */
  2860.  
  2861.     if ((x = (*fn)(0)) < 0)             /* Get the option. */
  2862.       return(x);
  2863.     x &= 0xff;                          /* Trim to 8 bits. */
  2864.  
  2865.     if (seslog && sessft == XYFT_D) {   /* Session log */
  2866.         logchar((char) x);
  2867.     }
  2868.     if ((deblog || tn_deb || debses) && c != SB) {
  2869.         sprintf(tn_msg,"TELNET RCVD %s %s",TELCMD(c),TELOPT(x));
  2870.         debug(F101,tn_msg,"",x);
  2871.         if (tn_deb || debses) tn_debug(tn_msg);
  2872.     }
  2873.  
  2874.     /* Now handle the command */
  2875.     switch (c) {
  2876.       case WILL:
  2877. #ifdef CK_SSL
  2878.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  2879.             return(0);
  2880. #endif /* CK_SSL */
  2881.         if (!TELOPT_OK(x) || TELOPT_U_MODE(x) == TN_NG_RF) {
  2882.             if (tn_sopt(DONT,x) < 0)
  2883.               return(-1);
  2884.             if (TELOPT_UNANSWERED_DO(x))
  2885.                 TELOPT_UNANSWERED_DO(x) = 0;
  2886.         } else if (!TELOPT_U(x)) {
  2887.             if (!TELOPT_UNANSWERED_DO(x)) {
  2888.                 if (tn_sopt(DO,x) < 0)
  2889.                   return -1;
  2890.             }
  2891.             if (TELOPT_UNANSWERED_DO(x))
  2892.                 TELOPT_UNANSWERED_DO(x) = 0;
  2893.             TELOPT_U(x) = 1;
  2894.  
  2895.             switch (x) {
  2896. #ifdef CK_SSL
  2897.               case TELOPT_START_TLS:
  2898.                 /*
  2899.                    If my proposal is accepted, at this point the Telnet
  2900.                    protocol is turned off and a TLS negotiation takes
  2901.                    place.
  2902.  
  2903.                    Start by sending SB START_TLS FOLLOWS  to signal
  2904.                    we are ready.  Wait for the peer to send the same
  2905.                    and then start the TLS negotiation.
  2906.  
  2907.                    If the TLS negotiation succeeds we call tn_ini()
  2908.                    again to reset the telnet state machine and restart
  2909.                    the negotiation process over the now secure link.
  2910.  
  2911.                    If the TLS negotiation fails, we call ttclos()
  2912.                    to terminate the connection.
  2913.  
  2914.                    Only the server should receive a WILL START_TLS
  2915.                  */
  2916.                 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
  2917.                 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
  2918.                 break;
  2919. #endif /* CK_SSL */
  2920.  
  2921. #ifdef CK_AUTHENTICATION
  2922.               case TELOPT_AUTHENTICATION: {
  2923.                   /* We now have to perform a SB SEND to identify the  */
  2924.                   /* supported authentication types to the other side. */
  2925.                   extern int authentication_version;
  2926.                   authentication_version = AUTHTYPE_AUTO;
  2927.                   ck_tn_auth_request();
  2928.                   break;
  2929.               }
  2930. #endif /* CK_AUTHENTICATION */
  2931. #ifdef CK_ENCRYPTION
  2932.               case TELOPT_ENCRYPTION:
  2933.                 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
  2934.                       TELOPT_U(TELOPT_AUTHENTICATION))
  2935.                     ) {
  2936.                     if (tn_sopt(DONT,x) < 0)
  2937.                       return(-1);
  2938.                     TELOPT_U(x) = 0;
  2939.                 } else {
  2940.                     if (ck_tn_auth_in_progress()) {
  2941.                         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 1;
  2942.                     } else {
  2943.                         /* Perform subnegotiation */
  2944.                         ck_encrypt_send_support();
  2945.                     }
  2946.                     if (!(TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x))
  2947.                         && TELOPT_ME_MODE(x) != TN_NG_RF) {
  2948.                         if (tn_sopt(WILL, x) < 0)
  2949.                           return(-1);
  2950.                         TELOPT_UNANSWERED_WILL(x) = 1;
  2951.                     }
  2952.                 }
  2953.                 break;
  2954. #endif /* CK_ENCRYPTION */
  2955. #ifdef IKS_OPTION
  2956.               case TELOPT_KERMIT:
  2957.                 if (!TELOPT_ME(x)) {
  2958.                     /* Tell the other side what Start of Packet Character */
  2959.                     tn_siks(KERMIT_SOP); /* SOP */
  2960.  
  2961.                     if (!TELOPT_UNANSWERED_WILL(x) &&
  2962.                         TELOPT_ME_MODE(x) != TN_NG_RF) {
  2963.                         if (tn_sopt(WILL, x) < 0)
  2964.                           return(-1);
  2965.                         TELOPT_UNANSWERED_WILL(x) = 1;
  2966.                     }
  2967.                 }
  2968.                 break;
  2969. #endif /* IKS_OPTION */
  2970.               case TELOPT_BINARY:
  2971.                 if (!TELOPT_ME(x)) {
  2972.                     if (!TELOPT_UNANSWERED_WILL(x) &&
  2973.                         TELOPT_ME_MODE(x) >= TN_NG_RQ) {
  2974.                         if (tn_sopt(WILL, x) < 0)
  2975.                           return(-1);
  2976.                         TELOPT_UNANSWERED_WILL(x) = 1;
  2977.                     }
  2978.                 }
  2979.                 break;
  2980.               case TELOPT_ECHO:
  2981.                 if (echo) {
  2982.                     if (TELOPT_UNANSWERED_DO(x))
  2983.                       TELOPT_UNANSWERED_DO(x) = 0;
  2984.                     return(2);
  2985.                 }
  2986.                 break;
  2987.               case TELOPT_TTYPE:
  2988.                 /* SB TTYPE SEND */
  2989.                 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
  2990.                 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
  2991.                 break;
  2992. #ifdef CK_ENVIRONMENT
  2993.               case TELOPT_NEWENVIRON:   /* SB NEW-ENVIRON SEND */
  2994. #ifdef CK_AUTHENTICATION
  2995.                 if (ck_tn_auth_valid() != AUTH_VALID)
  2996. #endif /* CK_AUTHENTICATION */
  2997.         {
  2998.                   char request[6];      /* request it */
  2999.                   sprintf(request,"%cUSER",TEL_ENV_VAR);
  3000.                   tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_SEND,request,5);
  3001.                   TELOPT_UNANSWERED_SB(TELOPT_NEWENVIRON)=1;
  3002.                 }
  3003.                 break;
  3004. #endif /* CK_ENVIRONMENT */
  3005. #ifdef CK_FORWARD_X
  3006.                case TELOPT_FORWARD_X:
  3007.                   if ( !tn_outst(0) || tn_init ) {
  3008.                       if (tn_sndfwdx() < 0) {
  3009.                           if (tn_sopt(DONT,x) < 0)
  3010.                               return(-1);
  3011.                           TELOPT_UNANSWERED_DONT(x) = 1;
  3012.                       }
  3013.                   } else {
  3014.                       TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 1;
  3015.                   }
  3016.                   break;
  3017. #endif /* CK_FORWARD_X */
  3018.             } /* switch */
  3019.         } else {
  3020.             if (TELOPT_UNANSWERED_DO(x))
  3021.                 TELOPT_UNANSWERED_DO(x) = 0;
  3022.         }
  3023.         break;
  3024.       case WONT:
  3025. #ifdef CK_SSL
  3026.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  3027.             return(0);
  3028. #endif /* CK_SSL */
  3029.         if (!TELOPT_OK(x) || TELOPT_U(x) || TELOPT_UNANSWERED_DO(x)) {
  3030.             /* David Borman says we should not respond DONT when */
  3031.             /* the WONT is a response to a DO that we sent.   */
  3032.             if (!(TELOPT_UNANSWERED_DO(x) || TELOPT_UNANSWERED_DONT(x)))
  3033.               if (tn_sopt(DONT,x) < 0)
  3034.                 return(-1);
  3035.             if (TELOPT_UNANSWERED_DONT(x))
  3036.                 TELOPT_UNANSWERED_DONT(x) = 0;
  3037.             if (TELOPT_UNANSWERED_DO(x))
  3038.                 TELOPT_UNANSWERED_DO(x) = 0;
  3039.             if (TELOPT_U(x)) {
  3040.                 TELOPT_U(x) = 0;
  3041.             }
  3042.             switch(x) {
  3043. #ifdef CK_SSL
  3044.             case TELOPT_START_TLS:
  3045.                 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
  3046.                     printf("Telnet Start-TLS refused.\n");
  3047.                     ttclos(0);
  3048.                     whyclosed = WC_TELOPT;
  3049.                     return(-3);
  3050.                 }
  3051.                 break;
  3052. #endif /* CK_SSL */
  3053. #ifdef CK_AUTHENTICATION
  3054.               case TELOPT_AUTHENTICATION:
  3055.                 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
  3056.                     printf("Telnet authentication refused.\n");
  3057.                     ttclos(0);
  3058.                     whyclosed = WC_TELOPT;
  3059.                     return(-3);
  3060.                 } else if (TELOPT_U_MODE(x) == TN_NG_RQ) {
  3061.                     TELOPT_U_MODE(x) = TN_NG_AC;
  3062.                 }
  3063.                 if (ck_tn_auth_in_progress())
  3064.                   printf("Telnet authentication refused.\n");
  3065. #ifdef CK_ENCRYPTION
  3066.                 if (sstelnet) {
  3067.                     if (tn_no_encrypt()<0)
  3068.                         return(-1);
  3069.                 }
  3070. #endif /* CK_ENCRYPTION */
  3071.                 break;
  3072. #endif /* CK_AUTHENTICATION */
  3073. #ifdef CK_ENCRYPTION
  3074.               case TELOPT_ENCRYPTION:
  3075.                 ck_tn_enc_stop();
  3076.                 break;
  3077. #endif /* CK_ENCRYPTION */
  3078. #ifdef IKS_OPTION
  3079.               case TELOPT_KERMIT:
  3080.                 TELOPT_SB(x).kermit.u_start = 0;
  3081.                 TELOPT_SB(x).kermit.me_req_start = 0;
  3082.                 TELOPT_SB(x).kermit.me_req_stop = 0;
  3083.                 break;
  3084. #endif /* IKS_OPTION */
  3085.               case TELOPT_NAWS: {
  3086.                   /* The client does not support NAWS. */
  3087.                   /* Assume a height of 24 and a width of 80 */
  3088.                   if (sstelnet
  3089. #ifdef IKSD
  3090.                    || inserver
  3091. #endif /* IKSD */
  3092.                    ) {
  3093.                       int w = 80, h = 24;
  3094.                       if (tcp_incoming) {
  3095. #ifdef OS2
  3096.                           tt_cols[VTERM] = w;
  3097.                           tt_rows[VTERM] = h;
  3098.                           VscrnSetWidth(VTERM, w);
  3099.                           VscrnSetHeight(VTERM, h+(tt_status?1:0));
  3100. #else /* OS2 */
  3101.                           tt_cols = w;
  3102.                           tt_rows = h;
  3103. #endif /* OS2 */
  3104.                       } else {
  3105. #ifdef OS2
  3106.                           tt_cols[VCMD] = w;
  3107.                           tt_rows[VCMD] = h;
  3108.                           VscrnSetWidth(VCMD, w);
  3109.                           VscrnSetHeight(VCMD, h);
  3110. #endif /* OS2 */
  3111.                           cmd_cols = w;
  3112.                           cmd_rows = h;
  3113.                       }
  3114.                       /* Add LINES and COLUMNS to the environment */
  3115.                       sprintf((char *)rows_buf,"LINES=%d",h);
  3116.                       sprintf((char *)cols_buf,"COLUMNS=%d",w);
  3117. #ifdef OS2ORUNIX
  3118. #ifndef NOPUTENV
  3119.                       putenv(rows_buf);
  3120.                       putenv(cols_buf);
  3121. #endif /* NOPUTENV */
  3122. #endif /* OS2ORUNIX */
  3123.                   }
  3124.                   break;
  3125.               }
  3126.               case TELOPT_ECHO:
  3127.                 if (!echo) {
  3128.                     if (TELOPT_UNANSWERED_DO(x))
  3129.                       TELOPT_UNANSWERED_DO(x) = 0;
  3130.                     return(1);
  3131.                 }
  3132.                 break;
  3133.             }
  3134.         } else {
  3135.             if (TELOPT_UNANSWERED_DONT(x))
  3136.                 TELOPT_UNANSWERED_DONT(x) = 0;
  3137.             if (TELOPT_UNANSWERED_DO(x))
  3138.                 TELOPT_UNANSWERED_DO(x) = 0;
  3139.         }
  3140.         if (TELOPT_U_MODE(x) == TN_NG_MU) {
  3141.             sprintf(tn_msg,
  3142.             "Peer refuses TELNET DO %s negotiations - terminating connection",
  3143.                     TELOPT(x)
  3144.                     );
  3145.             debug(F100,tn_msg,"",0);
  3146.             if (tn_deb || debses) tn_debug(tn_msg);
  3147.             printf("%s\n",tn_msg);
  3148.             ttclos(0);
  3149.             whyclosed = WC_TELOPT;
  3150.             return(-3);
  3151.         }
  3152. #ifdef COMMENT
  3153.         if (x == TELOPT_ECHO && !echo) /* Special handling for echo */
  3154.           return(1);                   /* because we allow 'duplex' */
  3155. #endif /* COMMENT */
  3156.         break;
  3157.  
  3158.       case DO:
  3159. #ifdef CK_SSL
  3160.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  3161.             return(0);
  3162. #endif /* CK_SSL */
  3163.         if (!TELOPT_OK(x) || TELOPT_ME_MODE(x) == TN_NG_RF) {
  3164.             if (tn_sopt(WONT,x) < 0)
  3165.               return(-1);
  3166.             if (TELOPT_UNANSWERED_WILL(x))
  3167.                 TELOPT_UNANSWERED_WILL(x) = 0;
  3168.         } else if (!TELOPT_ME(x)) {
  3169.             if (!TELOPT_UNANSWERED_WILL(x)) {
  3170.                 if (tn_sopt(WILL,x) < 0)
  3171.                   return(-1);
  3172.             }
  3173.             if (TELOPT_UNANSWERED_WILL(x))
  3174.                 TELOPT_UNANSWERED_WILL(x) = 0;
  3175.             TELOPT_ME(x) = 1;
  3176.  
  3177.             switch (x) {
  3178. #ifdef CK_SSL
  3179.               case TELOPT_START_TLS:
  3180.                 /*
  3181.                    If my proposal is accepted at this point the Telnet
  3182.                    protocol is turned off and a TLS negotiation takes
  3183.                    place.
  3184.  
  3185.                    Start by sending SB START_TLS FOLLOWS  to signal
  3186.                    we are ready.  Wait for the peer to send the same
  3187.                    and then start the TLS negotiation.
  3188.  
  3189.                    If the TLS negotiation succeeds we call tn_ini()
  3190.                    again to reset the telnet state machine and restart
  3191.                    the negotiation process over the now secure link.
  3192.  
  3193.                    If the TLS negotiation fails, we call ttclos()
  3194.                    to terminate the connection.  Then we set the
  3195.                    U_MODE and ME_MODE for TELOPT_START_TLS to REFUSE
  3196.                    and then call ttopen() to create a new connection
  3197.                    to the same host but this time do not attempt
  3198.                    TLS security.
  3199.  
  3200.                    Only the client should receive DO START_TLS.
  3201.                 */
  3202.                 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
  3203.                 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
  3204.                 break;
  3205. #endif /* CK_SSL */
  3206.  
  3207. #ifdef CK_AUTHENTICATION
  3208.               case TELOPT_AUTHENTICATION: {
  3209.                   /* We don't know what authentication we are using yet */
  3210.                   /* but it is not NULL until a failure is detected so */
  3211.                   /* use AUTO in the meantime. */
  3212.                   extern int authentication_version;
  3213.                   authentication_version = AUTHTYPE_AUTO;
  3214.                   break;
  3215.               }
  3216. #endif /* CK_AUTHENTICATION */
  3217. #ifdef CK_ENCRYPTION
  3218.               case TELOPT_ENCRYPTION:
  3219.                 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
  3220.                       TELOPT_U(TELOPT_AUTHENTICATION))
  3221.                     ) {
  3222.                     if (tn_sopt(WONT,x) < 0)
  3223.                       return(-1);
  3224.                     TELOPT_ME(x) = 0;
  3225.                 } else {
  3226.                     if (!(TELOPT_U(x) || TELOPT_UNANSWERED_DO(x))
  3227.                         && TELOPT_U_MODE(x) != TN_NG_RF) {
  3228.                         if (tn_sopt(DO, x) < 0)
  3229.                           return(-1);
  3230.                         TELOPT_UNANSWERED_DO(x) = 1;
  3231.                     }
  3232.                 }
  3233.                 break;
  3234. #endif /* CK_ENCRYPTION */
  3235. #ifdef IKS_OPTION
  3236.               case TELOPT_KERMIT:
  3237. /* If currently processing Kermit server packets, must tell the other side */
  3238.  
  3239.                 debug(F111,"tn_doop","what",what);
  3240.                 debug(F111,"tn_doop","server",server);
  3241. #ifdef CK_AUTODL
  3242.                 debug(F111,"tn_doop","autodl",autodl);
  3243.                 debug(F111,"tn_doop","inautodl",inautodl);
  3244.                 debug(F111,"tn_doop","cmdadl",cmdadl);
  3245. #endif /* CK_AUTODL */
  3246.  
  3247.                 if (server
  3248. #ifdef CK_AUTODL
  3249.                     || (local && ((what == W_CONNECT && autodl) ||
  3250.                                   (what != W_CONNECT && inautodl)))
  3251.                     || (!local && cmdadl)
  3252. #endif /* CK_AUTODL */
  3253.                     ) {
  3254.                     tn_siks(KERMIT_START);      /* START */
  3255.                 }
  3256.                 if (!TELOPT_U(x)) {
  3257.                     /* Tell the other side what Start of Packet Character */
  3258.                     tn_siks(KERMIT_SOP);             /* SOP */
  3259.                     if (!TELOPT_UNANSWERED_DO(x) &&
  3260.                         TELOPT_U_MODE(x) != TN_NG_RF) {
  3261.                         if (tn_sopt(DO, x) < 0)
  3262.                           return(-1);
  3263.                         TELOPT_UNANSWERED_DO(x) = 1;
  3264.                     }
  3265.                 }
  3266.                 break;
  3267. #endif /* IKS_OPTION */
  3268.  
  3269.               case TELOPT_BINARY:
  3270.                 if (!TELOPT_U(x)) {
  3271.                     if (!TELOPT_UNANSWERED_DO(x) &&
  3272.                         TELOPT_U_MODE(x) >= TN_NG_RQ) {
  3273.                         if (tn_sopt(DO, x) < 0)
  3274.                           return(-1);
  3275.                         TELOPT_UNANSWERED_DO(x) = 1;
  3276.                     }
  3277.                 }
  3278.                 break;
  3279.               case TELOPT_NAWS:
  3280. #ifndef NOSIGWINCH
  3281. #ifdef SIGWINCH
  3282. #ifdef UNIX
  3283.                 if (sw_armed++ < 1) {   /* Catch window-size changes. */
  3284.                     debug(F100,"tn_doop arming SIGWINCH","",0);
  3285.                     signal(SIGWINCH,winchh);
  3286.                 }
  3287. #else
  3288.                 debug(F100,"SIGWINCH defined but not used","",0);
  3289. #endif /* UNIX */
  3290. #else  /* SIGWINCH */
  3291.                 debug(F100,"SIGWINCH not defined","",0);
  3292. #endif /* SIGWINCH */
  3293. #else  /* NOSIGWINCH */
  3294.                 debug(F100,"NOSIGWINCH defined","",0);
  3295. #endif /* NOSIGWINCH */
  3296. #ifdef CK_NAWS
  3297.                 if ( !tn_outst(0) || tn_init ) {
  3298.                     if (tn_snaws() < 0)
  3299.                         return(-1);
  3300.                 } else {
  3301.                     TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 1;
  3302.                 }
  3303. #endif /* CK_NAWS */
  3304.                 break;
  3305.               case TELOPT_LOGOUT:
  3306.                 ttclos(0);              /* And then hangup */
  3307.                 whyclosed = WC_TELOPT;
  3308. #ifdef IKSD
  3309.                 if (inserver
  3310. #ifndef NOLOCAL
  3311.                     && !local
  3312. #endif /* NOLOCAL */
  3313.                     )
  3314.                   doexit(GOOD_EXIT,0);
  3315. #endif /* IKSD */
  3316.                 if (TELOPT_UNANSWERED_WILL(x))
  3317.                   TELOPT_UNANSWERED_WILL(x) = 0;
  3318.                 return(6);
  3319. #ifdef CK_SNDLOC
  3320.                case TELOPT_SNDLOC:
  3321.                   if ( !tn_outst(0) || tn_init ) {
  3322.                       if (tn_sndloc() < 0)
  3323.                           return(-1);
  3324.                   } else {
  3325.                       TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 1;
  3326.                   }
  3327.                   break;
  3328. #endif /* CK_SNDLOC */
  3329.             } /* switch */
  3330.         } else {
  3331.           if (TELOPT_UNANSWERED_WILL(x))
  3332.             TELOPT_UNANSWERED_WILL(x) = 0;
  3333.         }
  3334.         break;
  3335.  
  3336.       case DONT:
  3337. #ifdef CK_SSL
  3338.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  3339.             return(0);
  3340. #endif /* CK_SSL */
  3341.         if (!TELOPT_OK(x) || TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x)) {
  3342.             /* David Borman says we should not respond DONT when */
  3343.             /* the WONT is a response to a WILL that we sent. */
  3344.             if (!(TELOPT_UNANSWERED_WILL(x) || TELOPT_UNANSWERED_WONT(x)))
  3345.               if (tn_sopt(WONT,x) < 0)
  3346.                 return(-1);
  3347.  
  3348.             if (TELOPT_UNANSWERED_WILL(x))
  3349.                 TELOPT_UNANSWERED_WILL(x) = 0;
  3350.             if (TELOPT_UNANSWERED_WONT(x))
  3351.                 TELOPT_UNANSWERED_WONT(x) = 0;
  3352.             if (TELOPT_ME(x))
  3353.               TELOPT_ME(x) = 0;
  3354.  
  3355.             switch (x) {
  3356. #ifdef CK_SSL
  3357.             case TELOPT_START_TLS:
  3358.                 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
  3359.                     printf("Telnet Start-TLS refused.\n");
  3360.                     ttclos(0);
  3361.                     whyclosed = WC_TELOPT;
  3362.                     return(-3);
  3363.                 }
  3364.                 break;
  3365. #endif /* CK_SSL */
  3366. #ifdef CK_AUTHENTICATION
  3367.               case TELOPT_AUTHENTICATION:
  3368.                 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
  3369.                     printf("Telnet authentication refused.\n");
  3370.                     ttclos(0);
  3371.                     whyclosed = WC_TELOPT;
  3372.                     return(-3);
  3373.                 } else if (TELOPT_ME_MODE(x) == TN_NG_RQ) {
  3374.                     TELOPT_ME_MODE(x) = TN_NG_AC;
  3375.                 }
  3376.                 if (ck_tn_auth_in_progress())
  3377.                   printf("Telnet authentication refused.\n");
  3378. #ifdef CK_ENCRYPTION
  3379.                 if (!sstelnet) {
  3380.                     if (tn_no_encrypt()<0)
  3381.                         return(-1);
  3382.                 }
  3383. #endif /* CK_ENCRYPTION */
  3384.                 break;
  3385. #endif /* CK_AUTHENTICATION */
  3386.               case TELOPT_ENCRYPTION:
  3387. #ifdef CK_ENCRYPTION
  3388.                 ck_tn_enc_stop();
  3389. #endif /* CK_ENCRYPTION */
  3390.                 break;
  3391.               case TELOPT_KERMIT:
  3392. #ifdef IKS_OPTION
  3393.                 TELOPT_SB(x).kermit.me_start = 0;
  3394. #endif /* IKS_OPTION */
  3395.                 break;
  3396.               default:
  3397.                 break;
  3398.             } /* switch */
  3399.         } else {
  3400.           if (TELOPT_UNANSWERED_WILL(x))
  3401.               TELOPT_UNANSWERED_WILL(x) = 0;
  3402.           if (TELOPT_UNANSWERED_WONT(x))
  3403.               TELOPT_UNANSWERED_WONT(x) = 0;
  3404.         }
  3405.         if (TELOPT_ME_MODE(x) == TN_NG_MU) {
  3406.             sprintf(tn_msg,
  3407.            "Peer refuses TELNET WILL %s negotiations - terminating connection",
  3408.                     TELOPT(x)
  3409.                     );
  3410.             debug(F100,tn_msg,"",0);
  3411.             if (tn_deb || debses) tn_debug(tn_msg);
  3412.             printf("%s\n",tn_msg);
  3413.             ttclos(0);
  3414.             whyclosed = WC_TELOPT;
  3415.             return(-3);
  3416.         }
  3417.         break;
  3418.       case SB:
  3419.         if ((y = tn_sb(x,&n,fn)) <= 0)
  3420.           return(y);
  3421.  
  3422. #ifdef CK_SSL
  3423.         /* Do not process subnegotiations other than START_TLS after we */
  3424.         /* have agreed to begin the TLS negotiation sequence.           */
  3425.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows &&
  3426.              x != TELOPT_START_TLS)
  3427.             break;
  3428. #endif /* CK_SSL */
  3429.  
  3430.         if (!TELOPT_OK(x)) {
  3431.             hexdump("unknown telnet subnegotiation",sb,n);
  3432.             break;
  3433.         } else if ( !(TELOPT_ME(x) || TELOPT_U(x)) ) {
  3434.             hexdump("telnet option not negotiated",sb,n);
  3435.             if (!tn_sb_bug)
  3436.                 break;
  3437.             if (TELOPT_UNANSWERED_WILL(x)) {
  3438.                 TELOPT_UNANSWERED_WILL(x) = 0;
  3439.                 TELOPT_U(x) = 1;
  3440.                 sprintf(tn_msg,
  3441.          "TELNET DO %s (implied by receipt of SB - protocol error ignored)",
  3442.                          TELOPT(x)
  3443.                          );
  3444.                 debug(F100,tn_msg,"",0);
  3445.                 if (tn_deb || debses) tn_debug(tn_msg);
  3446.             }
  3447.             if (TELOPT_UNANSWERED_DO(x)) {
  3448.                 TELOPT_UNANSWERED_DO(x) = 0;
  3449.                 TELOPT_ME(x) = 1;
  3450.                 sprintf(tn_msg,
  3451.          "TELNET WILL %s (implied by receipt of SB - protocol error ignored)",
  3452.                          TELOPT(x)
  3453.                          );
  3454.                 debug(F100,tn_msg,"",0);
  3455.                 if (tn_deb || debses) tn_debug(tn_msg);
  3456.              }
  3457.         }
  3458.  
  3459.         TELOPT_UNANSWERED_SB(x)=0;
  3460.         switch (x) {
  3461. #ifdef CK_FORWARD_X
  3462.           case TELOPT_FORWARD_X:
  3463.             return(fwdx_tn_sb(sb, n));
  3464. #endif /* CK_FORWARD_X */
  3465. #ifdef CK_SSL
  3466.           case TELOPT_START_TLS: {
  3467.               /*
  3468.                  the other side is saying SB START_TLS FOLLOWS
  3469.                  the incoming channel is now ready for starting the
  3470.                  TLS negotiation.
  3471.                  */
  3472.               int def_tls_u_mode, def_tls_me_mode;
  3473.               int def_enc_u_mode, def_enc_me_mode;
  3474.               int rc = 0;
  3475.  
  3476.               TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 1;
  3477.               /* Preserve the default modes and make sure we will */
  3478.               /* refuse START_TLS when we retry. */
  3479.               if (sstelnet) {
  3480.                   def_tls_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_START_TLS);
  3481.                   def_tls_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS);
  3482.                   TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  3483.                   TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
  3484. #ifdef CK_ENCRYPTION
  3485.                   def_enc_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
  3486.                   def_enc_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
  3487.                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3488.                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
  3489. #endif /* CK_ENCRYPTION */
  3490.               } else {
  3491.                   def_tls_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_START_TLS);
  3492.                   def_tls_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS);
  3493.                   TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  3494.                   TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
  3495. #ifdef CK_ENCRYPTION
  3496.                   def_enc_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
  3497.                   def_enc_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
  3498.                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3499.                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
  3500. #endif /* CK_ENCRYPTION */
  3501.               }
  3502.               /* Negotiate TLS */
  3503.               ttnproto = NP_TLS;
  3504.               tn_init = 0;
  3505.               if (ck_tn_tls_negotiate()<0) {
  3506.                   /* we failed.  disconnect and if we are the client */
  3507.                   /* then reconnect and try without START_TLS.       */
  3508.                   extern char * line;
  3509.                   int x = -1;
  3510.                   extern int mdmtyp;
  3511.  
  3512.                   if (sstelnet) {
  3513.                       printf("TLS failed:  Disconnecting.\n");
  3514.                       TELOPT_DEF_S_U_MODE(TELOPT_START_TLS)  = def_tls_u_mode;
  3515.                       TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
  3516. #ifdef CK_ENCRYPTION
  3517.                      TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  3518.                      TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  3519. #endif /* CK_ENCRYPTION */
  3520.                       ttclos(0);
  3521.                       whyclosed = WC_TELOPT;
  3522.                       ttnproto = NP_TELNET;
  3523.                       rc = -3;
  3524.                   } else {
  3525.                       extern tls_norestore;
  3526.                       printf("TLS failed:  Disconnecting...\n");
  3527. #ifdef CK_ENCRYPTION
  3528.                      TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  3529.                      TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  3530. #endif /* CK_ENCRYPTION */
  3531.                       /* if START_TLS is not REQUIRED, then retry without it */
  3532.                       if ( def_tls_me_mode != TN_NG_MU ) {
  3533.                           tls_norestore = 1;
  3534.                           ttclos(0);
  3535.                           whyclosed = WC_TELOPT;
  3536.                           tls_norestore = 0;
  3537.                           ttnproto = NP_TELNET;
  3538.                           printf("Reconnecting without TLS.\n");
  3539.                           sleep(2);
  3540.                           if (ttopen(line,&x,mdmtyp,0)<0)
  3541.                               rc = -3;
  3542.                       } else {
  3543.                           TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) =
  3544.                             def_tls_u_mode;
  3545.                           TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) =
  3546.                             def_tls_me_mode;
  3547.                           ttclos(0);
  3548.                           whyclosed = WC_TELOPT;
  3549.                           ttnproto = NP_TELNET;
  3550.                           rc = -3;
  3551.                       }
  3552.                   }
  3553.               } else {
  3554.                   /* we succeeded.  restart telnet negotiations from */
  3555.                   /* the beginning.  However, if we have received a  */
  3556.                   /* client certificate and we are a server, then do */
  3557.                   /* not offer TELOPT_AUTH */
  3558.                   if ( ck_tn_auth_valid() == AUTH_VALID ) {
  3559.                       TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  3560.                       TELOPT_DEF_S_ME_MODE(TELOPT_AUTHENTICATION)= TN_NG_RF;
  3561.                   }
  3562.                   ttnproto = NP_TELNET;
  3563.                   if (tn_ini() < 0)
  3564.                     if (ttchk() < 0)
  3565.                       rc = -1;
  3566.               }
  3567.               /* Restore the default modes */
  3568.               if (sstelnet) {
  3569.                   TELOPT_DEF_S_U_MODE(TELOPT_START_TLS)  = def_tls_u_mode;
  3570.                   TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
  3571. #ifdef CK_ENCRYPTION
  3572.                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  3573.                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  3574. #endif /* CK_ENCRYPTION */
  3575.               } else {
  3576.                   TELOPT_DEF_C_U_MODE(TELOPT_START_TLS)  = def_tls_u_mode;
  3577.                   TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
  3578. #ifdef CK_ENCRYPTION
  3579.                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  3580.                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  3581. #endif /* CK_ENCRYPTION */
  3582.               }
  3583.               return(rc);
  3584.           }
  3585. #endif /* CK_SSL */
  3586. #ifdef CK_AUTHENTICATION
  3587.           case TELOPT_AUTHENTICATION:
  3588.             if (ck_tn_sb_auth(sb,n) < 0) {
  3589.                 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
  3590.                     ttclos(0);
  3591.                     whyclosed = WC_TELOPT;
  3592.                     return(-3);
  3593.                 } else if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
  3594.                     ttclos(0);
  3595.                     whyclosed = WC_TELOPT;
  3596.                     return(-3);
  3597.                 } else {
  3598.                     if (TELOPT_ME_MODE(x) == TN_NG_RQ)
  3599.                       TELOPT_ME_MODE(x) = TN_NG_AC;
  3600.                     if (TELOPT_U_MODE(x) == TN_NG_RQ)
  3601.                       TELOPT_U_MODE(x) = TN_NG_AC;
  3602.                 }
  3603.                 if (TELOPT_ME(x)) {
  3604.                     TELOPT_ME(x) = 0;
  3605.                     if (tn_sopt(WONT,x) < 0)
  3606.                       return(-1);
  3607.                 }
  3608.                 if (TELOPT_U(x)) {
  3609.                     TELOPT_U(x) = 0;
  3610.                     if (tn_sopt(DONT,x) < 0)
  3611.                       return(-1);
  3612.                 }
  3613. #ifdef CK_ENCRYPTION
  3614.                 if (tn_no_encrypt()<0)
  3615.                     return(-1);
  3616. #endif /* CK_ENCRYPTION */
  3617.             } else {
  3618. #ifdef CK_ENCRYPTION
  3619.                 if (!ck_tn_auth_in_progress()) { /* we are finished */
  3620.                     if (ck_tn_authenticated() == AUTHTYPE_SSL) {
  3621.                         /* TLS was successful.  Disable ENCRYPTION */
  3622.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3623.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3624.                     }
  3625.                     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send) {
  3626.                         ck_encrypt_send_support();
  3627.                         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
  3628.                     }
  3629.                 }
  3630. #endif /* CK_ENCRYPTION */
  3631.             }
  3632.             break;
  3633. #endif /* CK_AUTHENTICATION */
  3634. #ifdef CK_ENCRYPTION
  3635.           case TELOPT_ENCRYPTION:
  3636.             if (ck_tn_sb_encrypt(sb, n) < 0) {
  3637.                 if (TELOPT_U_MODE(x) == TN_NG_MU ||
  3638.                     TELOPT_ME_MODE(x) == TN_NG_MU)
  3639.                   {
  3640.                       ttclos(0);
  3641.                       whyclosed = WC_TELOPT;
  3642.                       return(-3);
  3643.                 } else {
  3644.                     if (TELOPT_ME_MODE(x) == TN_NG_RQ)
  3645.                       TELOPT_ME_MODE(x) = TN_NG_AC;
  3646.                     if (TELOPT_U_MODE(x) == TN_NG_RQ)
  3647.                       TELOPT_U_MODE(x) = TN_NG_AC;
  3648.                 }
  3649.                 if (TELOPT_ME(x)) {
  3650.                     TELOPT_ME(x) = 0;
  3651.                     if (tn_sopt(WONT,x) < 0)
  3652.                       return(-1);
  3653.                 }
  3654.                 if (TELOPT_U(x)) {
  3655.                     TELOPT_U(x) = 0;
  3656.                     if (tn_sopt(DONT,x) < 0)
  3657.                       return(-1);
  3658.                 }
  3659.             }
  3660.             break;
  3661. #endif /* CK_ENCRYPTION */
  3662. #ifdef IKS_OPTION
  3663.           case TELOPT_KERMIT:
  3664.             return(iks_tn_sb((char *)sb, n));
  3665. #endif /* IKS_OPTION */
  3666.           case TELOPT_TTYPE:
  3667.             switch (sb[0]) {
  3668.               case TELQUAL_SEND:        /* SEND terminal type? */
  3669.                 if ( !tn_outst(0) || tn_init ) {
  3670.                     if (tn_sttyp() < 0) /* Yes, so send it. */
  3671.                         return(-1);
  3672.                 } else {
  3673.                     TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 1;
  3674.                 }
  3675.                 break;
  3676.               case TELQUAL_IS: {        /* IS terminal type? */
  3677.                   /* IS terminal type -- remote gave us its current type */
  3678.                   int i = 0;
  3679. #ifndef OS2
  3680.                   CHAR oldterm[64], *p;
  3681. #endif /* OS2 */
  3682.                   /* Isolate the specified terminal type string */
  3683.                   while (sb[i++] != IAC) {
  3684.                       if (i == 40 ||    /* max len of term string - RFC */
  3685.                           sb[i] == IAC) {
  3686.                           sb[i] = '\0';
  3687.                           break;
  3688.                       }
  3689.                   }
  3690. #ifdef OS2
  3691.                   strupr(&(sb[1]));     /* Upper case it */
  3692.                   for (i = 0; i <= max_tt; i++) { /* find it in our list */
  3693.                       if (!strcmp(&(sb[1]),tt_info[i].x_name)
  3694.                           && i != TT_VTNT) /* can't support VTNT as server */
  3695.                         {
  3696.                           /* Set terminal type to the one chosen */
  3697.                           if (i != tt_type)
  3698.                             settermtype(i,0);
  3699.                           break;
  3700.                       }
  3701.                   }
  3702.                   if (i > max_tt &&
  3703.                       strcmp(&(sb[1]),TELOPT_SB(TELOPT_TTYPE).term.type)) {
  3704.                       /* Couldn't find the specified term type */
  3705.                       sb[40] = '\0';
  3706.                       strcpy(TELOPT_SB(TELOPT_TTYPE).term.type,&(sb[1]));
  3707.                       /* SB TTYPE SEND */
  3708.                       tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
  3709.                       TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
  3710.                   }
  3711. #else /* OS2 */
  3712.                   p = (CHAR *) getenv("TERM");
  3713.                   if (p)
  3714.                     ckstrncpy((char *)oldterm,(char *)p,63);
  3715.                   else
  3716.                     oldterm[0] = '\0';
  3717.                   cklower((char *)&(sb[1])); /* Lower case new term */
  3718.                   sprintf(term_buf,"TERM=%s",&(sb[1]));
  3719. #ifdef OS2ORUNIX
  3720. #ifndef NOPUTENV
  3721.                   putenv(term_buf);
  3722. #endif /* NOPUTENV */
  3723. #endif /* OS2ORUNIX */
  3724. #ifdef CK_CURSES
  3725. #ifndef MYCURSES
  3726. #ifndef COHERENT
  3727.                   if (trmbuf) {
  3728.                       if (tgetent(trmbuf,(char *)&sb[1]) < 1) {
  3729.                           /* Unsupported terminal.  If new and old terminal */
  3730.                           /* types do not match, ask for another type. */
  3731.                           if (strcmp((char *)oldterm,(char *)&sb[1])) {
  3732.                               /* SB TTYPE SEND */
  3733.                               tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
  3734.                               TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
  3735.                           }
  3736.                       }
  3737.                   }
  3738. #endif /* COHERENT */
  3739. #endif /* MYCURSES */
  3740. #endif /* CK_CURSES */
  3741. #endif /* OS2 */
  3742.               }
  3743.             }
  3744.             break;
  3745. #ifdef CK_ENVIRONMENT
  3746. #ifdef CK_XDISPLOC
  3747.           case TELOPT_XDISPLOC:         /* Send X-Display Location */
  3748.             if (sb[0] == TELQUAL_SEND) {/* SEND X-Display Loc? */
  3749.                 if ( !tn_outst(0) || tn_init ) {
  3750.                     if (tn_sxdisploc() < 0)     /* Yes, so send it. */
  3751.                         return(-1);
  3752.                 } else {
  3753.                     TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 1;
  3754.                 }
  3755.             }
  3756.             /* IS -- X Display Location (not supported) */
  3757.             else if (sb[0] == TELQUAL_IS) {
  3758.                 int i = 0;
  3759.                 /* Isolate the specified X-display string */
  3760.                 while (sb[i++] != IAC) {
  3761.                     if (i >= TSBUFSIZ)
  3762.                       return (-1);
  3763.                     if (sb[i] == IAC) {
  3764.                         sb[i] = '\0';
  3765.                         break;
  3766.                     }
  3767.                 }
  3768.                 debug(F110,"TELNET SB XDISPLOC IS",&sb[1],0);
  3769.             }
  3770.             break;
  3771. #endif /* CK_XDISPLOC */
  3772. #endif /* CK_ENVIRONMENT */
  3773.           case TELOPT_NAWS:
  3774.               if (sstelnet
  3775. #ifdef IKSD
  3776.                    || inserver
  3777. #endif /* IKSD */
  3778.                    ) {
  3779.                   int w = 0, h = 0;
  3780.                   int i = 0;
  3781.                   /* At this point sb[] should contain width and height */
  3782.                   if (sb[i] == IAC) i++;
  3783.                   w = (sb[i++] << 8);   /* save upper height */
  3784.                   if (sb[i] == IAC) i++;
  3785.                   w += sb[i++];         /* save the width */
  3786.                   if (sb[i] == IAC) i++;
  3787.                   h = (sb[i++] << 8);   /* save upper height */
  3788.                   if (sb[i] == IAC) i++;
  3789.                   h += sb[i++];
  3790.                   debug(F111,"tn_doop NAWS SB","width",w);
  3791.                   debug(F111,"tn_doop NAWS SB","height",h);
  3792.  
  3793.                   if (w == 0)
  3794.                     w = 80;
  3795.                   if (h == 0)
  3796.                     h = 24;
  3797.                   if (tcp_incoming) {
  3798. #ifdef OS2
  3799.                       tt_cols[VTERM] = w;
  3800.                       tt_rows[VTERM] = h;
  3801.                       VscrnSetWidth(VTERM, w);
  3802.                       VscrnSetHeight(VTERM, h+(tt_status?1:0));
  3803. #ifdef IKSD
  3804.                       if (inserver) {
  3805.                           cmd_cols = tt_cols[VCMD] = w;
  3806.                           cmd_rows = tt_rows[VCMD] = h;
  3807.                           VscrnSetWidth(VCMD, w);
  3808.                           VscrnSetHeight(VCMD, h);
  3809.                       }
  3810. #endif /* IKSD */
  3811. #else /* OS2 */
  3812.                       tt_cols = w;
  3813.                       tt_rows = h;
  3814. #endif /* OS2 */
  3815.                   } else {
  3816. #ifdef OS2
  3817.                       tt_cols[VCMD] = w;
  3818.                       tt_rows[VCMD] = h;
  3819.                       VscrnSetWidth(VCMD, w);
  3820.                       VscrnSetHeight(VCMD, h);
  3821. #endif /* OS2 */
  3822.                       cmd_cols = w;
  3823.                       cmd_rows = h;
  3824.                   }
  3825.                   /* Add LINES and COLUMNS to the environment */
  3826.                   sprintf((char *)rows_buf,"LINES=%d",h);
  3827.                   sprintf((char *)cols_buf,"COLUMNS=%d",w);
  3828. #ifdef OS2ORUNIX
  3829. #ifndef NOPUTENV
  3830.                   putenv(rows_buf);
  3831.                   putenv(cols_buf);
  3832. #endif /* NOPUTENV */
  3833. #endif /* OS2ORUNIX */
  3834.               }
  3835.               break;
  3836. #ifdef CK_ENVIRONMENT
  3837.           case TELOPT_NEWENVIRON:
  3838.             switch (sb[0]) {
  3839.               case TELQUAL_IS:                  /* IS */
  3840.               case TELQUAL_INFO:                /* INFO */
  3841.                 if (sb[0] == TELQUAL_IS)
  3842.                   debug(F101,"tn_doop NEW-ENV SB IS","",n-3);
  3843.                 else
  3844.                   debug(F101,"tn_doop NEW-ENV SB INFO","",n-3);
  3845.                 if (sstelnet || inserver) { /* Yes, receive it. */
  3846.                     if (tn_rnenv((CHAR *)&sb[1],n-3) < 0)
  3847.                       return(-1);
  3848.                 }
  3849.                 break;
  3850.               case TELQUAL_SEND:        /* SEND */
  3851.                 if ( sstelnet || inserver )         /* ignore if server */
  3852.                     break;
  3853.                 /* We need to take the sb[] and build a structure */
  3854.                 /* containing all of the variables and types that */
  3855.                 /* we are supposed to keep track of and send to   */
  3856.                 /* the host, then call tn_snenv().                  */
  3857.                 /* Or we can punt ...                               */
  3858.                 if ( !tn_outst(0) || tn_init ) {
  3859.                   if (tn_snenv((CHAR *)&sb[1],n-3) < 0) /* Yes, send it. */
  3860.                      return(-1);
  3861.                 } else {
  3862. #ifndef VMS
  3863.                   CHAR * xxx;
  3864.                   xxx = (CHAR *) malloc(n-1);
  3865. #else
  3866.                   unsigned char * xxx;
  3867.                   xxx = (unsigned char *) malloc(n-1);
  3868. #endif /* VMS */
  3869.                   /* Postpone sending until end of tn_ini() */
  3870.                   TELOPT_SB(TELOPT_NEWENVIRON).env.str = xxx;
  3871.                   if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  3872.                   ckmemcpy((char *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
  3873.                             (char *)&sb[1],n-3);
  3874.                   TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-3] = IAC;
  3875.                   TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-2] = '\0';
  3876.                   TELOPT_SB(TELOPT_NEWENVIRON).env.len = n-3;
  3877.                   TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 1;
  3878.                   }
  3879.                 }
  3880.                 break;
  3881.               }
  3882.               break;
  3883. #endif /* CK_ENVIRONMENT */
  3884. #ifdef CK_SNDLOC
  3885.           case TELOPT_SNDLOC: {
  3886.               if ( deblog ) {
  3887.                   sb[n-2] = '\0';
  3888.                   debug(F110,"TELNET Send-Location",sb,0);
  3889.               }
  3890.               break;
  3891.           }
  3892. #endif /* CK_SNDLOC */
  3893.           } /* switch */
  3894.         break;
  3895.     }
  3896.     return(0);
  3897. }
  3898.  
  3899. #ifdef CK_ENVIRONMENT
  3900.  
  3901. /* Telnet receive new environment */
  3902. /* Returns -1 on error, 0 if nothing happens, 1 on success */
  3903. /* In order for this code to work, sb[len] == IAC          */
  3904. /* We currently only support the USER environment variable */
  3905.  
  3906. int
  3907. #ifdef CK_ANSIC
  3908. tn_rnenv(CHAR * sb, int len)
  3909. #else
  3910. tn_rnenv(sb, len) CHAR * sb; int len;
  3911. #endif /* CK_ANSIC */
  3912. /* tn_rnenv */ {                        /* Receive new environment */
  3913.     char varname[17];
  3914.     char value[65];
  3915.     char * reply = 0, * s = 0;
  3916.     int i,j,k,n;                                /* Worker. */
  3917.     int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR, */
  3918.                   /* 3 for VALUE in progress */
  3919.  
  3920.     if (ttnet != NET_TCPB) return(0);
  3921.     if (ttnproto != NP_TELNET) return(0);
  3922.     if (sb == NULL) return(-1);
  3923.  
  3924.     if (len == 0) return(1);
  3925.  
  3926.     /*
  3927.     Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
  3928.     follow here until done...
  3929.     */
  3930.     for (i = 0, j = 0, k = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
  3931.         switch (sb[i]) {
  3932.         case TEL_ENV_VAR:               /* VAR */
  3933.         case TEL_ENV_USERVAR:           /* USERVAR */
  3934.         case IAC:                       /* End of the list */
  3935.             switch (type) {
  3936.           case 0:            /* Nothing in progress */
  3937.                 /* If we get IAC only, then that means there were */
  3938.                 /* no environment variables to send.  we are done */
  3939.                 if (j == 0 && sb[i] == IAC)
  3940.                     return(1);
  3941.           case 1:            /* VAR in progress */
  3942.           case 2:            /* USERVAR in progress */
  3943.           case 3:            /* VALUE in progress */
  3944.                 value[k] = '\0';
  3945.                 varname[j] = '\0';
  3946.                 debug(F111,"tn_rnenv varname",varname,type);
  3947.                 debug(F111,"tn_rnenv value",value,type);
  3948.                 if (!strcmp(varname,"USER")) {
  3949. #ifdef CK_AUTHENTICATION
  3950.                     if (ck_tn_auth_valid() != AUTH_VALID) {
  3951.                         extern char szUserNameRequested[];
  3952.                         debug(F100,"tn_rnenv != AUTH_VALID","",0);
  3953.                         ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
  3954.                         ckstrncpy(uidbuf,value,UIDBUFLEN);
  3955. #ifdef CK_SSL
  3956.                         if (ssl_active_flag) {
  3957.                             if ( tls_is_user_valid(ssl_con, uidbuf) ) {
  3958.                                 extern char szUserNameAuthenticated[];
  3959.                                 ckstrncpy(szUserNameAuthenticated,uidbuf,
  3960.                                            UIDBUFLEN);
  3961.                                 auth_finished(AUTH_VALID);
  3962.                             }
  3963.                         } else if (tls_active_flag) {
  3964.                             if ( tls_is_user_valid(tls_con, uidbuf) ) {
  3965.                                 extern char szUserNameAuthenticated[];
  3966.                                 ckstrncpy(szUserNameAuthenticated,uidbuf,
  3967.                                            UIDBUFLEN);
  3968.                                 auth_finished(AUTH_VALID);
  3969.                             }
  3970.                         }
  3971. #endif /* CK_SSL */
  3972.                     } else {    /* AUTH_VALID */
  3973.                         debug(F110,"tn_rnenv AUTH_VALID uidbuf",uidbuf,0);
  3974.                         if ( strcmp(value,uidbuf) ) {
  3975.                             extern char szUserNameRequested[];
  3976.                             ckstrncpy(uidbuf,value,UIDBUFLEN);
  3977.                             ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
  3978.                             auth_finished(AUTH_USER);
  3979. #ifdef CK_SSL
  3980.                             if (ssl_active_flag || tls_active_flag) {
  3981.                                 if ( tls_is_user_valid(ssl_con, uidbuf) )
  3982.                                     auth_finished(AUTH_VALID);
  3983.                             }
  3984. #endif /* CK_SSL */
  3985.                         }
  3986.                     }
  3987. #else /* CK_AUTHENTICATION */
  3988.                     ckstrncpy(uidbuf,value,UIDBUFLEN);
  3989. #endif /* CK_AUTHENTICATION */
  3990.                 }
  3991.                 break;
  3992.             }
  3993.             varname[0] = '\0';
  3994.             value[0] = '\0';
  3995.             j = 0;
  3996.             k = 0;
  3997.             type = (sb[i] == TEL_ENV_USERVAR ? 2 :      /* USERVAR */
  3998.                     sb[i] == TEL_ENV_VAR ? 1 :  /* VAR */
  3999.                      0
  4000.                      );
  4001.             break;
  4002.         case TEL_ENV_VALUE: /* VALUE */
  4003.             if ( type == 1 || type == 2 )
  4004.                 type = 3;
  4005.             break;
  4006.         case TEL_ENV_ESC:       /* ESC */
  4007.             /* Take next character literally */
  4008.             if ( ++i >= len )
  4009.                 break;
  4010.             /* otherwise, fallthrough so byte will be added to string. */
  4011.         default:
  4012.             switch (type) {
  4013.             case 1:     /* VAR in progress */
  4014.             case 2:     /* USERVAR in progress */
  4015.                 if ( j < 16 )
  4016.                     varname[j++] = sb[i];
  4017.                 break;
  4018.             case 3:
  4019.                 if ( k < 64 )
  4020.                     value[k++] = sb[i];
  4021.                 break;
  4022.             }
  4023.         }
  4024.     }
  4025.     return(0);
  4026. }
  4027.  
  4028. /* Telnet send new environment */
  4029. /* Returns -1 on error, 0 if nothing happens, 1 on success */
  4030. /* In order for this code to work, sb[len] == IAC          */
  4031.  
  4032. int
  4033. #ifdef CK_ANSIC
  4034. tn_snenv(CHAR * sb, int len)
  4035. #else
  4036. tn_snenv(sb, len) CHAR * sb; int len;
  4037. #endif /* CK_ANSIC */
  4038. /* tn_snenv */ {                        /* Send new environment */
  4039.     char varname[16];
  4040.     char * reply = 0, * s = 0;
  4041.     int i,j,n;                          /* Worker. */
  4042.     int type = 0;       /* 0 for NONE, 1 for VAR, 2 for USERVAR in progress */
  4043.     extern int ck_lcname;
  4044.     char localuidbuf[UIDBUFLEN];
  4045.     char * uu = uidbuf;
  4046.     char * disp = NULL, tmploc[256];
  4047.  
  4048.     if (ttnet != NET_TCPB) return(0);
  4049.     if (ttnproto != NP_TELNET) return(0);
  4050.     if (!sb) return(-1);
  4051.  
  4052. #ifdef CK_SSL
  4053.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  4054.         return(0);
  4055.     }
  4056. #endif /* CK_SSL */
  4057.  
  4058.     /* Must compute the DISPLAY string we are going to send to the host */
  4059.     /* If one is not assigned, do not send a string unless the user has */
  4060.     /* explicitedly requested we try to send one via X-Display Location */
  4061.  
  4062.     if (tn_env_disp[0]) {
  4063.         int colon = ckindex(":",tn_env_disp,0,0,1);
  4064.         if ( !colon ) {
  4065.             sprintf(tmploc,"%s:%s",myipaddr,tn_env_disp);
  4066.             disp = tmploc;
  4067.         } else if ( ckindex("localhost:",tn_env_disp,0,0,0) ||
  4068.                     ckindex("127.0.0.1:",tn_env_disp,0,0,0) ||
  4069.                     ckindex("0:",tn_env_disp,0,0,0) ) {
  4070.             sprintf(tmploc,"%s:%s",myipaddr,&tn_env_disp[colon]);
  4071.             disp = tmploc;
  4072.         } else
  4073.             disp = tn_env_disp;
  4074.     }
  4075.     else if (TELOPT_ME_MODE(TELOPT_XDISPLOC)) {
  4076.         sprintf(tmploc,"%s:0.0",myipaddr);
  4077.         disp = tmploc;
  4078.     }
  4079.  
  4080.  
  4081.     if (ck_lcname) {
  4082.         ckstrncpy(localuidbuf,uidbuf,UIDBUFLEN);
  4083.         cklower(localuidbuf);
  4084.         uu = localuidbuf;
  4085.     }
  4086.  
  4087.     hexdump((CHAR *)"tn_snenv sb[]",sb,len);
  4088.     debug(F110,"tn_snenv uidbuf",uidbuf,0);
  4089.     debug(F110,"tn_snenv localuidbuf",localuidbuf,0);
  4090.     debug(F110,"tn_snenv tn_env_sys",tn_env_sys,0);
  4091.     debug(F110,"tn_snenv tn_env_disp",tn_env_disp,0);
  4092.     debug(F110,"tn_snenv disp",disp,0);
  4093.  
  4094.     /* First determine the size of the buffer we will need */
  4095.     for (i = 0, j = 0, n = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
  4096.         switch (sb[i]) {
  4097.           case TEL_ENV_VAR:             /* VAR */
  4098.           case TEL_ENV_USERVAR:         /* USERVAR */
  4099.           case IAC:                     /* End of the list */
  4100.             switch (type) {
  4101.               case 0:                   /* Nothing in progress */
  4102.                 /* If we get IAC only, then that means send all */
  4103.                 /* VAR and USERVAR.  But since we don't support */
  4104.                 /* USERVAR yet, we can just pass through        */
  4105.                 if (!(j == 0 && sb[i] == IAC))
  4106.                   break;
  4107.               case 1:                   /* VAR in progress */
  4108.                 varname[j] = '\0' ;
  4109.                 if (!varname[0]) {      /* Send All */
  4110.                     if (uu[0])
  4111.                       n += strlen(uu) + 4 + 2;
  4112.                     if (tn_env_job[0])
  4113.                       n += strlen(tn_env_job) + 3 + 2;
  4114.                     if (tn_env_acct[0])
  4115.                       n += strlen(tn_env_acct) + 4 + 2;
  4116.                     if (tn_env_prnt[0])
  4117.                       n += strlen(tn_env_prnt) + 7 + 2;
  4118.                     if (tn_env_sys[0])
  4119.                       n += strlen(tn_env_sys) + 10 + 2;
  4120.                     if (tn_env_disp[0])
  4121.                       n += strlen(tn_env_disp) + 7 + 2;
  4122.                 } else if (!strcmp(varname,"USER") && uu[0])
  4123.                   n += strlen(uu) + 4 + 2;
  4124.                 else if (!strcmp(varname,"JOB") && tn_env_job[0])
  4125.                   n += strlen(tn_env_job) + 3 + 2;
  4126.                 else if (!strcmp(varname,"ACCT") && tn_env_acct[0])
  4127.                   n += strlen(tn_env_acct) + 4 + 2;
  4128.                 else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0])
  4129.                   n += strlen(tn_env_prnt) + 7 + 2;
  4130.                 else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0])
  4131.                   n += strlen(tn_env_sys) + 10 + 2;
  4132.                 else if (!strcmp(varname,"DISPLAY") && disp)
  4133.                   n += strlen(disp) + 7 + 2;
  4134.                 break;
  4135.               case 2:                   /* USERVAR in progress */
  4136.                 break;                  /* We don't support this yet */
  4137.             }
  4138.             varname[0] = '\0';
  4139.             j = 0;
  4140.             type = (sb[i] == TEL_ENV_USERVAR ? 2 :      /* USERVAR */
  4141.                     sb[i] == TEL_ENV_VAR ? 1 :          /* VAR */
  4142.                     0
  4143.                    );
  4144.             break;
  4145.           case TEL_ENV_VALUE:           /* VALUE */
  4146.             /* Protocol Error */
  4147.             debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
  4148.             if (tn_deb || debses)
  4149.               tn_debug("TELNET Subnegotiation error - VALUE in SEND");
  4150.             return(0);
  4151.           case TEL_ENV_ESC:     /* ESC */
  4152.             if (++i >= len)
  4153.               break;
  4154.           default:
  4155.             if (j < 16 )
  4156.               varname[j++] = sb[i];
  4157.         }
  4158.     }
  4159.     reply = malloc(n + 16);              /* Leave room for IAC stuff */
  4160.     if (!reply) {
  4161.         debug(F100, "TELNET Subnegotiation error - malloc failed", "",0);
  4162.         if (tn_deb || debses)
  4163.           tn_debug("TELNET Subnegotiation error - malloc failed");
  4164.  
  4165.         /* Send a return packet with no variables so that the host */
  4166.         /* may continue with additional negotiations               */
  4167.         if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,"",0) < 0)
  4168.           return(-1);
  4169.         return(0);
  4170.     }
  4171.  
  4172.     /* Now construct the real reply */
  4173.  
  4174.     n = 0;                              /* Start at beginning of buffer */
  4175. /*
  4176.   Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
  4177.   follow here until done...
  4178. */
  4179.     for (i = 0, j = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
  4180.         switch (sb[i]) {
  4181.           case TEL_ENV_VAR:             /* VAR */
  4182.           case TEL_ENV_USERVAR:         /* USERVAR */
  4183.           case IAC:                     /* End of the list */
  4184.             switch (type) {
  4185.               case 0:                   /* Nothing in progress */
  4186.                 /* If we get IAC only, then that means send all */
  4187.                 /* VAR and USERVAR.  But since we don't support */
  4188.                 /* USERVAR yet, we can just pass through        */
  4189.                 if (!(j == 0 && sb[i] == IAC))
  4190.                   break;
  4191.               case 1:                   /* VAR in progress */
  4192.                 varname[j] = '\0';
  4193.                 if (!varname[0]) {
  4194.                     /* Send All */
  4195.                     if (uu[0]) {
  4196.                         reply[n] = TEL_ENV_VAR; /* VAR */
  4197.                         strcpy(&reply[n+1],"USER");
  4198.                         reply[n+5] = TEL_ENV_VALUE;             /* VALUE */
  4199.                         strcpy(&reply[n+6],uu);
  4200.                         n += strlen(uu) + 4 + 2;
  4201.                     }
  4202.                     if (tn_env_job[0]) {
  4203.                         reply[n] = TEL_ENV_VAR; /* VAR */
  4204.                         strcpy(&reply[n+1],"JOB");
  4205.                         reply[n+4] = TEL_ENV_VALUE;     /* VALUE */
  4206.                         strcpy(&reply[n+5],tn_env_job);
  4207.                         n += strlen(tn_env_job) + 3 + 2;
  4208.                     }
  4209.                     if (tn_env_acct[0]) {
  4210.                         reply[n] = TEL_ENV_VAR; /* VAR */
  4211.                         strcpy(&reply[n+1],"ACCT");
  4212.                         reply[n+5] = TEL_ENV_VALUE;     /* VALUE */
  4213.                         strcpy(&reply[n+6],tn_env_acct);
  4214.                         n += strlen(tn_env_acct) + 4 + 2;
  4215.                     }
  4216.                     if (tn_env_prnt[0]) {
  4217.                         reply[n] = TEL_ENV_VAR; /* VAR */
  4218.                         strcpy(&reply[n+1],"PRINTER");
  4219.                         reply[n+8] = TEL_ENV_VALUE;     /* VALUE */
  4220.                         strcpy(&reply[n+9],tn_env_prnt);
  4221.                         n += strlen(tn_env_prnt) + 7 + 2;
  4222.                     }
  4223.                     if (tn_env_sys[0]) {
  4224.                         reply[n] = TEL_ENV_VAR; /* VAR */
  4225.                         strcpy(&reply[n+1],"SYSTEMTYPE");
  4226.                         reply[n+11] = TEL_ENV_VALUE; /* VALUE */
  4227.                         strcpy(&reply[n+12],tn_env_sys);
  4228.                         n += strlen(tn_env_sys) + 10 + 2;
  4229.                     }
  4230.                     if (disp) {
  4231.                         reply[n] = TEL_ENV_VAR; /* VAR */
  4232.                         strcpy(&reply[n+1],"DISPLAY");
  4233.                         reply[n+8] = TEL_ENV_VALUE;     /* VALUE */
  4234.                         strcpy(&reply[n+9],disp);
  4235.                         n += strlen(disp) + 7 + 2;
  4236.                     }
  4237.                 } else if (!strcmp(varname,"USER") && uu[0]) {
  4238.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  4239.                     strcpy(&reply[n+1],"USER");
  4240.                     reply[n+5] = TEL_ENV_VALUE; /* VALUE */
  4241.                     strcpy(&reply[n+6],uu);
  4242.                     n += strlen(uu) + 4 + 2;
  4243.                 } else if (!strcmp(varname,"JOB") && tn_env_job[0]) {
  4244.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  4245.                     strcpy(&reply[n+1],"JOB");
  4246.                     reply[n+4] = TEL_ENV_VALUE; /* VALUE */
  4247.                     strcpy(&reply[n+5],tn_env_job);
  4248.                     n += strlen(tn_env_job) + 3 + 2;
  4249.                 } else if (!strcmp(varname,"ACCT") && tn_env_acct[0]) {
  4250.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  4251.                     strcpy(&reply[n+1],"ACCT");
  4252.                     reply[n+5] = TEL_ENV_VALUE; /* VALUE */
  4253.                     strcpy(&reply[n+6],tn_env_acct);
  4254.                     n += strlen(tn_env_acct) + 4 + 2;
  4255.                 } else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0]) {
  4256.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  4257.                     strcpy(&reply[n+1],"PRINTER");
  4258.                     reply[n+8] = TEL_ENV_VALUE; /* VALUE */
  4259.                     strcpy(&reply[n+9],tn_env_prnt);
  4260.                     n += strlen(tn_env_prnt) + 7 + 2;
  4261.                 } else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0]) {
  4262.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  4263.                     strcpy(&reply[n+1],"SYSTEMTYPE");
  4264.                     reply[n+11] = TEL_ENV_VALUE;        /* VALUE */
  4265.                     strcpy(&reply[n+12],tn_env_sys);
  4266.                     n += strlen(tn_env_sys) + 10 + 2;
  4267.                 } else if (!strcmp(varname,"DISPLAY") && disp) {
  4268.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  4269.                     strcpy(&reply[n+1],"DISPLAY");
  4270.                     reply[n+8] = TEL_ENV_VALUE; /* VALUE */
  4271.                     strcpy(&reply[n+9],disp);
  4272.                     n += strlen(disp) + 7 + 2;
  4273.                 }
  4274.                 break;
  4275.             case 2:     /* USERVAR in progress */
  4276.                 /* we don't support this yet */
  4277.                 break;
  4278.             }
  4279.             varname[0] = '\0';
  4280.             j = 0;
  4281.             type = (sb[i] == TEL_ENV_USERVAR ? 2 :      /* USERVAR */
  4282.                     sb[i] == TEL_ENV_VAR ? 1 :  /* VAR */
  4283.                     0
  4284.                    );
  4285.             break;
  4286.           case TEL_ENV_VALUE: /* VALUE */
  4287.             /* Protocol Error */
  4288.             debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
  4289.             if (tn_deb || debses)
  4290.               tn_debug("TELNET Subnegotiation error - VALUE in SEND");
  4291.             return(0);  /* Was -1 but that would be taken as */
  4292.                         /* an I/O error, so absorb it and go on. */
  4293.           case TEL_ENV_ESC:     /* ESC */
  4294.             /* Not sure what this for.  Quote next character? */
  4295.             break;
  4296.           default:
  4297.             varname[j++] = sb[i];
  4298.         }
  4299.     }
  4300.     if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,reply,n) < 0) {
  4301.         free(reply);
  4302.         return(-1);
  4303.     }
  4304.     free(reply);
  4305.     return(1);
  4306. }
  4307. #endif /* CK_ENVIRONMENT */
  4308.  
  4309. /* Telnet send terminal type */
  4310. /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
  4311.  
  4312. int
  4313. tn_sttyp() {                            /* Send telnet terminal type. */
  4314.     char *ttn;                          /* Name of terminal type. */
  4315. #ifdef OS2
  4316.     static int alias = -1;              /* which alias are we using ? */
  4317. #endif /* OS2 */
  4318.     int i;                              /* Worker. */
  4319.     int tntermflg = 0;
  4320.     int settype = 0;
  4321.  
  4322.     if (ttnet != NET_TCPB) return(0);
  4323.     if (ttnproto != NP_TELNET) return(0);
  4324.  
  4325.     if (!TELOPT_ME(TELOPT_TTYPE)) return(0);
  4326.  
  4327. #ifdef CK_SSL
  4328.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  4329.         return(0);
  4330.     }
  4331. #endif /* CK_SSL */
  4332.     ttn = NULL;
  4333.  
  4334. #ifdef OS2
  4335.     if (!tn_term) {
  4336.         if (ttnum == -1) {
  4337.             ttnum = tt_type;
  4338.             settype = 0;
  4339.             alias = -1;
  4340.         } else if (ttnumend) {
  4341.             ttnumend = 0;
  4342.             settype = 0;
  4343.         } else {
  4344.             if (tt_info[tt_type].x_aliases[++alias] == NULL)  {
  4345.                 if (--tt_type < 0)
  4346.                   tt_type = max_tt;
  4347.                 if (ttnum == tt_type)
  4348.                   ttnumend = 1;
  4349.                 settype = 1;
  4350.                 alias = -1;
  4351.             }
  4352.         }
  4353.         if (tt_type >= 0 && tt_type <= max_tt) {
  4354.             if (alias == -1)
  4355.               ttn = tt_info[tt_type].x_name;
  4356.             else
  4357.               ttn = tt_info[tt_type].x_aliases[alias];
  4358.         } else
  4359.           ttn = NULL;
  4360.     }
  4361.     else settype = 0;
  4362. #endif /* OS2 */
  4363.  
  4364.     if (tn_term) {                      /* Terminal type override? */
  4365.         debug(F110,"tn_sttyp",tn_term,0);
  4366.         if (*tn_term) {
  4367.             ttn = tn_term;
  4368.             tntermflg = 1;
  4369.         }
  4370.     } else debug(F100,"tn_sttyp no term override","",0);
  4371.  
  4372. #ifndef datageneral
  4373.     if (!ttn) {                         /* If no override, */
  4374.         ttn = getenv("TERM");           /* get it from the environment. */
  4375.     }
  4376. #endif /* datageneral */
  4377.     if ((ttn == ((char *)0)) || ((int)strlen(ttn) >= TSBUFSIZ))
  4378.       ttn = "UNKNOWN";
  4379.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  4380.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  4381.     sb[2] = TELOPT_TTYPE;               /* Terminal Type */
  4382.     sb[3] = (CHAR) 0;                   /* Is... */
  4383.     for (i = 4; *ttn; ttn++,i++) {      /* Copy and uppercase it */
  4384. #ifdef VMS
  4385.         if (!tntermflg && *ttn == '-' &&
  4386.             (!strcmp(ttn,"-80") || !strcmp(ttn,"-132")))
  4387.           break;
  4388.         else
  4389. #endif /* VMS */
  4390.         sb[i] = (char) ((!tntermflg && islower(*ttn)) ? toupper(*ttn) : *ttn);
  4391.     }
  4392.     ttn = (char *)sb;                   /* Point back to beginning */
  4393.     if (deblog || tn_deb || debses) {
  4394.         sb[i] = '\0';                   /* For debugging */
  4395.         sprintf(tn_msg,"TELNET SENT SB %s IS %s IAC SE",
  4396.                  TELOPT(TELOPT_TTYPE),sb+4);
  4397.         debug(F100,tn_msg,"",0);
  4398.         if (tn_deb || debses) tn_debug(tn_msg);
  4399.     }
  4400.     sb[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  4401.     sb[i++] = (CHAR) SE;                /* marked by IAC SE */
  4402.     if (ttol((CHAR *)sb,i) < 0)         /* Send it. */
  4403.       return(-1);
  4404. #ifdef OS2
  4405.     if (settype)
  4406.         settermtype(tt_type,0);
  4407.     else {
  4408.         ipadl25();
  4409.         VscrnIsDirty(VTERM);
  4410.     }
  4411. #endif /* OS2 */
  4412.     return(1);
  4413. }
  4414.  
  4415. #ifdef CK_ENVIRONMENT
  4416. #ifdef CK_XDISPLOC
  4417.  
  4418. /* Telnet send xdisplay location */
  4419. /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
  4420.  
  4421. int
  4422. tn_sxdisploc() {                        /* Send telnet X display location. */
  4423.     char * disp=NULL;
  4424.     char tmploc[256];
  4425.     int i;
  4426.  
  4427.     tmploc[0] = '\0';
  4428.     if (ttnet != NET_TCPB) return(0);
  4429.     if (ttnproto != NP_TELNET) return(0);
  4430.  
  4431.     if (!TELOPT_ME(TELOPT_XDISPLOC)) return(0);
  4432.  
  4433. #ifdef CK_SSL
  4434.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  4435.         return(0);
  4436.     }
  4437. #endif /* CK_SSL */
  4438.     if (tn_env_disp[0]) {
  4439.         int colon = ckindex(":",tn_env_disp,0,0,1);
  4440.         if ( !colon ) {
  4441.             sprintf(tmploc,"%s:%s",myipaddr,tn_env_disp);
  4442.             disp = tmploc;
  4443.         } else if ( ckindex("localhost:",tn_env_disp,0,0,0) ||
  4444.                     ckindex("127.0.0.1:",tn_env_disp,0,0,0) ||
  4445.                     ckindex("0:",tn_env_disp,0,0,0) ) {
  4446.             sprintf(tmploc,"%s:%s",myipaddr,&tn_env_disp[colon]);
  4447.             disp = tmploc;
  4448.         } else
  4449.             disp = tn_env_disp;
  4450.     } else {
  4451.         sprintf(tmploc,"%s:0.0",myipaddr);
  4452.         disp = tmploc;
  4453.     }
  4454.     debug(F110,"tn_sxdisploc",disp,0);
  4455.  
  4456.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  4457.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  4458.     sb[2] = TELOPT_XDISPLOC;            /* X-Display Location */
  4459.     sb[3] = (CHAR) 0;                   /* Is... */
  4460.     for (i = 4; *disp; disp++,i++) {      /* Copy and uppercase it */
  4461.         sb[i] = (char) *disp;
  4462.     }
  4463.     if (deblog || tn_deb || debses) {
  4464.         sb[i] = '\0';                   /* For debugging */
  4465.         sprintf(tn_msg,
  4466.                 "TELNET SENT SB %s IS %s IAC SE",
  4467.                 TELOPT(TELOPT_XDISPLOC),sb+4);
  4468.         debug(F100,tn_msg,"",0);
  4469.         if (tn_deb || debses) tn_debug(tn_msg);
  4470.     }
  4471.     sb[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  4472.     sb[i++] = (CHAR) SE;                /* marked by IAC SE */
  4473.     if (ttol((CHAR *)sb,i) < 0)         /* Send it. */
  4474.       return(-1);
  4475.     return(1);
  4476. }
  4477. #endif /* CK_XDISPLOC */
  4478. #endif /* CK_ENVIRONMENT */
  4479.  
  4480. #ifdef CK_FORWARD_X
  4481. int
  4482. tn_sndfwdx() {                          /* Send Fwd X Screen number to host */
  4483.     unsigned char screen = 0;
  4484.  
  4485.     if (!TELOPT_U(TELOPT_FORWARD_X)) return(0);
  4486. #ifdef CK_SSL
  4487.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  4488.         return(0);
  4489.     }
  4490. #endif /* CK_SSL */
  4491.  
  4492.     /*
  4493.      * The format of the DISPLAY variable is [<host>:]<display>[.<screen>]
  4494.      * where <host> is an optional DNS name or ip address with a default of
  4495.      * the localhost; the screen defaults to 0
  4496.      */
  4497.  
  4498.     if (tn_env_disp[0]) {
  4499.         int colon,dot;
  4500.         colon = ckindex(":",tn_env_disp,0,0,1);
  4501.         dot   = ckindex(".",&tn_env_disp[colon],0,0,1);
  4502.  
  4503.         if ( dot ) {
  4504.             screen = atoi(&tn_env_disp[colon+dot]);
  4505.         }
  4506.     } else {
  4507.         return(-1);
  4508.     }
  4509.  
  4510.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  4511.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  4512.     sb[2] = TELOPT_FORWARD_X;           /* Forward X */
  4513.     sb[3] = FWDX_SCREEN;                /* Screen */
  4514.     sb[4] = screen;
  4515.     sb[5] = (CHAR) IAC;                 /* End of Subnegotiation */
  4516.     sb[6] = (CHAR) SE;                  /* marked by IAC SE */
  4517.     if (ttol((CHAR *)sb,7) < 0)         /* Send it. */
  4518.       return(-1);
  4519. #ifdef DEBUG
  4520.     if (deblog || tn_deb || debses) {
  4521.         sprintf(tn_msg,"TELNET SENT SB %s SCREEN %02x IAC SE",
  4522.         TELOPT(TELOPT_FORWARD_X),screen);
  4523.         debug(F100,tn_msg,"",0);
  4524.         if (tn_deb || debses) tn_debug(tn_msg);
  4525.     }
  4526. #endif /* DEBUG */
  4527.     return(0);
  4528. }
  4529. #endif /* CK_FORWARD_X */
  4530.  
  4531. #ifdef CK_SNDLOC
  4532. int
  4533. tn_sndloc() {                           /* Send location. */
  4534.     int i;                              /* Worker. */
  4535.     char *ttloc;
  4536.  
  4537.     if (!TELOPT_ME(TELOPT_SNDLOC)) return(0);
  4538.  
  4539. #ifdef CK_SSL
  4540.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  4541.         return(0);
  4542.     }
  4543. #endif /* CK_SSL */
  4544.     ttloc = (tn_loc ? tn_loc : "");     /* In case we are being called even */
  4545.                                         /* though there is no location. */
  4546.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  4547.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  4548.     sb[2] = TELOPT_SNDLOC;              /* Location */
  4549.     for (i = 3; *ttloc && i < TSBUFSIZ; ttloc++,i++) /* Copy it */
  4550.       sb[i] = (char) *ttloc;
  4551.     sb[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  4552.     sb[i++] = (CHAR) SE;                /* marked by IAC SE */
  4553.     if (ttol((CHAR *)sb,i) < 0)         /* Send it. */
  4554.       return(-1);
  4555.     sb[i-2] = '\0';                     /* For debugging */
  4556. #ifdef DEBUG
  4557.     if (deblog || tn_deb || debses) {
  4558.         sprintf(tn_msg,"TELNET SENT SB %s %s IAC SE",
  4559.         TELOPT(TELOPT_SNDLOC),sb+3);
  4560.         debug(F100,tn_msg,"",0);
  4561.         if (tn_deb || debses) tn_debug(tn_msg);
  4562.     }
  4563. #endif /* DEBUG */
  4564.     return(0);
  4565. }
  4566. #endif /* CK_SNDLOC */
  4567.  
  4568. #ifdef CK_NAWS                  /*  NAWS = Negotiate About Window Size  */
  4569. int
  4570. tn_snaws() {                    /*  Send terminal width and height, RFC 1073 */
  4571.     int i = 0;
  4572. #ifdef OS2
  4573.     int x = VscrnGetWidth(VTERM),
  4574.     y = VscrnGetHeight(VTERM) - (tt_status ? 1 : 0);
  4575. #else /* OS2 */
  4576.     int x = tt_cols, y = tt_rows;
  4577. #endif /* OS2 */
  4578.  
  4579.     if (ttnet != NET_TCPB) return(0);
  4580.     if (ttnproto != NP_TELNET) return(0);
  4581.     if (!TELOPT_ME(TELOPT_NAWS)) return(0);
  4582.  
  4583. #ifdef CK_SSL
  4584.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  4585.         return(0);
  4586.     }
  4587. #endif /* CK_SSL */
  4588.     if (x < 0) x = 0;
  4589.     if (y < 0) y = 0;
  4590.  
  4591.     if (x == TELOPT_SB(TELOPT_NAWS).naws.x && /* Only send if changed */
  4592.         y == TELOPT_SB(TELOPT_NAWS).naws.y
  4593.         )
  4594.       return(0);
  4595.     TELOPT_SB(TELOPT_NAWS).naws.x = x;  /* Remember the size     */
  4596.     TELOPT_SB(TELOPT_NAWS).naws.y = y;
  4597.  
  4598.     sb[i++] = (CHAR) IAC;               /* Send the subnegotiation */
  4599.     sb[i++] = (CHAR) SB;
  4600.     sb[i++] = TELOPT_NAWS;
  4601.     sb[i++] = (CHAR) (x >> 8) & 0xff;
  4602.     if ((CHAR) sb[i-1] == (CHAR) IAC)   /* IAC in data must be doubled */
  4603.       sb[i++] = (CHAR) IAC;
  4604.     sb[i++] = (CHAR) (x & 0xff);
  4605.     if ((CHAR) sb[i-1] == (CHAR) IAC)
  4606.       sb[i++] = (CHAR) IAC;
  4607.     sb[i++] = (CHAR) (y >> 8) & 0xff;
  4608.     if ((CHAR) sb[i-1] == (CHAR) IAC)
  4609.       sb[i++] = (CHAR) IAC;
  4610.     sb[i++] = (CHAR) (y & 0xff);
  4611.     if ((CHAR) sb[i-1] == (CHAR) IAC)
  4612.       sb[i++] = (CHAR) IAC;
  4613.     sb[i++] = (CHAR) IAC;
  4614.     sb[i++] = (CHAR) SE;
  4615.     if (deblog || tn_deb || debses) {
  4616.         sprintf(tn_msg,"TELNET SENT SB NAWS %d %d IAC SE",x,y);
  4617.         debug(F100,tn_msg,"",0);
  4618.         if (tn_deb || debses) tn_debug(tn_msg);
  4619.     }
  4620.     if (ttol((CHAR *)sb,i) < 0)         /* Send it. */
  4621.       return(-1);
  4622.     return (0);
  4623. }
  4624. #endif /* CK_NAWS */
  4625. #endif /* TNCODE */
  4626.