1 char *cktelv = "Telnet support, 9.0.277, 12 Apr 2013";
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 Telnet Forward X by Jeffrey Altman
12 Telnet START_TLS support by Jeffrey Altman
13 Telnet AUTH and ENCRYPT support by Jeffrey Altman
14 Telnet COMPORT support by Jeffrey Altman
15 Telnet NEW-ENVIRONMENT support by Jeffrey Altman
16 Telnet NAWS support by Frank da Cruz and Jeffrey Altman
17 Telnet TERMTYPE support by Jeffrey Altman
18 Telnet KERMIT support by Jeffrey Altman
19 Other contributions as indicated in the code.
20
21 Copyright (C) 1985, 2013,
22 Trustees of Columbia University in the City of New York.
23 All rights reserved. See the C-Kermit COPYING.TXT file or the
24 copyright text in the ckcmai.c module for disclaimer and permissions.
25 */
26
27 /*
28 NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
29 C-Kermit source files, must be compatible with C preprocessors that support
30 only #ifdef, #else, #endif, #define, and #undef. Please do not use #if,
31 logical operators, or other preprocessor features in this module. Also,
32 don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
33 */
34
35 #include "ckcsym.h"
36 #include "ckcdeb.h"
37
38 #ifdef TNCODE
39 #include "ckcker.h"
40 #define TELCMDS /* to define name array */
41 #define TELOPTS /* to define name array */
42 #define SLC_NAMES /* to define name array */
43 #define ENCRYPT_NAMES
44 #define AUTH_NAMES
45 #define TELOPT_STATES
46 #define TELOPT_MODES
47 #define TNC_NAMES
48 #include "ckcnet.h"
49 #include "ckctel.h"
50 #ifdef CK_AUTHENTICATION
51 #include "ckuath.h"
52 #endif /* CK_AUTHENTICATION */
53 #ifdef CK_SSL
54 #include "ck_ssl.h"
55 #endif /* CK_SSL */
56
57 #ifndef NOTERM
58 #ifdef OS2 /* For terminal type name string */
59 #include "ckuusr.h"
60 #ifndef NT
61 #include <os2.h>
62 #undef COMMENT
63 #else
64 #define isascii __isascii
65 #endif /* NT */
66 #include "ckocon.h"
67 extern int tt_type, max_tt;
68 extern struct tt_info_rec tt_info[];
69 #endif /* OS2 */
70 #endif /* NOTERM */
71
72 #ifdef OS2
73 #include <assert.h>
74 #ifdef NT
75 #include <setjmpex.h>
76 #else /* NT */
77 #include <setjmp.h>
78 #endif /* NT */
79 #include <signal.h>
80 #include "ckcsig.h"
81 #include "ckosyn.h"
82 #endif /* OS2 */
83
84 #ifdef CK_NAWS /* Negotiate About Window Size */
85 #ifdef RLOGCODE
86 _PROTOTYP( int rlog_naws, (void) );
87 #endif /* RLOGCODE */
88 #endif /* CK_NAWS */
89
90 int tn_init = 0; /* Telnet protocol initialized flag */
91 int tn_begun = 0; /* Telnet protocol started flag */
92 static int tn_first = 1; /* First time init flag */
93 extern int tn_exit; /* Exit on disconnect */
94 extern int nettype;
95 extern int inserver; /* Running as IKSD */
96 char *tn_term = NULL; /* Terminal type override */
97
98 #ifdef CK_SNDLOC
99 char *tn_loc = NULL; /* Location override */
100 #endif /* CK_SNDLOC */
101 int tn_nlm = TNL_CRLF; /* Telnet CR -> CR LF mode */
102 int tn_b_nlm = TNL_CR; /* Telnet Binary CR RAW mode */
103 int tn_b_meu = 0; /* Telnet Binary ME means U too */
104 int tn_b_ume = 0; /* Telnet Binary U means ME too */
105 int tn_wait_flg = 1; /* Telnet Wait for Negotiations */
106 int tn_infinite = 0; /* Telnet Bug Infinite-Loop-Check */
107 int tn_rem_echo = 1; /* We will echo if WILL ECHO */
108 int tn_b_xfer = 0; /* Telnet Binary for Xfers? */
109 int tn_sb_bug = 1; /* Telnet BUG - SB w/o WILL or DO */
110 int tn_auth_krb5_des_bug = 1; /* Telnet BUG - AUTH KRB5 DES */
111 /* truncates long keys */
112 int tn_no_encrypt_xfer = 0; /* Turn off Telnet Encrypt? */
113 int tn_delay_sb = 1; /* Delay SBs until safe */
114 int tn_auth_how = TN_AUTH_HOW_ANY;
115 int tn_auth_enc = TN_AUTH_ENC_ANY;
116 int tn_deb = 0; /* Telnet Debug mode */
117 int tn_sfu = 0; /* Microsoft SFU compatibility */
118 #ifdef CK_FORWARD_X
119 char * tn_fwdx_xauthority = NULL; /* Xauthority File */
120 int fwdx_no_encrypt = 0; /* Forward-X requires encryption */
121 #endif /* CK_FORWARD_X */
122
123 #ifdef OS2
124 int ttnum = -1; /* Last Telnet Terminal Type sent */
125 int ttnumend = 0; /* Has end of list been found */
126 #endif /* OS2 */
127
128 char tn_msg[TN_MSG_LEN]; /* Telnet data can be rather long */
129 char hexbuf[TN_MSG_LEN];
130 char tn_msg_out[TN_MSG_LEN];
131 #ifdef CK_FORWARD_X
132 CHAR fwdx_msg_out[TN_MSG_LEN];
133 #endif /* CK_FORWARD_X */
134
135 /*
136 In order to prevent an infinite telnet negotiation loop we maintain a
137 count of the number of times the same telnet negotiation message is
138 sent. When this count hits MAXTNCNT, we do not send any more of the
139 message. The count is stored in the tncnts[][] array.
140
141 The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
142 TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
143 negotiation message types (WILL, WONT, DO, DONT). All telnet negotiations
144 are kept track of in this way.
145
146 The count for a message is zeroed when the "opposite" message is sent.
147 WILL is the opposite of WONT, and DO is the opposite of DONT.
148 For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
149 and zeroes tncnts[TELOPT_SGA][1].
150
151 The code that does this is in tn_sopt().
152
153 rogersh@fsj.co.jp, 18/3/1995
154
155 8/16/1998 - with the recent rewrite of the telnet state machine I don't
156 think this code is necessary anymore. However, it can't do any harm so
157 I am leaving it in. - Jeff
158
159 12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
160 because the Telnet option list is no longer contiguous. We also must
161 allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
162 for an invalid option number.
163 */
164
165 #define MAXTNCNT 4 /* Permits 4 intermediate telnet firewalls/gateways */
166
167 char tncnts[NTELOPTS+1][4]; /* Counts */
168 char tnopps[4] = { 1,0,3,2 }; /* Opposites */
169
170 #ifdef CK_ENVIRONMENT
171 #ifdef CK_FORWARD_X
172 #define TSBUFSIZ 2056
173 #else /* CK_FORWARD_X */
174 #define TSBUFSIZ 1024
175 #endif /* CK_FORWARD_X */
176 char tn_env_acct[64];
177 char tn_env_disp[64];
178 char tn_env_job[64];
179 char tn_env_prnt[64];
180 char tn_env_sys[64];
181 char * tn_env_uservar[8][2];
182 int tn_env_flg = 1;
183 #else /* CK_ENVIRONMENT */
184 #define TSBUFSIZ 41
185 int tn_env_flg = 0;
186 #endif /* CK_ENVIRONMENT */
187
188 #ifdef COMMENT
189 /* SIGWINCH handler moved to ckuusx.c */
190 #ifndef NOSIGWINCH
191 #ifdef CK_NAWS /* Window size business */
192 #ifdef UNIX
193 #include <signal.h>
194 #endif /* UNIX */
195 #endif /* CK_NAWS */
196 #endif /* NOSIGWINCH */
197 #endif /* COMMENT */
198
199 CHAR sb[TSBUFSIZ]; /* Buffer - incoming subnegotiations */
200 CHAR sb_out[TSBUFSIZ]; /* Buffer - outgoing subnegotiations */
201
202 int tn_duplex = 1; /* Local echo */
203
204 extern char uidbuf[]; /* User ID buffer */
205 extern int quiet, ttnet, ttnproto, debses, what, duplex, oldplex, local;
206 extern int seslog, sessft, whyclosed;
207 #ifdef OS2
208 #ifndef NOTERM
209 extern int tt_rows[], tt_cols[];
210 extern int tt_status[VNUM];
211 extern int scrninitialized[];
212 #endif /* NOTERM */
213 #else /* OS2 */
214 extern int tt_rows, tt_cols; /* Everybody has this */
215 #endif /* OS2 */
216 extern int cmd_cols, cmd_rows;
217 extern char namecopy[];
218 extern char myipaddr[]; /* Global copy of my IP address */
219
220 #ifndef TELOPT_MACRO
221 int
telopt_index(opt)222 telopt_index(opt) int opt; {
223 if (opt >= 0 && opt <= TELOPT_STDERR)
224 return(opt);
225 else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
226 return(opt-88);
227 else if (opt == TELOPT_IBM_SAK)
228 return(opt-147);
229 else
230 return(NTELOPTS);
231 }
232
233 int
telopt_ok(opt)234 telopt_ok(opt) int opt; {
235 return((opt >= TELOPT_BINARY && opt <= TELOPT_STDERR) ||
236 (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
237 (opt == TELOPT_IBM_SAK));
238 }
239
240 CHAR *
telopt(opt)241 telopt(opt) int opt; {
242 if (telopt_ok(opt))
243 return((CHAR *)telopts[telopt_index(opt)]);
244 else
245 return((CHAR *)"UNKNOWN");
246 }
247
248 int
telopt_mode_ok(opt)249 telopt_mode_ok(opt) int opt; {
250 return((unsigned int)(opt) <= TN_NG_MU);
251 }
252
253 CHAR *
telopt_mode(opt)254 telopt_mode(opt) int opt; {
255 if (telopt_mode_ok(opt))
256 return((CHAR *)telopt_modes[opt-TN_NG_RF]);
257 else
258 return((CHAR *)"UNKNOWN");
259 }
260 #endif /* TELOPT_MACRO */
261
262 static int
tn_outst(notquiet)263 tn_outst(notquiet) int notquiet; {
264 int outstanding = 0;
265 int x = 0;
266 #ifdef CK_ENCRYPTION
267 int e = 0;
268 int d = 0;
269 #endif /* CK_ENCRYPTION */
270
271 if (tn_wait_flg) {
272 for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
273 if (TELOPT_OK(x)) {
274 if (TELOPT_UNANSWERED_WILL(x)) {
275 if ( notquiet )
276 printf("?Telnet waiting for response to WILL %s\r\n",
277 TELOPT(x));
278 debug(F111,"tn_outst","unanswered WILL",x);
279 outstanding = 1;
280 if ( !notquiet )
281 break;
282 }
283 if (TELOPT_UNANSWERED_DO(x)) {
284 if ( notquiet )
285 printf("?Telnet waiting for response to DO %s\r\n",
286 TELOPT(x));
287 debug(F111,"tn_outst","unanswered DO",x);
288 outstanding = 1;
289 if ( !notquiet )
290 break;
291 }
292 if (TELOPT_UNANSWERED_WONT(x)) {
293 if ( notquiet )
294 printf("?Telnet waiting for response to WONT %s\r\n",
295 TELOPT(x));
296 debug(F111,"tn_outst","unanswered WONT",x);
297 outstanding = 1;
298 if ( !notquiet )
299 break;
300 }
301 if (TELOPT_UNANSWERED_DONT(x)) {
302 if ( notquiet )
303 printf("?Telnet waiting for response to DONT %s\r\n",
304 TELOPT(x));
305 debug(F111,"tn_outst","unanswered DONT",x);
306 outstanding = 1;
307 if ( !notquiet )
308 break;
309 }
310 if (TELOPT_UNANSWERED_SB(x)) {
311 if ( notquiet )
312 printf("?Telnet waiting for response to SB %s\r\n",
313 TELOPT(x));
314 debug(F111,"tn_outst","unanswered SB",x);
315 outstanding = 1;
316 if ( !notquiet )
317 break;
318 }
319 }
320 }
321 #ifdef CK_AUTHENTICATION
322 if (ck_tn_auth_in_progress()) {
323 if (TELOPT_ME(TELOPT_AUTHENTICATION)) {
324 if (notquiet)
325 printf("?Telnet waiting for WILL %s subnegotiation\r\n",
326 TELOPT(TELOPT_AUTHENTICATION));
327 debug(F111,
328 "tn_outst",
329 "ME authentication in progress",
330 TELOPT_AUTHENTICATION
331 );
332 outstanding = 1;
333 } else if (TELOPT_U(TELOPT_AUTHENTICATION)) {
334 if (notquiet)
335 printf("?Telnet waiting for DO %s subnegotiation\r\n",
336 TELOPT(TELOPT_AUTHENTICATION));
337 debug(F111,
338 "tn_outst",
339 "U authentication in progress",
340 TELOPT_AUTHENTICATION
341 );
342 outstanding = 1;
343 }
344 }
345 #endif /* CK_AUTHENTICATION */
346 #ifdef CK_ENCRYPTION
347 if (!outstanding) {
348 e = ck_tn_encrypting();
349 d = ck_tn_decrypting();
350 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
351 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
352 !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
353 ) {
354 if ( notquiet )
355 printf("?Telnet waiting for WILL %s subnegotiation\r\n",
356 TELOPT(TELOPT_ENCRYPTION));
357 debug(F111,
358 "tn_outst",
359 "encryption mode switch",
360 TELOPT_ENCRYPTION
361 );
362 outstanding = 1;
363 }
364 }
365 if (TELOPT_U(TELOPT_ENCRYPTION)) {
366 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
367 !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
368 ) {
369 if ( notquiet )
370 printf("?Telnet waiting for DO %s subnegotiation\r\n",
371 TELOPT(TELOPT_ENCRYPTION));
372 debug(F111,
373 "tn_outst",
374 "decryption mode switch",
375 TELOPT_ENCRYPTION
376 );
377 outstanding = 1;
378 }
379 }
380 }
381 #endif /* CK_ENCRYPTION */
382 } /* if (tn_wait_flg) */
383
384 #ifdef IKS_OPTION
385 /* Even if we are not waiting for Telnet options we must wait for */
386 /* Kermit Telnet Subnegotiations if we have sent a request to the */
387 /* other guy. Otherwise we will get out of sync. */
388 if (!outstanding) {
389 if (TELOPT_U(TELOPT_KERMIT) &&
390 (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
391 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
392 !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
393 ) {
394 if ( notquiet )
395 printf("?Telnet waiting for SB %s negotiation\r\n",
396 TELOPT(TELOPT_KERMIT));
397 debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
398 outstanding = 1;
399 }
400 }
401 #endif /* IKS_OPTION */
402
403 #ifdef TN_COMPORT
404 if (!outstanding) {
405 if (TELOPT_ME(TELOPT_COMPORT)) {
406 if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb) {
407 if (notquiet)
408 printf("?Telnet waiting for SB %s negotiation\r\n",
409 TELOPT(TELOPT_COMPORT));
410 debug(F111,"tn_outst","ComPort SB in progress",TELOPT_COMPORT);
411 outstanding = 1;
412 }
413 if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms) {
414 if (notquiet)
415 printf("?Telnet waiting for SB %s MODEM_STATUS negotiation\r\n",
416 TELOPT(TELOPT_COMPORT));
417 debug(F111,"tn_outst","ComPort SB MS in progress",TELOPT_COMPORT);
418 outstanding = 1;
419 }
420 }
421 }
422 #endif /* TN_COMPORT */
423 return(outstanding);
424 }
425
426 int
istncomport()427 istncomport() {
428 #ifdef TN_COMPORT
429 if (!local) return(0);
430 if (ttnet != NET_TCPB) return(0);
431 if (ttnproto != NP_TELNET) return(0);
432 if (TELOPT_ME(TELOPT_COMPORT))
433 return(1);
434 else
435 #endif /* TN_COMPORT */
436 return(0);
437 }
438
439 /* tn_wait() -- Wait for response to Telnet negotiation. */
440 /*
441 Wait for up to <timeout> seconds for the response to arrive.
442 Place all non-telnet data into Telnet Wait Buffer.
443 If response does arrive return 1, else return 0.
444 */
445 #ifndef TN_WAIT_BUF_SZ
446 #define TN_WAIT_BUF_SZ 4096
447 #endif /* TN_WAIT_BUF_SZ */
448 static char tn_wait_buf[TN_WAIT_BUF_SZ];
449 static int tn_wait_idx = 0;
450 #ifndef TN_TIMEOUT
451 #define TN_TIMEOUT 120
452 #endif /* TN_TIMEOUT */
453 static int tn_wait_tmo = TN_TIMEOUT;
454
455 #ifdef CKSPINNER
456 VOID
prtwait(state)457 prtwait(state) int state; {
458 switch (state % 4) {
459 case 0:
460 printf("/");
461 break;
462 case 1:
463 printf("-");
464 break;
465 case 2:
466 printf("\\");
467 break;
468 case 3:
469 printf("|");
470 break;
471 }
472 }
473 #endif /* CKSPINNER */
474
475 static int nflag = 0;
476
477 int
478 #ifdef CK_ANSIC
tn_wait(char * where)479 tn_wait(char * where)
480 #else
481 tn_wait(where) char * where;
482 #endif /* CK_ANSIC */
483 /* tn_wait */ {
484 extern int ckxech, local;
485 int ch = 0, count = 0;
486 #ifndef NOHINTS
487 int nohintgiven = 1;
488 extern int hints;
489 #endif /* NOHINTS */
490 int outstanding;
491 #ifdef TN_COMPORT
492 int savcarr;
493 extern int ttcarr;
494 #endif /* TN_COMPORT */
495
496 /* if (!IS_TELNET()) return(1); */
497
498 rtimer();
499
500 debug(F110,"tn_wait waiting for",where,0);
501 tn_wait_tmo = TN_TIMEOUT;
502 debug(F111,"tn_wait","timeout",tn_wait_tmo);
503 outstanding = tn_outst(0);
504 debug(F111,"tn_wait","outstanding",outstanding);
505 debug(F111,"tn_wait","tn_wait_flg",tn_wait_flg);
506
507 /* The following is meant to be !(||). We only want to return */
508 /* immediately if both the tn_wait_flg && tn_outst() are false */
509 if (!(outstanding || tn_wait_flg)) /* If no need to wait */
510 return(1); /* Don't. */
511
512 if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
513
514 #ifdef CKSPINNER
515 if (!sstelnet && !quiet)
516 prtwait(0);
517 #endif /* CKSPINNER */
518
519 /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
520 do {
521 #ifdef NTSIG
522 ck_ih();
523 #endif /* NTSIG */
524 ch = ttinc(1);
525 if (ch == -1) { /* Timed out */
526 if (!sstelnet && !quiet) { /* Let user know... */
527 #ifdef CKSPINNER
528 printf("\b");
529 prtwait(gtimer());
530 #else
531 if (nflag == 0) {
532 printf(" Negotiations.");
533 nflag++;
534 }
535 if (nflag > 0) {
536 printf(".");
537 nflag++;
538 fflush(stdout);
539 }
540 #endif /* CKSPINNER */
541 }
542 } else if (ch < -1) {
543 printf("\r\n?Connection closed by peer.\r\n");
544 if (tn_deb || debses) tn_debug("<connection closed by peer>");
545 return(-1);
546 } else
547 switch (ch) {
548 case IAC:
549 #ifdef CKSPINNER
550 if (!sstelnet && !quiet)
551 printf("\b");
552 #endif /* CKSPINNER */
553 ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
554 #ifdef CKSPINNER
555 if (!sstelnet && !quiet) {
556 prtwait(gtimer());
557 }
558 #endif /* CKSPINNER */
559 debug(F101,"tn_wait tn_doop","",ch);
560 switch (ch) {
561 case 1:
562 duplex = 1; /* Turn on echoing */
563 if (inserver)
564 ckxech = 1;
565 break;
566 case 2:
567 duplex = 0; /* Turn off echoing */
568 if (inserver)
569 ckxech = 0;
570 break;
571 case 3:
572 tn_wait_buf[tn_wait_idx++] = IAC;
573 break;
574 case 4: /* IKS event */
575 case 6: /* Logout */
576 break;
577 case -1:
578 if (!quiet)
579 printf("?Telnet Option negotiation error.\n");
580 if (tn_deb || debses)
581 tn_debug("<Telnet Option negotiation error>");
582 return(-1);
583 case -2:
584 printf("?Connection closed by peer.\n");
585 if (tn_deb || debses) tn_debug("<Connection closed by peer>");
586 ttclos(0);
587 return(-2);
588 default:
589 if (ch < 0) {
590 if (tn_deb || debses) tn_debug("<Unknown connection error>");
591 return(ch);
592 }
593 } /* switch */
594 break;
595 default:
596 #ifdef CKSPINNER
597 if (!sstelnet && !quiet) {
598 printf("\b");
599 prtwait(gtimer());
600 }
601 #endif /* CKSPINNER */
602 tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
603 } /* switch */
604
605 outstanding = tn_outst(0);
606
607 if ( outstanding && ch != IAC ) {
608 int timer = gtimer();
609 if ( timer > tn_wait_tmo ) {
610 if (!sstelnet) {
611 printf(
612 "\r\n?Telnet Protocol Timeout - connection closed\r\n");
613 if (tn_deb || debses)
614 tn_debug(
615 "<telnet protocol timeout - connection closed>");
616 tn_outst(1);
617 }
618 /* if we do not close the connection, then we will block */
619 /* the next time we hit a wait. and if we don't we will */
620 /* do the wrong thing if the host sends 0xFF and does */
621 /* not intend it to be an IAC. */
622 ttclos(0);
623 whyclosed = WC_TELOPT;
624 return(-1);
625 }
626 #ifndef NOHINTS
627 else if ( hints && timer > 30 && nohintgiven && !inserver ) {
628 #ifdef CKSPINNER
629 printf("\b");
630 #else /* CKSPINNER */
631 printf("\r\n");
632 #endif /* CKSPINNER */
633 printf("*************************\r\n");
634 printf("The Telnet %s is not sending required responses.\r\n\r\n",
635 sstelnet?"client":"server");
636 tn_outst(1);
637 printf("\nYou can continue to wait or you can cancel with Ctrl-C.\r\n");
638 printf("In case the Telnet server never responds as required,\r\n");
639 printf("you can try connecting to this host with TELNET /NOWAIT.\r\n");
640 printf("Use SET HINTS OFF to suppress further hints.\r\n");
641 printf("*************************\r\n");
642 nohintgiven = 0;
643 }
644 #endif /* NOHINTS */
645 }
646
647 #ifdef TN_COMPORT
648 /* Must disable carrier detect check if we are using Telnet Comport */
649 savcarr = ttcarr;
650 ttscarr(CAR_OFF);
651 count = ttchk();
652 ttscarr(savcarr);
653 #else /* TN_COMPORT */
654 count = ttchk();
655 #endif /* TN_COMPORT */
656 } while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
657 (outstanding && count >= 0));
658
659 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
660 if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
661 return(0);
662 }
663
664 if (!sstelnet && !quiet) {
665 #ifdef CKSPINNER
666 printf("\b \b");
667 #else
668 if (nflag > 0) {
669 printf(" (OK)\n");
670 nflag = -1;
671 }
672 #endif /* CKSPINNER */
673 }
674 if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
675 return(0);
676 }
677
678 /* Push data from the Telnet Wait Buffer into the I/O Queue */
679 /* Return 1 on success */
680
681 int
tn_push()682 tn_push() {
683 #ifdef NETLEBUF
684 extern int tt_push_inited;
685 #endif /* NETLEBUF */
686 /* if (!IS_TELNET()) return(1); */
687
688 if (tn_wait_idx) {
689 ckhexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
690 #ifdef NETLEBUF
691 if (!tt_push_inited) /* Local handling */
692 le_init();
693 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
694 #else /* External handling... */
695 #ifdef OS2 /* K95 has its own way */
696 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
697 #else
698 #ifdef TTLEBUF /* UNIX, etc */
699 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
700 #else
701 /*
702 If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
703 the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
704 places in your ck?tio.c module.
705 */
706 printf("tn_push called but not implemented - data lost.\n");
707 #endif /* TTLEBUF */
708 #endif /* OS2 */
709 #endif /* NETLEBUF */
710 tn_wait_idx = 0;
711 }
712 tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
713 return(1);
714 }
715
716 /* T N _ S O P T */
717 /*
718 Sends a telnet option, avoids loops.
719 Returns 1 if command was sent, 0 if not, -1 on error.
720 */
721 int
tn_sopt(cmd,opt)722 tn_sopt(cmd,opt) int cmd, opt; { /* TELNET SEND OPTION */
723 CHAR buf[5];
724 char msg[128];
725 int rc;
726 if (ttnet != NET_TCPB) return(-1); /* Must be TCP/IP */
727 if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
728 if (!TELCMD_OK(cmd)) return(-1);
729 if (TELOPT_OK(opt)) {
730 if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
731 if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
732 if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
733 if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
734 }
735 #ifdef CK_SSL
736 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
737 return(0);
738 }
739 #endif /* CK_SSL */
740
741 if (cmd == DO && opt == TELOPT_AUTHENTICATION)
742 buf[0] = 0;
743
744 if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about */
745 int index = TELOPT_INDEX(opt); /* preventing infinite loops */
746 int m = cmd - WILL;
747
748 if (tncnts[index][m] > MAXTNCNT) {
749 #ifdef DEBUG
750 if (tn_deb || debses || deblog) {
751 ckmakmsg(msg,sizeof(msg),
752 "TELNET negotiation loop ",
753 TELCMD(cmd), " ",
754 TELOPT(opt));
755 debug(F101,msg,"",opt);
756 if (tn_deb || debses) tn_debug(msg);
757 }
758 #endif /* DEBUG */
759 return(0);
760 }
761 tncnts[index][m]++;
762 tncnts[index][tnopps[m]] = 0;
763 }
764 buf[0] = (CHAR) IAC;
765 buf[1] = (CHAR) (cmd & 0xff);
766 buf[2] = (CHAR) (opt & 0xff);
767 buf[3] = (CHAR) 0;
768 #ifdef DEBUG
769 if ((tn_deb || debses || deblog) && cmd != SB)
770 ckmakmsg(msg,sizeof(msg),"TELNET SENT ",TELCMD(cmd)," ",
771 TELOPT(opt));
772 #endif /* DEBUG */
773 #ifdef OS2
774 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
775 #endif
776 debug(F101,msg,"",opt);
777 if ((tn_deb || debses) && cmd != SB)
778 tn_debug(msg);
779 rc = (ttol(buf,3) < 3);
780 #ifdef OS2
781 ReleaseTelnetMutex();
782 #endif
783 if (rc)
784 return(-1);
785
786
787 if (TELOPT_OK(opt)) {
788 if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
789 TELOPT_UNANSWERED_DO(opt) = 0;
790 if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
791 TELOPT_UNANSWERED_WILL(opt) = 0;
792 if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
793 TELOPT_UNANSWERED_DONT(opt) = 0;
794 if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
795 TELOPT_UNANSWERED_WONT(opt) = 0;
796 }
797 return(1);
798 }
799
800 /* Send a telnet sub-option */
801 /* Returns 1 if command was sent, 0 if not, -1 on error */
802
803 int
tn_ssbopt(opt,sub,data,len)804 tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
805 CHAR buf[256];
806 int n,m,rc;
807
808 if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
809 if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
810 if (!TELOPT_OK(opt)) return(-1);
811 if (len < 0 || len > 250) {
812 debug(F111,"Unable to Send TELNET SB - data too long","len",len);
813 return(-1); /* Data too long */
814 }
815 #ifdef CK_SSL
816 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
817 if (ttchk() < 0)
818 return(-1);
819 else
820 return(1);
821 }
822 #endif /* CK_SSL */
823
824 if (!data) len = 0;
825
826 buf[0] = (CHAR) IAC;
827 buf[1] = (CHAR) (SB & 0xff);
828 buf[2] = (CHAR) (opt & 0xff);
829 buf[3] = (CHAR) (sub & 0xff);
830 if (data && len > 0) {
831 memcpy(&buf[4],data,len);
832 }
833 buf[4+len] = (CHAR) IAC;
834 buf[5+len] = (CHAR) SE;
835
836 #ifdef DEBUG
837 if (tn_deb || debses || deblog) {
838 if (opt == TELOPT_START_TLS && sub == 1)
839 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
840 TELOPT(opt)," FOLLOWS IAC SE",NULL);
841 else if (opt == TELOPT_TTYPE && sub == 1)
842 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ", TELOPT(opt),
843 " SEND IAC SE",NULL);
844 else if (opt == TELOPT_TTYPE && sub == 0)
845 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",TELOPT(opt)," IS ",
846 (char *)data," IAC SE",NULL,NULL,NULL,NULL,NULL,NULL,NULL);
847 else if (opt == TELOPT_NEWENVIRON) {
848 int i, quote;
849 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
850 TELOPT(TELOPT_NEWENVIRON)," ",
851 sub == TELQUAL_SEND ? "SEND" :
852 sub == TELQUAL_IS ? "IS" :
853 sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
854 for (i = 0, quote = 0; i < len; i++) {
855 if (quote) {
856 sprintf(hexbuf,"%02x",data[i]); /* safe but ugly */
857 ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
858 quote = 0;
859 } else {
860 switch (data[i]) {
861 case TEL_ENV_USERVAR:
862 ckstrncat(tn_msg_out," USERVAR ",TN_MSG_LEN);
863 break;
864 case TEL_ENV_VAR:
865 ckstrncat(tn_msg_out," VAR ",TN_MSG_LEN);
866 break;
867 case TEL_ENV_VALUE:
868 ckstrncat(tn_msg_out," VALUE ",TN_MSG_LEN);
869 break;
870 case TEL_ENV_ESC:
871 ckstrncat(tn_msg_out," ESC ",TN_MSG_LEN);
872 quote = 1;
873 break;
874 case IAC:
875 ckstrncat(tn_msg_out," IAC ",TN_MSG_LEN);
876 break;
877 default:
878 sprintf(hexbuf,"%c",data[i]); /* safe but ugly */
879 ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
880 }
881 }
882 }
883 ckstrncat(tn_msg_out," IAC SE",TN_MSG_LEN);
884 } else {
885 sprintf(hexbuf,"%02x",sub); /* safe but ugly */
886 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
887 "TELNET SENT SB ",TELOPT(opt),
888 " ",
889 hexbuf,
890 " <data> IAC SE",
891 NULL,NULL,NULL,NULL,NULL,NULL,NULL
892 );
893 }
894 }
895 #endif /* DEBUG */
896 #ifdef OS2
897 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
898 #endif /* OS2 */
899 #ifdef DEBUG
900 debug(F101,tn_msg_out,"",opt);
901 if (tn_deb || debses)
902 tn_debug(tn_msg_out);
903 #endif /* DEBUG */
904 rc = (ttol(buf,6+len) < 6+len);
905 #ifdef OS2
906 ReleaseTelnetMutex();
907 #endif
908
909 if (rc)
910 return(-1);
911 return(1);
912 }
913
914 /*
915 tn_flui() -- Processes all waiting data for Telnet commands.
916 All non-Telnet data is to be stored into the Telnet Wait Buffer.
917 Returns 1 on success.
918 */
919 int
tn_flui()920 tn_flui() {
921 extern int ckxech;
922 int x = 0;
923
924 /* if (!IS_TELNET()) return(0); */
925
926 /* Wait up to 5 sec for responses to outstanding telnet negotiations */
927 while (x >= 0 && ttchk() > 0 && tn_wait_idx < TN_WAIT_BUF_SZ) {
928 x = ttinc(1);
929 switch (x) {
930 case IAC:
931 x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
932 debug(F101,"tn_flui tn_doop","",x);
933 switch (x) {
934 case 1: /* Turn on echoing */
935 duplex = 1;
936 if (inserver)
937 ckxech = 1;
938 break;
939 case 2: /* Turn off echoing */
940 duplex = 0;
941 if (inserver)
942 ckxech = 0;
943 break;
944 case 3:
945 tn_wait_buf[tn_wait_idx++] = IAC;
946 break;
947 case 4: /* IKS event */
948 case 6: /* Logout */
949 break;
950 }
951 break;
952 default:
953 if (x >= 0)
954 tn_wait_buf[tn_wait_idx++] = x;
955 }
956 }
957 return(1);
958 }
959
960 unsigned char *
tn_get_display()961 tn_get_display()
962 {
963 char * disp = NULL;
964 static char tmploc[256];
965
966 /* Must compute the DISPLAY string we are going to send to the host */
967 /* If one is not assigned, do not send a string unless the user has */
968 /* explicitedly requested we try to send one via X-Display Location */
969 /* But do not send a string at all if FORWARD_X is in use. */
970
971 /* if (!IS_TELNET()) return(0); */
972
973 debug(F110,"tn_get_display() myipaddr",myipaddr,0);
974 #ifdef CK_ENVIRONMENT
975 debug(F110,"tn_get_display() tn_env_disp",tn_env_disp,0);
976 if (tn_env_disp[0]) {
977 int colon = ckindex(":",tn_env_disp,0,0,1);
978 if ( !colon ) {
979 ckmakmsg(tmploc,256,myipaddr,":",tn_env_disp,NULL);
980 disp = tmploc;
981 } else if ( ckindex("localhost:",tn_env_disp,0,0,0) ||
982 ckindex("unix:",tn_env_disp,0,0,0) ||
983 ckindex("127.0.0.1:",tn_env_disp,0,0,0) ||
984 !ckstrcmp("0:",tn_env_disp,2,1) ||
985 tn_env_disp[0] == ':' ) {
986 ckmakmsg(tmploc,256,myipaddr,":",&tn_env_disp[colon],NULL);
987 disp = tmploc;
988 } else
989 disp = tn_env_disp;
990 }
991 else
992 #endif /* CK_ENVIRONMENT */
993 if (TELOPT_ME(TELOPT_XDISPLOC) ||
994 TELOPT_U(TELOPT_FORWARD_X)) {
995 ckmakmsg(tmploc,256,myipaddr,":0.0",NULL,NULL);
996 disp = tmploc;
997 }
998 debug(F110,"tn_get_display() returns",disp,0);
999 return((CHAR *)disp);
1000 }
1001
1002 #ifdef CK_FORWARD_X
1003 static Xauth fake_xauth = {0,0,NULL,0,NULL,0,NULL,0,NULL};
1004 static Xauth *real_xauth=NULL;
1005
1006 /*
1007 * Author: Jim Fulton, MIT X Consortium
1008 *
1009 * fwdx_parse_displayname -
1010 * display a display string up into its component parts
1011 */
1012 #ifdef UNIX
1013 #define UNIX_CONNECTION "unix"
1014 #define UNIX_CONNECTION_LENGTH 4
1015 #endif
1016
1017 /*
1018 * private utility routines
1019 */
1020
1021 static int
1022 #ifdef CK_ANSIC
XmuGetHostname(char * buf,int maxlen)1023 XmuGetHostname (char *buf, int maxlen)
1024 #else
1025 XmuGetHostname (buf, maxlen)
1026 char *buf;
1027 int maxlen;
1028 #endif /* CK_ANSIC */
1029 {
1030 int len;
1031
1032 #ifdef NEED_UTSNAME
1033 /*
1034 * same host name crock as in server and xinit.
1035 */
1036 struct utsname name;
1037
1038 uname (&name);
1039 len = strlen (name.nodename);
1040 if (len >= maxlen) len = maxlen - 1;
1041 strncpy (buf, name.nodename, len);
1042 buf[len] = '\0';
1043 #else
1044 buf[0] = '\0';
1045 (void) gethostname (buf, maxlen);
1046 buf [maxlen - 1] = '\0';
1047 len = strlen(buf);
1048 #endif /* hpux */
1049 return len;
1050 }
1051
1052 static char *
1053 #ifdef CK_ANSIC
copystring(char * src,int len)1054 copystring (char *src, int len)
1055 #else
1056 copystring (src, len)
1057 char *src;
1058 int len;
1059 #endif /* CK_ANSIC */
1060 {
1061 char *cp;
1062
1063 if (!src && len != 0) return NULL;
1064 cp = malloc (len + 1);
1065 if (cp) {
1066 if (src) strncpy (cp, src, len);
1067 cp[len] = '\0';
1068 }
1069 return cp;
1070 }
1071
1072 static char *
1073 #ifdef CK_ANSIC
get_local_hostname(char * buf,int maxlen)1074 get_local_hostname (char *buf, int maxlen)
1075 #else
1076 get_local_hostname (buf, maxlen)
1077 char *buf;
1078 int maxlen;
1079 #endif
1080 {
1081 buf[0] = '\0';
1082 (void) XmuGetHostname (buf, maxlen);
1083 return (buf[0] ? buf : NULL);
1084 }
1085
1086 #ifndef UNIX
1087 static char *
copyhostname()1088 copyhostname ()
1089 {
1090 char buf[256];
1091
1092 return (get_local_hostname (buf, sizeof buf) ?
1093 copystring (buf, strlen (buf)) : NULL);
1094 }
1095 #endif
1096
1097
1098 int
1099 #ifdef CK_ANSIC
fwdx_parse_displayname(char * displayname,int * familyp,char ** hostp,int * dpynump,int * scrnump,char ** restp)1100 fwdx_parse_displayname (char *displayname, int *familyp, char **hostp,
1101 int *dpynump, int *scrnump, char **restp)
1102 #else
1103 fwdx_parse_displayname (displayname, familyp, hostp, dpynump, scrnump, restp)
1104 char *displayname;
1105 int *familyp; /* return */
1106 char **hostp; /* return */
1107 int *dpynump, *scrnump; /* return */
1108 char **restp; /* return */
1109 #endif /* CK_ANSIC */
1110 {
1111 char *ptr; /* work variables */
1112 int len; /* work variable */
1113 int family = -1; /* value to be returned */
1114 char *host = NULL; /* must free if set and error return */
1115 int dpynum = -1; /* value to be returned */
1116 int scrnum = 0; /* value to be returned */
1117 char *rest = NULL; /* must free if set and error return */
1118 int dnet = 0; /* if 1 then using DECnet */
1119
1120 /* check the name */
1121 if (!displayname || !displayname[0])
1122 return 0;
1123 /* must have at least :number */
1124 ptr = (char *)strchr(displayname, ':');
1125 if (!ptr || !ptr[1]) return 0;
1126 if (ptr[1] == ':') {
1127 if (ptr[2] == '\0') return 0;
1128 dnet = 1;
1129 }
1130
1131 /*
1132 * get the host string; if none is given, use the most effiecient path
1133 */
1134
1135 len = (ptr - displayname); /* length of host name */
1136 if (len == 0) { /* choose most efficient path */
1137 #ifdef UNIX
1138 host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
1139 family = FamilyLocal;
1140 #else
1141 if (dnet) {
1142 host = copystring ("0", 1);
1143 family = FamilyDECnet;
1144 } else {
1145 host = copyhostname ();
1146 family = FamilyInternet;
1147 }
1148 #endif
1149 } else {
1150 host = copystring (displayname, len);
1151 if (dnet) {
1152 family = dnet;
1153 } else {
1154 #ifdef UNIX
1155 if (host && strcmp (host, UNIX_CONNECTION) == 0)
1156 family = FamilyLocal;
1157 else
1158 #endif
1159 family = FamilyInternet;
1160 }
1161 }
1162
1163 if (!host) return 0;
1164
1165
1166 /*
1167 * get the display number; we know that there is something after the
1168 * colon (or colons) from above. note that host is now set and must
1169 * be freed if there is an error.
1170 */
1171
1172 if (dnet) ptr++; /* skip the extra DECnet colon */
1173 ptr++; /* move to start of display num */
1174 {
1175 register char *cp;
1176
1177 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
1178 len = (cp - ptr);
1179 /* check present and valid follow */
1180 if (len == 0 || (*cp && *cp != '.')) {
1181 free (host);
1182 return 0;
1183 }
1184
1185 dpynum = atoi (ptr); /* it will handle num. as well */
1186 ptr = cp;
1187 }
1188
1189 /*
1190 * now get screen number if given; ptr may point to nul at this point
1191 */
1192 if (ptr[0] == '.') {
1193 register char *cp;
1194
1195 ptr++;
1196 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
1197 len = (cp - ptr);
1198 if (len == 0 || (*cp && *cp != '.')) { /* all prop name */
1199 free (host);
1200 return 0;
1201 }
1202
1203 scrnum = atoi (ptr); /* it will handle num. as well */
1204 ptr = cp;
1205 }
1206
1207 /*
1208 * and finally, get any additional stuff that might be following the
1209 * the screen number; ptr must point to a period if there is anything
1210 */
1211
1212 if (ptr[0] == '.') {
1213 ptr++;
1214 len = strlen (ptr);
1215 if (len > 0) {
1216 rest = copystring (ptr, len);
1217 if (!rest) {
1218 free (host);
1219 return 1;
1220 }
1221 }
1222 }
1223
1224 /*
1225 * and we are done!
1226 */
1227
1228 if ( familyp )
1229 *familyp = family;
1230 if ( hostp )
1231 *hostp = host;
1232 else
1233 free(host);
1234 if ( dpynump )
1235 *dpynump = dpynum;
1236 if ( scrnump )
1237 *scrnump = scrnum;
1238 if ( restp )
1239 *restp = rest;
1240 else
1241 free(rest);
1242 return 1;
1243 }
1244
1245
1246 int
1247 #ifdef CK_ANSIC
fwdx_tn_sb(unsigned char * sb,int n)1248 fwdx_tn_sb( unsigned char * sb, int n )
1249 #else
1250 fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
1251 #endif /* CK_ANSIC */
1252 {
1253 unsigned short hchannel, nchannel;
1254 unsigned char * p;
1255 int i;
1256 int rc = -1;
1257
1258 /* check to ensure we have negotiated Forward X */
1259 if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
1260 !sstelnet && !TELOPT_U(TELOPT_FORWARD_X) ) {
1261 debug(F100,"fwdx_tn_sb() not negotiated","",0);
1262 return(0);
1263 }
1264
1265 #ifdef CK_SSL
1266 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1267 return(0);
1268 }
1269 #endif /* CK_SSL */
1270
1271 switch (sb[0]) {
1272 case FWDX_SCREEN:
1273 if (sstelnet && n == 4)
1274 rc = fwdx_create_listen_socket(sb[1]);
1275 break;
1276 case FWDX_OPEN:
1277 if ( !sstelnet && n >= 5 ) {
1278 p = (unsigned char *) &nchannel;
1279 i = 1;
1280 /* IAC quoting has been stripped in tn_sb() */
1281 p[0] = sb[i++];
1282 p[1] = sb[i++];
1283 hchannel = ntohs(nchannel);
1284 rc = fwdx_open_client_channel(hchannel);
1285 if ( rc < 0 ) {
1286 /* Failed; Send CLOSE channel */
1287 fwdx_send_close(hchannel);
1288 rc = 0; /* Do not consider this to be a telnet error */
1289 }
1290 #ifdef NT
1291 if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
1292 ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
1293 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
1294 }
1295 #endif /* NT */
1296 }
1297 break;
1298 case FWDX_CLOSE:
1299 p = (unsigned char *) &nchannel;
1300 i = 1;
1301 /* IAC quoting has been stripped in tn_sb() */
1302 p[0] = sb[i++];
1303 p[1] = sb[i++];
1304 hchannel = ntohs(nchannel);
1305 fwdx_close_channel(hchannel);
1306 rc = 0; /* no errors when closing */
1307 break;
1308 case FWDX_DATA:
1309 p = (unsigned char *) &nchannel;
1310 i = 1;
1311 /* IAC quoting has been stripped in tn_sb() */
1312 p[0] = sb[i++];
1313 p[1] = sb[i++];
1314 hchannel = ntohs(nchannel);
1315 rc = fwdx_send_xauth_to_xserver(hchannel,(CHAR *)&sb[3],n-5);
1316 if ( rc >= 0 && n-5-rc > 0) {
1317 rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3+rc],n-5-rc);
1318 if ( rc < 0 ) {
1319 /* Failed; Send CLOSE channel */
1320 rc = fwdx_send_close(hchannel);
1321 }
1322 }
1323 break;
1324 case FWDX_OPTIONS:
1325 if ( sstelnet ) {
1326 #ifndef FWDX_SERVER
1327 rc = 0;
1328 #else
1329 rc = fwdx_server_accept_options((char*)&sb[2],n-3);
1330 #endif
1331 } else {
1332 rc = fwdx_client_reply_options((char *)&sb[2],n-3);
1333 if ( rc >= 0 ) {
1334 rc = tn_sndfwdx();
1335 }
1336 }
1337 break;
1338 case FWDX_OPT_DATA:
1339 switch ( sb[1] ) {
1340 default:
1341 rc = 0; /* we don't recognize, not an error */
1342 }
1343 break;
1344
1345 case FWDX_XOFF:
1346 case FWDX_XON:
1347 if ( !sstelnet ) {
1348 p = (unsigned char *) &nchannel;
1349 i = 1;
1350 /* IAC quoting has been stripped in tn_sb() */
1351 p[0] = sb[i++];
1352 p[1] = sb[i++];
1353 hchannel = ntohs(nchannel);
1354 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[hchannel].suspend =
1355 (sb[0] == FWDX_XOFF);
1356 rc = 0;
1357 }
1358 break;
1359 }
1360 return(rc < 0 ? -1 : 0);
1361 }
1362
1363 int
1364 #ifdef CK_ANSIC
fwdx_send_xauth_to_xserver(int channel,unsigned char * data,int len)1365 fwdx_send_xauth_to_xserver(int channel, unsigned char * data, int len)
1366 #else
1367 fwdx_send_xauth_to_xserver(channel, data, len)
1368 int channel; unsigned char * data; int len;
1369 #endif /* CK_ANSIC */
1370 {
1371 int name_len, data_len, i;
1372
1373 for (i = 0; i < MAXFWDX ; i++) {
1374 if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
1375 break;
1376 }
1377 if ( i == MAXFWDX )
1378 goto auth_err;
1379
1380 if (!TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth)
1381 return(0);
1382
1383 if (len < 12)
1384 goto auth_err;
1385
1386 /* Parse the lengths of variable-length fields. */
1387 if (data[0] == 0x42) { /* byte order MSB first. */
1388 /* Xauth packets appear to always have this format */
1389 if ( data[1] != 0x00 ||
1390 data[2] != 0x00 ||
1391 data[3] != 0x0B ||
1392 data[4] != 0x00 ||
1393 data[5] != 0x00 )
1394 goto auth_err;
1395
1396 name_len = (data[6] << 8) + data[7];
1397 data_len = (data[8] << 8) + data[9];
1398 } else if (data[0] == 0x6c) { /* Byte order LSB first. */
1399 /* Xauth packets appear to always have this format */
1400 if ( data[1] != 0x00 ||
1401 data[2] != 0x0B ||
1402 data[3] != 0x00 ||
1403 data[4] != 0x00 ||
1404 data[5] != 0x00 )
1405 goto auth_err;
1406
1407 name_len = data[6] + (data[7] << 8);
1408 data_len = data[8] + (data[9] << 8);
1409 } else {
1410 /* bad byte order byte */
1411 goto auth_err;
1412 }
1413
1414 /* Check if the whole packet is in buffer. */
1415 if (len < 12 + ((name_len + 3) & ~3) + ((data_len + 3) & ~3))
1416 goto auth_err;
1417 /* If the Telnet Server allows a real Xauth message to be sent */
1418 /* Then let the message be processed by the Xserver. */
1419 if (name_len + data_len > 0) {
1420 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1421 return(0);
1422 }
1423 else
1424 /* If an empty Xauth message was received. We are going to */
1425 /* send our own Xauth message using the real Xauth data. And */
1426 /* then send any other data in the buffer. */
1427 {
1428 int c, err, dpynum, scrnum, family, sb_len;
1429 char *display, *host = NULL, *rest = NULL;
1430 unsigned char *sb, *p;
1431
1432 /* parse the local DISPLAY env var */
1433 display = getenv("DISPLAY");
1434 if ( !display )
1435 display = "127.0.0.1:0.0";
1436
1437 if (fwdx_parse_displayname(display,
1438 &family, &host, &dpynum, &scrnum, &rest)) {
1439 char * disp_no = ckitoa(dpynum); /* should be unsigned */
1440 if (family == FamilyLocal) {
1441 /* call with address = "<local host name>" */
1442 char address[300] = "localhost";
1443 gethostname(address, sizeof(address) - 1);
1444 real_xauth = XauGetAuthByAddr(family,
1445 strlen(address),
1446 address,
1447 strlen(disp_no),
1448 disp_no, 0, NULL);
1449 }
1450 else if (family == FamilyInternet) {
1451 /* call with address = 4 bytes numeric ip addr (MSB) */
1452 struct hostent *hi;
1453 if (hi = gethostbyname(host))
1454 real_xauth = XauGetAuthByAddr(family, 4,
1455 hi->h_addr, strlen(disp_no),
1456 disp_no, 0, NULL);
1457 }
1458 }
1459 if (host) free(host);
1460 if (rest) free(rest);
1461 if (!real_xauth) {
1462 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1463 return(0);
1464 }
1465
1466 if (!strncmp(real_xauth->name,
1467 "MIT-MAGIC-COOKIE-1",
1468 real_xauth->name_length)) {
1469 char msg[64];
1470
1471 name_len = real_xauth->name_length;
1472 data_len = 16;
1473
1474 if ( data[0] == 0x42 ) {
1475 msg[0] = 0x42; /* MSB order */
1476 msg[1] = msg[2] = 0;
1477 msg[3] = 0x0B;
1478 msg[4] = msg[5] = 0;
1479 msg[6] = (name_len >> 8);
1480 msg[7] = (name_len & 0xFF);
1481 msg[8] = (data_len >> 8);
1482 msg[9] = (data_len & 0xFF);
1483 } else {
1484 msg[0] = 0x6c; /* LSB order */
1485 msg[1] = 0;
1486 msg[2] = 0x0B;
1487 msg[3] = msg[4] = msg[5] = 0;
1488 msg[6] = (name_len & 0xFF);
1489 msg[7] = (name_len >> 8);
1490 msg[8] = (data_len & 0xFF);
1491 msg[9] = (data_len >> 8);
1492 }
1493 msg[10] = msg[11] = 0;
1494 memcpy(&msg[12],real_xauth->name,18);
1495 msg[30] = msg[31] = 0;
1496 memcpy(&msg[32],real_xauth->data,16);
1497
1498 if (fwdx_write_data_to_channel(channel,(char *)msg,48) < 0) {
1499 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1500 return(-1);
1501 } else {
1502 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1503 return(12);
1504 }
1505 } else {
1506 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1507 return(0); /* we do not know how to handle this type yet */
1508 }
1509 }
1510
1511 auth_err:
1512 debug(F100,"fwdx_send_xauth_to_xserver error","",0);
1513 return(-1);
1514 }
1515
1516
1517 #ifdef COMMENT
1518 int
1519 #ifdef CK_ANSIC
fwdx_authorize_channel(int channel,unsigned char * data,int len)1520 fwdx_authorize_channel(int channel, unsigned char * data, int len)
1521 #else
1522 fwdx_authorize_channel(channel, data, len)
1523 int channel; unsigned char * data; int len;
1524 #endif /* CK_ANSIC */
1525 {
1526 /* XXX maybe we should have some retry handling if not the whole first
1527 * authorization packet arrives complete
1528 */
1529 if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized ) {
1530 int name_len, data_len;
1531
1532 if (len < 12)
1533 goto auth_err;
1534
1535 /* Parse the lengths of variable-length fields. */
1536 if (data[0] == 0x42) { /* byte order MSB first. */
1537 /* Xauth packets appear to always have this format */
1538 if ( data[1] != 0x00 ||
1539 data[2] != 0x00 ||
1540 data[3] != 0x0B ||
1541 data[4] != 0x00 ||
1542 data[5] != 0x00 )
1543 goto auth_err;
1544
1545 name_len = (data[6] << 8) + data[7];
1546 data_len = (data[8] << 8) + data[9];
1547 } else if (data[0] == 0x6c) { /* Byte order LSB first. */
1548 /* Xauth packets appear to always have this format */
1549 if ( data[1] != 0x00 ||
1550 data[2] != 0x0B ||
1551 data[3] != 0x00 ||
1552 data[4] != 0x00 ||
1553 data[5] != 0x00 )
1554 goto auth_err;
1555
1556 name_len = data[6] + (data[7] << 8);
1557 data_len = data[8] + (data[9] << 8);
1558 } else {
1559 /* bad byte order byte */
1560 goto auth_err;
1561 }
1562 /* Check if authentication protocol matches. */
1563 if (name_len != fake_xauth.name_length ||
1564 memcmp(data + 12, fake_xauth.name, name_len) != 0) {
1565 /* connection uses different authentication protocol */
1566 goto auth_err;
1567 }
1568 /* Check if authentication data matches our fake data. */
1569 if (data_len != fake_xauth.data_length ||
1570 memcmp(data + 12 + ((name_len + 3) & ~3),
1571 fake_xauth.data, fake_xauth.data_length) != 0) {
1572 /* auth data does not match fake data */
1573 goto auth_err;
1574 }
1575 /* substitute the fake data with real data if we have any */
1576 if (real_xauth && real_xauth->data)
1577 memcpy(data + 12 + ((name_len + 3) & ~3),
1578 real_xauth->data, data_len);
1579
1580 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized = 1;
1581 }
1582 return(0);
1583 auth_err:
1584 return(-1);
1585 }
1586 #endif /* COMMENT */
1587
1588 int
1589 #ifdef CK_ANSIC
fwdx_send_close(int channel)1590 fwdx_send_close(int channel)
1591 #else
1592 fwdx_send_close(channel) int channel;
1593 #endif /* CK_ANSIC */
1594 {
1595 unsigned short nchannel;
1596 int i,rc;
1597 CHAR * p;
1598
1599 #ifdef CK_SSL
1600 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1601 return(0);
1602 }
1603 #endif /* CK_SSL */
1604
1605 nchannel = htons(channel);
1606 p = (unsigned char *) &nchannel;
1607
1608 i = 0;
1609 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1610 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1611 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1612 sb_out[i++] = FWDX_CLOSE; /* Open */
1613 sb_out[i++] = p[0]; /* First Byte of Channel */
1614 if ( p[0] == IAC )
1615 sb_out[i++] = IAC;
1616 sb_out[i++] = p[1]; /* Second Byte of Channel */
1617 if ( p[1] == IAC )
1618 sb_out[i++] = IAC;
1619 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1620 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1621 #ifdef DEBUG
1622 if (deblog || tn_deb || debses) {
1623 ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1624 TELOPT(TELOPT_FORWARD_X),
1625 " CLOSE CHANNEL=",ckitoa(channel)," IAC SE",
1626 NULL,NULL,NULL,NULL,NULL,NULL,NULL
1627 );
1628 }
1629 #endif /* DEBUG */
1630 #ifdef OS2
1631 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1632 #endif
1633 #ifdef DEBUG
1634 debug(F100,(char *)fwdx_msg_out,"",0);
1635 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1636 #endif /* DEBUG */
1637 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1638 #ifdef OS2
1639 ReleaseTelnetMutex();
1640 #endif
1641 if (rc)
1642 return(-1);
1643 return(0);
1644 }
1645
1646 int
1647 #ifdef CK_ANSIC
fwdx_send_open(int channel)1648 fwdx_send_open(int channel)
1649 #else /* CK_ANSIC */
1650 fwdx_send_open(channel) int channel;
1651 #endif /* CK_ANSIC */
1652 {
1653 unsigned short nchannel;
1654 int i, rc;
1655 CHAR * p;
1656
1657 #ifdef CK_SSL
1658 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1659 return(0);
1660 }
1661 #endif /* CK_SSL */
1662
1663 nchannel = htons(channel);
1664 p = (unsigned char *) &nchannel;
1665
1666 i = 0;
1667 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1668 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1669 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1670 sb_out[i++] = FWDX_OPEN; /* Open */
1671 sb_out[i++] = p[0]; /* First Byte of Channel */
1672 if ( p[0] == IAC )
1673 sb_out[i++] = IAC;
1674 sb_out[i++] = p[1]; /* Second Byte of Channel */
1675 if ( p[1] == IAC )
1676 sb_out[i++] = IAC;
1677 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1678 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1679 #ifdef DEBUG
1680 if (deblog || tn_deb || debses) {
1681 ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1682 TELOPT(TELOPT_FORWARD_X),
1683 " OPEN CHANNEL=",ckitoa(channel)," IAC SE",
1684 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
1685 }
1686 #endif /* DEBUG */
1687 #ifdef OS2
1688 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1689 #endif
1690 #ifdef DEBUG
1691 debug(F100,(char *)fwdx_msg_out,"",0);
1692 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1693 #endif /* DEBUG */
1694 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1695 #ifdef OS2
1696 ReleaseTelnetMutex();
1697 #endif
1698 if (rc)
1699 return(-1);
1700 return(0);
1701 }
1702
1703 int
1704 #ifdef CK_ANSIC
fwdx_client_reply_options(char * opts,int n)1705 fwdx_client_reply_options(char *opts, int n)
1706 #else
1707 fwdx_client_reply_options(opts, n) char *opts; int n;
1708 #endif /* CK_ANSIC */
1709 {
1710 int i,j,rc;
1711
1712 #ifdef CK_SSL
1713 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1714 return(0);
1715 }
1716 #endif /* CK_SSL */
1717
1718 i = 0;
1719 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1720 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1721 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1722 sb_out[i++] = FWDX_OPTIONS; /* Options */
1723
1724 /* Look for the options we recognize and will support for this session */
1725 /* and reply with their bytes set */
1726 for (j=0; j<n; j++,i++) {
1727 sb_out[i] = FWDX_OPT_NONE; /* Add zero byte - no options */
1728 #ifdef COMMENT
1729 /* If we had any options to support, this is how we would do it */
1730 if ( j == 0 ) {
1731 if (opts[j] & FWDX_OPT_XXXX) {
1732 /* set flag to remember option is in use */
1733 flag = 1;
1734 sb_out[i] |= FWDX_OPT_XXXX;
1735 }
1736 }
1737 #endif /* COMMENT */
1738 }
1739 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1740 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1741 #ifdef DEBUG
1742 if (deblog || tn_deb || debses) {
1743 ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1744 TELOPT(TELOPT_FORWARD_X),
1745 " OPTIONS ",ckctox(sb_out[4],1)," IAC SE",
1746 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
1747 }
1748 #endif /* DEBUG */
1749 #ifdef OS2
1750 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1751 #endif
1752 #ifdef DEBUG
1753 debug(F100,(char *)fwdx_msg_out,"",0);
1754 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1755 #endif /* DEBUG */
1756 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1757 #ifdef OS2
1758 ReleaseTelnetMutex();
1759 #endif
1760 if (rc)
1761 return(-1);
1762 return(0);
1763 }
1764
1765
1766 int
fwdx_send_options()1767 fwdx_send_options() {
1768 int i, rc;
1769
1770 #ifdef CK_SSL
1771 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1772 return(0);
1773 }
1774 #endif /* CK_SSL */
1775
1776 i = 0;
1777 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1778 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1779 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1780 sb_out[i++] = FWDX_OPTIONS; /* Options */
1781 sb_out[i] = FWDX_OPT_NONE;
1782 /* activate options here */
1783 i++;
1784 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1785 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1786
1787 #ifdef DEBUG
1788 if (deblog || tn_deb || debses) {
1789 ckmakmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1790 TELOPT(TELOPT_FORWARD_X),
1791 " OPTIONS 00 IAC SE",NULL);
1792 }
1793 #endif /* DEBUG */
1794 #ifdef OS2
1795 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1796 #endif
1797 #ifdef DEBUG
1798 debug(F100,(char *)fwdx_msg_out,"",0);
1799 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1800 #endif /* DEBUG */
1801 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1802 #ifdef OS2
1803 ReleaseTelnetMutex();
1804 #endif
1805 if (rc)
1806 return(-1);
1807 return(0);
1808 }
1809
1810 int
1811 #ifdef CK_ANSIC
fwdx_send_data_from_channel(int channel,char * data,int len)1812 fwdx_send_data_from_channel(int channel, char * data, int len)
1813 #else
1814 fwdx_send_data_from_channel(channel, data, len)
1815 int channel; char * data; int len;
1816 #endif
1817 {
1818 unsigned short nchannel;
1819 /* static */ CHAR sb_priv[2048];
1820 CHAR * p;
1821 int i, j, j_sav, rc;
1822 unsigned int tmp;
1823
1824 debug(F111,"fwdx_send_data_from_channel()","channel",channel);
1825
1826 #ifdef CK_SSL
1827 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1828 return(0);
1829 }
1830 #endif /* CK_SSL */
1831
1832 nchannel = htons(channel);
1833 p = (unsigned char *) &nchannel;
1834
1835 j = 0;
1836 sb_priv[j++] = (CHAR) IAC; /* I Am a Command */
1837 sb_priv[j++] = (CHAR) SB; /* Subnegotiation */
1838 sb_priv[j++] = TELOPT_FORWARD_X; /* Forward X */
1839 sb_priv[j++] = FWDX_DATA; /* Data */
1840 sb_priv[j++] = p[0]; /* First Byte of Channel */
1841 if ( p[0] == IAC )
1842 sb_priv[j++] = IAC;
1843 sb_priv[j++] = p[1]; /* Second Byte of Channel */
1844 if ( p[1] == IAC )
1845 sb_priv[j++] = IAC;
1846 j_sav = j;
1847
1848 for (i = 0; i < len; i++) {
1849 tmp = (unsigned int)data[i];
1850 if ( tmp == IAC ) {
1851 sb_priv[j++] = IAC;
1852 sb_priv[j++] = IAC;
1853 } else {
1854 sb_priv[j++] = tmp;
1855 }
1856 if ( j >= 2045 && (i < len-1) ) {
1857 sb_priv[j++] = (CHAR) IAC; /* End of Subnegotiation */
1858 sb_priv[j++] = (CHAR) SE; /* marked by IAC SE */
1859
1860 #ifdef DEBUG
1861 if (deblog || tn_deb || debses) {
1862 ckmakxmsg( (char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1863 TELOPT(TELOPT_FORWARD_X),
1864 " DATA CHANNEL=",ckitoa(channel)," ",
1865 NULL,NULL,NULL,NULL,NULL,NULL,NULL );
1866 tn_hex((CHAR *)fwdx_msg_out,
1867 TN_MSG_LEN,&sb_priv[j_sav],j-(j_sav+2));
1868 ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
1869 }
1870 #endif /* DEBUG */
1871 #ifdef OS2
1872 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1873 #endif
1874 #ifdef DEBUG
1875 debug(F100,(char *)fwdx_msg_out,"",0);
1876 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1877 #endif /* DEBUG */
1878 rc = (ttol(sb_priv,j) < 0); /* Send it. */
1879 #ifdef OS2
1880 ReleaseTelnetMutex();
1881 #endif
1882 if (rc) {
1883 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
1884 return(-1);
1885 }
1886
1887 j = 0;
1888 sb_priv[j++] = (CHAR) IAC; /* I Am a Command */
1889 sb_priv[j++] = (CHAR) SB; /* Subnegotiation */
1890 sb_priv[j++] = TELOPT_FORWARD_X; /* Forward X */
1891 sb_priv[j++] = FWDX_DATA; /* Data */
1892 sb_priv[j++] = p[0]; /* First Byte of Channel */
1893 if ( p[0] == IAC )
1894 sb_priv[j++] = IAC;
1895 sb_priv[j++] = p[1]; /* Second Byte of Channel */
1896 if ( p[1] == IAC )
1897 sb_priv[j++] = IAC;
1898 }
1899 }
1900
1901 sb_priv[j++] = (CHAR) IAC; /* End of Subnegotiation */
1902 sb_priv[j++] = (CHAR) SE; /* marked by IAC SE */
1903
1904 #ifdef DEBUG
1905 if (deblog || tn_deb || debses) {
1906 ckmakxmsg( (char *)fwdx_msg_out,TN_MSG_LEN,
1907 "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
1908 " DATA ",ckctox(p[0],1)," ",ckctox(p[1],1)," ",
1909 NULL,NULL,NULL,NULL,NULL);
1910 tn_hex((CHAR *)fwdx_msg_out,TN_MSG_LEN,&sb_priv[6],j-8);
1911 ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
1912 }
1913 #endif /* DEBUG */
1914 #ifdef OS2
1915 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1916 #endif
1917 #ifdef DEBUG
1918 debug(F100,(char *)fwdx_msg_out,"",0);
1919 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1920 #endif /* DEBUG */
1921 rc = (ttol(sb_priv,j) < 0); /* Send it. */
1922 #ifdef OS2
1923 ReleaseTelnetMutex();
1924 #endif
1925 if ( rc ) {
1926 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
1927 return(-1);
1928 }
1929
1930
1931 return(0);
1932 }
1933
1934 static unsigned char *
1935 #ifdef CK_ANSIC
fwdx_add_quoted_twobyte(unsigned char * p,unsigned short twobyte)1936 fwdx_add_quoted_twobyte(unsigned char *p, unsigned short twobyte)
1937 #else
1938 fwdx_add_quoted_twobyte(p, twobyte)
1939 unsigned char *p; unsigned short twobyte;
1940 #endif /* CK_ANSIC */
1941 /* adds the IAC quoted (MSB) representation of 'channel' at buffer pointer 'p',
1942 * returning pointer to new buffer position. NO OVERFLOW CHECK!
1943 */
1944 {
1945 *p++ = (unsigned char)((twobyte >> 8) & 0xFF);
1946 if (*(p - 1) == 0xFF)
1947 *p++ = 0xFF;
1948 *p++ = (unsigned char)(twobyte & 0xFF);
1949 if (*(p - 1) == 0xFF)
1950 *p++ = 0xFF;
1951 return p;
1952 }
1953
1954 int
1955 #ifdef CK_ANSIC
fwdx_create_fake_xauth(char * name,int name_len,int data_len)1956 fwdx_create_fake_xauth(char *name, int name_len, int data_len)
1957 #else
1958 fwdx_create_fake_xauth(name, name_len, data_len)
1959 char *name; int name_len; int data_len;
1960 #endif /* CK_ANSIC */
1961 {
1962 char stackdata[256];
1963 unsigned int c, n;
1964
1965 if (!name_len || !data_len)
1966 return 1;
1967 fake_xauth.name = malloc(name_len);
1968 fake_xauth.data = malloc(data_len);
1969 if (!fake_xauth.name || !fake_xauth.data)
1970 return 2;
1971 fake_xauth.name_length = name_len;
1972 memcpy(fake_xauth.name, name, name_len);
1973 fake_xauth.data_length = data_len;
1974
1975 /* try to make a random unsigned int to feed srand() */
1976 c = time(NULL);
1977 c *= getpid();
1978 for (n = 0; n < sizeof(stackdata); n++)
1979 c += stackdata[n];
1980 srand((unsigned int)c);
1981 for (c = 0; c < data_len; c++)
1982 fake_xauth.data[c] = (unsigned char)rand();
1983 return 0;
1984 }
1985
1986 #ifdef COMMENT
1987 /* No longer used */
1988 int
fwdx_send_xauth(void)1989 fwdx_send_xauth(void)
1990 {
1991 int c, err, dpynum, family, sb_len, rc;
1992 char *display, *host = NULL;
1993 unsigned char *sb_priv, *p;
1994
1995 /* parse the local DISPLAY env var */
1996 if (!(display = tn_get_display()))
1997 return (-1);
1998 if (fwdx_parse_displayname(display, &family, &host, &dpynum, NULL, NULL)) {
1999 char * disp_no = ckitoa(dpynum);
2000 if (family == FamilyLocal) {
2001 /* call with address = "<local host name>" */
2002 char address[300] = "localhost";
2003 gethostname(address, sizeof(address) - 1);
2004 real_xauth = XauGetAuthByAddr(family,
2005 strlen(address),
2006 address,
2007 strlen(disp_no),
2008 disp_no, 0, NULL
2009 );
2010 }
2011 else if (family == FamilyInternet) {
2012 /* call with address = 4 bytes numeric ip addr (MSB) */
2013 struct hostent *hi;
2014 if (hi = gethostbyname(host))
2015 real_xauth = XauGetAuthByAddr(family, 4,
2016 hi->h_addr,
2017 strlen(disp_no),
2018 disp_no, 0, NULL
2019 );
2020 }
2021 }
2022 if (host) {
2023 free(host);
2024 host = NULL;
2025 }
2026 if (real_xauth)
2027 err = fwdx_create_fake_xauth(real_xauth->name,
2028 real_xauth->name_length,
2029 real_xauth->data_length
2030 );
2031 else
2032 err = fwdx_create_fake_xauth("MIT-MAGIC-COOKIE-1",
2033 strlen("MIT-MAGIC-COOKIE-1"), 16);
2034 if (err)
2035 return(-1);
2036
2037 /* allocate memory for the SB block, alloc for worst case */
2038 /* the following sprintf() calls are safe due to length checking */
2039 /* buffer is twice as big as the input just in case every byte was IAC */
2040 sb_len = 5 + 2 + 2 + fake_xauth.name_length + fake_xauth.data_length + 2;
2041 if (!(sb_priv = malloc(2 * sb_len)))
2042 return(-1);
2043 p = sb_priv;
2044 sprintf(p, "%c%c%c%c%c", IAC, SB, TELOPT_FORWARD_X,
2045 FWDX_OPT_DATA, FWDX_OPT_XAUTH);
2046 p += 5;
2047 p = fwdx_add_quoted_twobyte(p, fake_xauth.name_length);
2048 p = fwdx_add_quoted_twobyte(p, fake_xauth.data_length);
2049 for (c = 0; c < fake_xauth.name_length; c++) {
2050 *p++ = fake_xauth.name[c];
2051 if ((unsigned char)fake_xauth.name[c] == 0xFF)
2052 *p++ = 0xFF;
2053 }
2054 for (c = 0; c < fake_xauth.data_length; c++) {
2055 *p++ = fake_xauth.data[c];
2056 if ((unsigned char)fake_xauth.data[c] == 0xFF)
2057 *p++ = 0xFF;
2058 }
2059 sprintf(p, "%c%c", IAC, SE);
2060 p += 2;
2061
2062 #ifdef DEBUG
2063 if (deblog || tn_deb || debses) {
2064 sprintf((char *)fwdx_msg_out,"TELNET SENT SB %s OPTION_DATA XAUTH ",
2065 TELOPT(TELOPT_FORWARD_X));
2066 tn_hex((char *)fwdx_msg_out,TN_MSG_LEN,&sb_priv[5],(p-sb_priv)-7);
2067 ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
2068 }
2069 #endif /* DEBUG */
2070
2071 /* Add Telnet Debug info here */
2072 #ifdef OS2
2073 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2074 #endif
2075 #ifdef DEBUG
2076 debug(F100,(char *)fwdx_msg_out,"",0);
2077 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
2078 #endif /* DEBUG */
2079 rc = ( ttol(sb_priv,p-sb_priv) < 0 ); /* Send it. */
2080 #ifdef OS2
2081 ReleaseTelnetMutex();
2082 #endif
2083 if (rc) {
2084 debug(F110,"fwdx_send_xauth()","ttol() failed",0);
2085 return(-1);
2086 }
2087
2088
2089 free(sb_priv);
2090 return(0);
2091 }
2092 #endif /* COMMENT */
2093 #ifdef FWDX_SERVER
2094 /* Only if we ever become a server - not yet ported to Kermit */
2095 /* And even so most of this code does not belong in this module */
2096
2097 int
fwdx_write_xauthfile(void)2098 fwdx_write_xauthfile(void)
2099 {
2100 int dpynum, scrnum, family;
2101 char myhost[300], *host, *rest = NULL;
2102 FILE *file;
2103 struct sockaddr_in saddr;
2104 struct hostent *hi;
2105
2106 if (!fwdx_display && !fwdx_xauthfile)
2107 return 1;
2108 if (!parse_displayname(fwdx_display,
2109 &family, &host, &dpynum, &scrnum, &rest))
2110 return 2;
2111 if (rest) free(rest);
2112 if (host) free(host);
2113 if (family != FamilyInternet)
2114 return 3; /* every thing but FamilyInternet is unexpected */
2115
2116 /* X connections to localhost:1 is actually treated as local unix sockets,
2117 * see the 'xauth' man page.
2118 */
2119 xauth.family = FamilyLocal;
2120 if (gethostname(myhost, sizeof(myhost) - 1))
2121 return 5;
2122 xauth.address_length = strlen(myhost);
2123 if (!(xauth.address = malloc(xauth.address_length)))
2124 return 5;
2125 memcpy(xauth.address, myhost, xauth.address_length);
2126
2127 /* the display number is written as a string, not numeric */
2128 if (!(xauth.number = malloc(6)))
2129 return 6;
2130 snprintf(xauth.number, 5, "%u", dpynum);
2131 xauth.number_length = strlen(xauth.number);
2132 if (!(file = fopen(fwdx_xauthfile, "wb")))
2133 return 7;
2134 if (!XauWriteAuth(file, &xauth))
2135 return 8;
2136 fclose(file);
2137 setenv("XAUTHORITY", fwdx_xauthfile, 1);
2138 return 0;
2139 }
2140
2141 int
fwdx_setup_xauth(unsigned char * sp,int len)2142 fwdx_setup_xauth(unsigned char *sp, int len)
2143 /* called with 'len' xauth bytes, starting at 'sp'
2144 * the data format is: <uint16 name_length> <uint16 data_length> <name> <data>
2145 */
2146 {
2147 int xauthfd;
2148
2149 if (!fwdx_options[FWDX_OPT_XAUTH])
2150 return 1;
2151 if (len < 4)
2152 return 2;
2153
2154 /* setup the xauth struct */
2155 xauth.name_length = (sp[0] << 8) + sp[1];
2156 xauth.data_length = (sp[2] << 8) + sp[3];
2157 if (len != 4 + xauth.name_length + xauth.data_length)
2158 return 3;
2159 xauth.name = malloc(xauth.name_length);
2160 xauth.data = malloc(xauth.data_length);
2161 if (!xauth.name || !xauth.data)
2162 return 4;
2163 memcpy(xauth.name, sp + 4, xauth.name_length);
2164 memcpy(xauth.data, sp + 4 + xauth.name_length, xauth.data_length);
2165
2166 /* Setup to always have a local .Xauthority. */
2167 fwdx_xauthfile = malloc(MAXPATHLEN+1);
2168 snprintf(fwdx_xauthfile, MAXPATHLEN, "/tmp/XauthXXXXXX");
2169 if ((xauthfd = mkstemp(fwdx_xauthfile)) != -1)
2170 /* we change file ownership later, when we know who is to be owner! */
2171 close(xauthfd);
2172 else {
2173 free(fwdx_xauthfile);
2174 fwdx_xauthfile = NULL;
2175 return 5;
2176 }
2177 /* Must have the subshell's new DISPLAY env var to write xauth to xauthfile */
2178 if (fwdx_display)
2179 if (fwdx_write_xauthfile())
2180 return 6;
2181
2182 return 0;
2183 }
2184
fwdx_set_xauthfile_owner(int uid)2185 void fwdx_set_xauthfile_owner(int uid)
2186 {
2187 struct passwd *pwd;
2188
2189 if (!fwdx_xauthfile || !(pwd = getpwuid(uid)))
2190 return;
2191 chown(fwdx_xauthfile, pwd->pw_uid, pwd->pw_gid);
2192 }
2193
2194 int
fwdx_server_accept_options(unsigned char * sp,int len)2195 fwdx_server_accept_options(unsigned char *sp, int len)
2196 /* called with 'len' option bytes, starting at 'sp' */
2197 {
2198 int c;
2199
2200 for (c = 0; c < len-2; c++) {
2201 if (c == 0) {
2202 if (sp[c] & FWDX_OPT_XAUTH)
2203 flag = 1;
2204 }
2205 }
2206 return(0);
2207 }
2208 #endif /* FWDX_SERVER */
2209 #endif /* CK_FORWARD_X */
2210
2211 #ifdef IKS_OPTION
2212 /*
2213 iks_wait() -- Wait for an IKS subnegotiation response.
2214 sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
2215 state of the peer's Kermit server.
2216 flushok - specifies whether it is ok to throw away non-Telnet data
2217 if so, then we call ttflui() instead of tn_flui().
2218 Returns:
2219 1 if the desired state is achieved or if it is unknown.
2220 0 if the desired state is not achieved.
2221 */
2222 int
2223 #ifdef CK_ANSIC
iks_wait(int sb,int flushok)2224 iks_wait(int sb, int flushok)
2225 #else /* CK_ANSIC */
2226 iks_wait(sb,flushok) int sb; int flushok;
2227 #endif /* CK_ANSIC */
2228 {
2229 int tn_wait_save = tn_wait_flg;
2230 int x;
2231 /*
2232 Problem noted with the Synchronet Telnet server, e.g. at b4bbs.sampsa.com:
2233 TELNET SENT DO KERMIT
2234 TELNET SENT WILL KERMIT
2235 TELNET RCVD WILL KERMIT <-- KERMIT option negotiated
2236 TELNET SENT SB KERMIT SOP 01 IAC SE <-- This is required
2237 TELNET RCVD DONT KERMIT <-- Required SB KERMIT SOP response not received.
2238
2239 Session hangs waiting for required response. User SETs TELNET WAIT OFF
2240 as a workaround, but session still hangs on next CONNECT command because
2241 tn_wait_flg is set here and never restored. If user SETs TELNET WAIT OFF,
2242 it is precisely to avoid such situations, so it should be respected.
2243 Fixed by testing tn_wait_flg in the following line. -fdc, 2013-04-09.
2244
2245 printf("*** TN_WAIT_FLG=*** TELOPT_U(TELOPT_KERMIT)=0%d\n",tn_wait_flg);
2246 printf("*** TELOPT_U(TELOPT_KERMIT)=%d\n",TELOPT_U(TELOPT_KERMIT));
2247 */
2248 if (tn_wait_flg && TELOPT_U(TELOPT_KERMIT)) {
2249 switch (sb) {
2250 case KERMIT_REQ_START:
2251 debug(F111,
2252 "iks_wait KERMIT_REQ_START",
2253 "u_start",
2254 TELOPT_SB(TELOPT_KERMIT).kermit.u_start
2255 );
2256 tn_siks(KERMIT_REQ_START); /* SB KERMIT SOP x */
2257 tn_wait_flg = 1; /* MUST wait for response: RFC2840 */
2258 do {
2259 if (flushok)
2260 tn_wait_idx = 0;
2261 x = tn_wait("iks_wait() me_iks_req_start");
2262 } while (x == 0 &&
2263 flushok &&
2264 tn_wait_idx == TN_WAIT_BUF_SZ &&
2265 /*
2266 The idea here is that if, while waiting for a response to SB KERMIT SOP,
2267 we get a DONT KERMIT, as happens in at least one real-life situation,
2268 we break out of the wait loop. It's not exactly according to spec but
2269 it makes sense. This should work because tn_wait() calls tn_doop(), which
2270 calls tn_xdoop(), which will unset TELOPT_ME(TELOPT_KERMIT) if DONT KERMIT
2271 arrives. -fdc, 2013-04-10.
2272 */
2273 TELOPT_ME(TELOPT_KERMIT)
2274 );
2275 tn_wait_flg = tn_wait_save;
2276 if (flushok)
2277 tn_wait_idx = 0;
2278 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
2279 /*
2280 * We are attempting to start a kermit server on the peer
2281 * the most likely reason is because we want to perform a
2282 * file transfer. But there is a huge amount of non telnet
2283 * negotiation data coming in and so we have not been able
2284 * to find the response. So we will lie and assume that
2285 * response is 'yes'. The worse that will happen is that
2286 * a RESP_STOP is received after we enter protocol mode.
2287 * And the protocol operation will be canceled.
2288 */
2289 tn_push();
2290 return(1);
2291 } else {
2292 tn_push();
2293 return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
2294 }
2295 case KERMIT_REQ_STOP:
2296 debug(F111,
2297 "iks_wait KERMIT_REQ_STOP",
2298 "u_start",
2299 TELOPT_SB(TELOPT_KERMIT).kermit.u_start
2300 );
2301 tn_siks(KERMIT_REQ_STOP);
2302 tn_wait_flg = 1; /* Kermit Option MUST wait */
2303 do {
2304 if (flushok)
2305 tn_wait_idx = 0;
2306 x = tn_wait("iks_wait() me_iks_req_stop");
2307 } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
2308 tn_wait_flg = tn_wait_save;
2309 if (flushok)
2310 tn_wait_idx = 0;
2311
2312 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
2313 /*
2314 * We are attempting to stop a kermit server on the peer
2315 * the most likely reason being that we want to enter
2316 * CONNECT mode. But there is a huge amount of non telnet
2317 * negotiation data coming in and so we have not been able
2318 * to find the response. So we will lie and assume that
2319 * the answer is 'yes' and allow the CONNECT command to
2320 * succeed. The worst that happens is that CONNECT mode
2321 * swallows the incoming data displaying it to the user
2322 * and then it resumes Kermit client mode.
2323 */
2324 tn_push();
2325 return(1);
2326 } else {
2327 tn_push();
2328 return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
2329 }
2330 }
2331 tn_push();
2332 }
2333 return(1);
2334 }
2335
2336 int
2337 #ifdef CK_ANSIC
iks_tn_sb(CHAR * sb,int n)2338 iks_tn_sb(CHAR * sb, int n)
2339 #else
2340 iks_tn_sb(sb, n) CHAR * sb; int n;
2341 #endif /* CK_ANSIC */
2342 {
2343 extern int server;
2344 extern CHAR sstate;
2345 #ifdef NOICP
2346 extern int autodl;
2347 int inautodl = 0, cmdadl = 1;
2348 #else
2349 #ifdef CK_AUTODL
2350 extern int autodl, inautodl, cmdadl;
2351 #endif /* CK_AUTODL */
2352 #endif /* NOICP */
2353 switch (sb[0]) {
2354 case KERMIT_START: /* START */
2355 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
2356 return(4);
2357
2358 case KERMIT_STOP: /* STOP */
2359 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2360 return(4);
2361
2362 case KERMIT_REQ_START: /* REQ-START */
2363 #ifndef NOXFER
2364 if (inserver) {
2365 #ifdef CK_AUTODL
2366 cmdadl = 1; /* Turn on packet detection */
2367 #endif /* CK_AUTODL */
2368 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
2369 tn_siks(KERMIT_RESP_START);
2370 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2371 tn_siks(KERMIT_RESP_START);
2372 } else {
2373 #ifndef IKSDONLY
2374 #ifdef CK_AUTODL
2375 #ifdef OS2
2376 if (local && (IsConnectMode() && autodl) ||
2377 (!IsConnectMode() &&
2378 (inautodl || sstate == 'x' || sstate == 'v'))
2379 )
2380 tn_siks(KERMIT_RESP_START); /* START */
2381 else
2382
2383 #else /* OS2 */
2384 if ((local && what == W_CONNECT && autodl) ||
2385 (local && what != W_CONNECT &&
2386 (inautodl || sstate == 'x' || sstate == 'v')
2387 ))
2388 tn_siks(KERMIT_RESP_START); /* START */
2389 else
2390 #endif /* OS2 */
2391 #endif /* CK_AUTODL */
2392 #endif /* IKSDONLY */
2393 tn_siks(KERMIT_RESP_STOP);
2394 }
2395 #else /* NOXFER */
2396 tn_siks(KERMIT_RESP_STOP);
2397 #endif /* NOXFER */
2398 return(4);
2399
2400 case KERMIT_REQ_STOP: /* REQ-STOP */
2401 /* The protocol requires that the request be responded to */
2402 /* either by changing states or by reporting the current */
2403 /* state. */
2404
2405 /* We need to provide the user some way of dictating what */
2406 /* the policies should be. For instance, if we are in */
2407 /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
2408 /* what should the proper response be? */
2409 #ifndef NOXFER
2410 if (inserver
2411 #ifdef CK_AUTODL
2412 || !local && cmdadl
2413 #endif /* CK_AUTODL */
2414 ) {
2415 #ifdef CK_AUTODL
2416 cmdadl = 0; /* Turn off packet detection */
2417 #endif /* CK_AUTODL */
2418 tn_siks(KERMIT_RESP_STOP);
2419 } else if (server) {
2420 extern int en_fin;
2421 if (en_fin) { /* If the server is allowed to stop */
2422 tn_siks(KERMIT_RESP_STOP);
2423 } else { /* We are not allowed to stop */
2424 tn_siks(KERMIT_RESP_START);
2425 }
2426 }
2427 #ifndef IKSDONLY
2428 #ifdef CK_AUTODL
2429 #ifdef OS2
2430 else if (local && (IsConnectMode() && autodl) ||
2431 (!IsConnectMode() && inautodl)
2432 ) {
2433 /* If we are a pseudo-server and the other side requests */
2434 /* that we stop, tell then that we have even though we */
2435 /* have not. Otherwise, the other side might refuse to */
2436 /* enter SERVER mode. */
2437
2438 tn_siks(KERMIT_RESP_STOP); /* STOP */
2439 }
2440 #else /* OS2 */
2441 else if ((local && what == W_CONNECT && autodl) ||
2442 (local && what != W_CONNECT && inautodl)
2443 ) {
2444 /* If we are a pseudo-server and the other side requests */
2445 /* that we stop, tell then that we have even though we */
2446 /* have not. Otherwise, the other side might refuse to */
2447 /* enter SERVER mode. */
2448
2449 tn_siks(KERMIT_RESP_STOP); /* STOP */
2450 }
2451 #endif /* OS2 */
2452 #endif /* CK_AUTODL */
2453 #endif /* IKSDONLY */
2454 else
2455 #endif /* NOXFER */
2456 {
2457 /* If we are not currently in any mode that accepts */
2458 /* Kermit packets then of course report that we are */
2459 /* not being a Kermit server. */
2460
2461 tn_siks(KERMIT_RESP_STOP); /* STOP */
2462 }
2463 return(4);
2464
2465 case KERMIT_SOP: { /* SOP */
2466 #ifndef NOXFER
2467 extern CHAR stchr; /* Incoming SOP character */
2468 stchr = sb[1];
2469 #endif /* NOXFER */
2470 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
2471 return(4);
2472 }
2473
2474 case KERMIT_RESP_START: /* START */
2475 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
2476 if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
2477 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2478 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
2479 /* If we have issued a request to stop a Kermit Server */
2480 /* and the response is Start, then we must report this */
2481 /* to the caller. */
2482 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2483 }
2484 return(4);
2485
2486 case KERMIT_RESP_STOP: /* STOP */
2487 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2488 if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
2489 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2490 /* If we have issued a request to start a Kermit Server */
2491 /* and the response is Stop, then we must report this */
2492 /* to the caller. */
2493 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
2494 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2495 }
2496 return(4);
2497
2498 default:
2499 return(0);
2500
2501 } /* switch (sb[0]) */
2502 }
2503 #endif /* IKS_OPTION */
2504
2505 /* Initialize telnet settings - set default values for ME and U modes */
2506 int
tn_set_modes()2507 tn_set_modes() {
2508 int opt,cmd;
2509 #ifdef CK_FORWARD_X
2510 int x;
2511 #endif /* CK_FORWARD_X */
2512 #ifdef CK_ENVIRONMENT
2513 {
2514 int i,j;
2515 for (i = 0; i < 8; i++) {
2516 tn_env_uservar[i][0] = NULL;
2517 tn_env_uservar[i][1] = NULL;
2518 }
2519 }
2520 #endif /* CK_ENVIRONMENT */
2521
2522 /* initialize all options to refuse in both directions */
2523 for (opt = 0; opt < NTELOPTS; opt++) {
2524 TELOPT_ME(opt) = 0;
2525 TELOPT_U(opt) = 0;
2526 TELOPT_UNANSWERED_WILL(opt) = 0;
2527 TELOPT_UNANSWERED_DO(opt) = 0;
2528 TELOPT_UNANSWERED_WONT(opt) = 0;
2529 TELOPT_UNANSWERED_DONT(opt) = 0;
2530 TELOPT_UNANSWERED_SB(opt) = 0;
2531 TELOPT_ME_MODE(opt) = TN_NG_RF;
2532 TELOPT_U_MODE(opt) = TN_NG_RF;
2533 TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
2534 TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
2535 TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
2536 TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
2537 for (cmd = 0; cmd < 4; cmd ++)
2538 tncnts[TELOPT_INDEX(opt)][cmd] = 0;
2539 }
2540 #ifdef IKS_OPTION
2541 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
2542 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2543 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2544 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2545 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
2546 #endif /* IKS_OPTION */
2547
2548 #ifdef CK_ENCRYPTION
2549 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
2550 #endif /* CK_ENCRYPTION */
2551
2552 #ifdef CK_NAWS
2553 TELOPT_SB(TELOPT_NAWS).naws.x = 0;
2554 TELOPT_SB(TELOPT_NAWS).naws.y = 0;
2555 #endif /* CK_NAWS */
2556
2557 #ifdef CK_SSL
2558 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
2559 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
2560 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
2561 #endif /* CK_SSL */
2562
2563 /* Now set the ones we want to accept to the proper values */
2564 TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
2565 TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
2566 TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
2567 TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
2568
2569 TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
2570 TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
2571 TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
2572 TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
2573
2574 TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2575 TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2576 TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2577 TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2578
2579 #ifdef IKS_OPTION
2580 TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2581 TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2582 TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2583 TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2584 #endif /* IKS_OPTION */
2585
2586 #ifdef CK_ENCRYPTION
2587 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2588 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2589 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2590 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2591 #endif /* CK_ENCRYPTION */
2592
2593 TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
2594 #ifdef IKSD
2595 if ( !inserver )
2596 #endif /* IKSD */
2597 TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
2598
2599 #ifdef CK_ENVIRONMENT
2600 TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
2601 #endif /* CK_ENVIRONMENT */
2602
2603 #ifdef CK_AUTHENTICATION
2604 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
2605 #endif /* CK_AUTHENTICATION */
2606
2607 #ifdef CK_SSL
2608 if (ck_ssleay_is_installed()) {
2609 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
2610 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
2611 }
2612 #endif /* CK_SSL */
2613
2614 #ifdef CK_NAWS
2615 TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
2616 #endif /* CK_NAWS */
2617
2618 TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
2619 TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
2620
2621 #ifdef CK_ENVIRONMENT
2622 TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
2623 #endif /* CK_ENVIRONMENT */
2624
2625 #ifdef CK_AUTHENTICATION
2626 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
2627 #endif /* CK_AUTHENTICATION */
2628
2629 #ifdef CK_NAWS
2630 TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
2631 #endif /* CK_NAWS */
2632
2633 #ifdef CK_SNDLOC
2634 TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
2635 #endif /* CK_SNDLOC */
2636
2637 #ifdef CK_FORWARD_X
2638 TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_AC;
2639 TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
2640 for (x = 0; x < MAXFWDX; x++) {
2641 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
2642 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
2643 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
2644 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
2645 }
2646 #endif /* CK_FORWARD_X */
2647
2648 #ifdef TN_COMPORT
2649 TELOPT_DEF_C_ME_MODE(TELOPT_COMPORT) = TN_NG_RQ;
2650 #endif /* TN_COMPORT */
2651
2652 /* Set the initial values for currently known mode */
2653 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
2654 if (TELOPT_OK(opt)) {
2655 TELOPT_ME_MODE(opt) = sstelnet ?
2656 TELOPT_DEF_S_ME_MODE(opt) :
2657 TELOPT_DEF_C_ME_MODE(opt);
2658 TELOPT_U_MODE(opt) = sstelnet ?
2659 TELOPT_DEF_S_U_MODE(opt) :
2660 TELOPT_DEF_C_U_MODE(opt);
2661 }
2662 }
2663 return(1);
2664 }
2665
2666
2667 /* Send Delayed Subnegotiations */
2668
2669 VOID
tn_sdsb()2670 tn_sdsb() {
2671 /* if (!IS_TELNET()) return; */
2672
2673 if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
2674 tn_sttyp();
2675 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
2676 }
2677 #ifdef CK_ENVIRONMENT
2678 if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
2679 TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
2680 tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
2681 TELOPT_SB(TELOPT_NEWENVIRON).env.len);
2682 free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
2683 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2684 TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
2685 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
2686 }
2687 #ifdef CK_XDISPLOC
2688 if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
2689 tn_sxdisploc();
2690 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
2691 }
2692 #endif /* CK_XDISPLOC */
2693 #endif /* CK_ENVIRONMENT */
2694 #ifdef CK_NAWS
2695 if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
2696 tn_snaws();
2697 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
2698 }
2699 #endif /* CK_NAWS */
2700 #ifdef CK_SNDLOC
2701 if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
2702 tn_sndloc();
2703 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
2704 }
2705 #endif /* CK_SNDLOC */
2706 #ifdef CK_FORWARD_X
2707 if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
2708 if ( sstelnet )
2709 fwdx_send_options();
2710 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
2711 }
2712 #endif /* CK_FORWARD_X */
2713 #ifdef TN_COMPORT
2714 if (TELOPT_SB(TELOPT_COMPORT).comport.need_to_send) {
2715 tn_sndcomport();
2716 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
2717 }
2718 #endif /* TN_COMPORT */
2719
2720 }
2721
2722 int
tn_reset()2723 tn_reset() {
2724 int x,opt,cmd;
2725
2726 /* if (!IS_TELNET()) return(1); */
2727
2728 tn_wait_idx = 0; /* Clear the tn_push() buffer */
2729 tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
2730
2731 nflag = 0;
2732
2733 /* Reset the TELNET OPTIONS counts */
2734 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
2735 if (TELOPT_OK(opt)) {
2736 TELOPT_ME(opt) = 0;
2737 TELOPT_U(opt) = 0;
2738 TELOPT_UNANSWERED_WILL(opt) = 0;
2739 TELOPT_UNANSWERED_DO(opt) = 0;
2740 TELOPT_UNANSWERED_WONT(opt) = 0;
2741 TELOPT_UNANSWERED_DONT(opt) = 0;
2742 TELOPT_UNANSWERED_SB(opt) = 0;
2743 TELOPT_ME_MODE(opt) = sstelnet ?
2744 TELOPT_DEF_S_ME_MODE(opt) :
2745 TELOPT_DEF_C_ME_MODE(opt);
2746 TELOPT_U_MODE(opt) = sstelnet ?
2747 TELOPT_DEF_S_U_MODE(opt) :
2748 TELOPT_DEF_C_U_MODE(opt);
2749
2750 #ifdef DEBUG
2751 if (deblog) {
2752 switch (TELOPT_ME_MODE(opt)) {
2753 case TN_NG_RF:
2754 debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
2755 break;
2756 case TN_NG_AC:
2757 debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
2758 break;
2759 case TN_NG_RQ:
2760 debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
2761 break;
2762 case TN_NG_MU:
2763 debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
2764 break;
2765 }
2766 switch (TELOPT_U_MODE(opt)) {
2767 case TN_NG_RF:
2768 debug(F110,"tn_ini U REFUSE ",TELOPT(opt),0);
2769 break;
2770 case TN_NG_AC:
2771 debug(F110,"tn_ini U ACCEPT ",TELOPT(opt),0);
2772 break;
2773 case TN_NG_RQ:
2774 debug(F110,"tn_ini U REQUEST",TELOPT(opt),0);
2775 break;
2776 case TN_NG_MU:
2777 debug(F110,"tn_ini U REQUIRE",TELOPT(opt),0);
2778 break;
2779 }
2780 }
2781 #endif /* DEBUG */
2782 for (cmd = 0; cmd < 4; cmd ++)
2783 tncnts[TELOPT_INDEX(opt)][cmd] = 0;
2784 }
2785 }
2786 #ifdef CK_ENVIRONMENT
2787 if (!tn_env_flg) {
2788 TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
2789 TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
2790 }
2791 #endif /* CK_ENVIRONMENT */
2792 #ifdef CK_SNDLOC
2793 if (!tn_loc)
2794 TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
2795 #endif /* CK_SNDLOC */
2796 #ifdef IKS_OPTION
2797 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
2798 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2799 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2800 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2801 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
2802 #endif /* IKS_OPTION */
2803 #ifdef CK_ENCRYPTION
2804 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
2805 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
2806 #endif /* CK_ENCRYPTION */
2807 #ifdef CK_NAWS
2808 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
2809 TELOPT_SB(TELOPT_NAWS).naws.x = 0;
2810 TELOPT_SB(TELOPT_NAWS).naws.y = 0;
2811 #endif /* CK_NAWS */
2812 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
2813 TELOPT_SB(TELOPT_TTYPE).term.type[0] = '\0';
2814 #ifdef CK_ENVIRONMENT
2815 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
2816 if (tn_first)
2817 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2818 else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
2819 free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
2820 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2821 }
2822 TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
2823 #ifdef CK_XDISPLOC
2824 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
2825 #endif /* CK_XDISPLOC */
2826 #endif /* CK_ENVIRONMENT */
2827 #ifdef CK_SNDLOC
2828 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
2829 #endif /* CK_SNDLOC */
2830 #ifdef CK_FORWARD_X
2831 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
2832 TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
2833 for (x = 0; x < MAXFWDX; x++) {
2834 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
2835 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
2836 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
2837 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
2838 }
2839 /* Reset Xauth data */
2840 if ( real_xauth ) {
2841 XauDisposeAuth(real_xauth);
2842 real_xauth = NULL;
2843 }
2844 if ( fake_xauth.name )
2845 free(fake_xauth.name);
2846 if ( fake_xauth.data )
2847 free(fake_xauth.data);
2848 if ( fake_xauth.address )
2849 free(fake_xauth.address);
2850 if ( fake_xauth.number )
2851 free(fake_xauth.number);
2852 memset(&fake_xauth,0,sizeof(fake_xauth));
2853 #ifdef NT
2854 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
2855 #endif /* NT */
2856 #endif /* CK_FORWARD_X */
2857 #ifdef CK_SSL
2858 if (tls_only_flag || ssl_only_flag) {
2859 TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
2860 TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
2861 }
2862 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
2863 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
2864 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
2865 #endif /* CK_SSL */
2866
2867 #ifdef CK_ENCRYPTION
2868 if (!ck_crypt_is_installed()
2869 #ifdef CK_SSL
2870 || tls_only_flag || ssl_only_flag
2871 #endif /* CK_SSL */
2872 ) {
2873 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2874 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2875 }
2876 #endif /* CK_ENCRYPTION */
2877
2878 #ifdef TN_COMPORT
2879 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
2880 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
2881 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
2882 tnc_init();
2883 #endif /* TN_COMPORT */
2884
2885 tn_first = 0; /* No longer the first time init */
2886
2887 #ifdef OS2
2888 ttnum = -1; /* Reset TermType negotiation */
2889 ttnumend = 0;
2890 #endif /* OS2 */
2891
2892 return(0);
2893 }
2894
2895 int
tn_start()2896 tn_start() {
2897 int wait, x, opt;
2898
2899 /* if (!IS_TELNET()) return(0); */
2900
2901 if (tn_init && tn_begun)
2902 return(0);
2903 tn_begun = 1;
2904
2905 debug(F111,"tn_start","sstelnet",sstelnet);
2906 wait = 0;
2907 if (tn_duplex) {
2908 oldplex = duplex; /* save old duplex value */
2909 duplex = 1; /* and set to half duplex for telnet */
2910 }
2911 #ifdef CK_SSL
2912 if (!TELOPT_ME(TELOPT_START_TLS) &&
2913 TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
2914 if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
2915 return(-1);
2916 TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
2917 wait = 1;
2918 }
2919 if (!TELOPT_U(TELOPT_START_TLS) &&
2920 TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
2921 if (tn_sopt(DO, TELOPT_START_TLS) < 0)
2922 return(-1);
2923 TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
2924 wait = 1;
2925 }
2926 #endif /* CK_SSL */
2927
2928 #ifdef CK_AUTHENTICATION
2929 debug(F110,"tn_ini() CK_AUTHENTICATION","",0);
2930 if (tn_init) /* tn_ini() might be called recursively */
2931 return(0);
2932 if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
2933 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
2934 if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
2935 return(-1);
2936 TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
2937 wait = 1;
2938 }
2939 if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
2940 TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
2941 if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
2942 return(-1);
2943 TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
2944 wait = 1;
2945 }
2946 #ifdef CK_ENCRYPTION
2947 if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
2948 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
2949 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2950 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2951 }
2952 #endif /* CK_ENCRYPTION */
2953 #endif /* CK_AUTHENTICATION */
2954
2955 #ifdef CK_NAWS
2956 #ifndef NOLOCAL
2957 debug(F110,"tn_ini() CK_NAWS !NOLOCAL","",0);
2958 if (!sstelnet) {
2959 /* Console terminal screen rows and columns */
2960 #ifdef OS2
2961 debug(F101,
2962 "tn_ini tt_rows 1",
2963 "",
2964 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
2965 );
2966 debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
2967 /* Not known yet */
2968 if (VscrnGetWidth(VTERM) < 0 ||
2969 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) < 0) {
2970 ttgwsiz(); /* Try to find out */
2971 }
2972 debug(F101,
2973 "tn_ini tt_rows 2",
2974 "",
2975 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
2976 );
2977 debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
2978 /* Now do we know? */
2979 if (VscrnGetWidth(VTERM) > 0 &&
2980 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) > 0) {
2981 if (!TELOPT_ME(TELOPT_NAWS) &&
2982 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2983 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
2984 return(-1);
2985 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
2986 wait = 1;
2987 }
2988 }
2989 #else /* OS2 */
2990 debug(F101,"tn_ini tt_rows 1","",tt_rows);
2991 debug(F101,"tn_ini tt_cols 1","",tt_cols);
2992 if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
2993 ttgwsiz(); /* Try to find out */
2994 }
2995 debug(F101,"tn_ini tt_rows 2","",tt_rows);
2996 debug(F101,"tn_ini tt_cols 2","",tt_cols);
2997 if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
2998 if (!TELOPT_ME(TELOPT_NAWS) &&
2999 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
3000 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
3001 return(-1);
3002 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
3003 wait = 1;
3004 }
3005 }
3006 #endif /* OS2 */
3007 } else
3008 #endif /* NOLOCAL */
3009 {
3010 if (!TELOPT_U(TELOPT_NAWS) &&
3011 TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
3012 if (tn_sopt(DO, TELOPT_NAWS) < 0)
3013 return(-1);
3014 TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
3015 wait = 1;
3016 }
3017 }
3018 #endif /* CK_NAWS */
3019
3020 if (!TELOPT_ME(TELOPT_SGA) &&
3021 TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
3022 if (tn_sopt(WILL, TELOPT_SGA) < 0)
3023 return(-1);
3024 TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
3025 wait = 1;
3026 }
3027 if (!TELOPT_U(TELOPT_SGA) &&
3028 TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
3029 if (tn_sopt(DO, TELOPT_SGA) < 0)
3030 return(-1);
3031 TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
3032 wait = 1;
3033 }
3034 if (!tn_duplex) {
3035 if (!TELOPT_U(TELOPT_ECHO) &&
3036 TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
3037 if (tn_sopt(DO, TELOPT_ECHO) < 0)
3038 return(-1);
3039 TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
3040 wait = 1;
3041 }
3042 }
3043 if (!TELOPT_ME(TELOPT_ECHO) &&
3044 TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
3045 if (tn_sopt(WILL, TELOPT_ECHO) < 0)
3046 return(-1);
3047 TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
3048 wait = 1;
3049 }
3050
3051 debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
3052 /*
3053 Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
3054 Also send WILL NAWS if we know our screen dimensions.
3055 */
3056 if (!TELOPT_ME(TELOPT_TTYPE) &&
3057 TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
3058 if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
3059 debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
3060 return(-1);
3061 }
3062 TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
3063 wait = 1;
3064 debug(F100,"tn_ini sent WILL TTYPE ok","",0);
3065 }
3066 if (!TELOPT_U(TELOPT_TTYPE) &&
3067 TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
3068 if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
3069 debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
3070 return(-1);
3071 }
3072 TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
3073 wait = 1;
3074 debug(F100,"tn_ini sent DO TTYPE ok","",0);
3075 }
3076 if (!TELOPT_ME(TELOPT_BINARY) &&
3077 TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
3078 if (tn_sopt(WILL, TELOPT_BINARY) < 0)
3079 return(-1);
3080 TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
3081 wait = 1;
3082 }
3083 if (!TELOPT_U(TELOPT_BINARY) &&
3084 TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
3085 if (tn_sopt(DO, TELOPT_BINARY) < 0)
3086 return(-1);
3087 TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
3088 wait = 1;
3089 }
3090 #ifdef CK_SNDLOC
3091 if (tn_loc) {
3092 if (!TELOPT_ME(TELOPT_SNDLOC) &&
3093 TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
3094 if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
3095 return(-1);
3096 TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
3097 wait = 1;
3098 }
3099 }
3100 #endif /* CK_SNDLOC */
3101 #ifdef CK_ENVIRONMENT
3102 #ifdef CK_FORWARD_X
3103 if (!TELOPT_U(TELOPT_FORWARD_X) &&
3104 TELOPT_U_MODE(TELOPT_FORWARD_X) >= TN_NG_RQ) {
3105 if (tn_sopt(WILL, TELOPT_FORWARD_X) < 0)
3106 return(-1);
3107 TELOPT_UNANSWERED_WILL(TELOPT_FORWARD_X) = 1;
3108 wait = 1;
3109 }
3110 #endif /* FORWARD_X */
3111 #ifdef CK_XDISPLOC
3112 if (!TELOPT_ME(TELOPT_XDISPLOC) &&
3113 TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
3114 if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
3115 return(-1);
3116 TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
3117 wait = 1;
3118 }
3119 #endif /* CK_XDISPLOC */
3120 /* Will send terminal environment. */
3121 if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
3122 TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
3123 if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
3124 return(-1);
3125 TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
3126 wait = 1;
3127 }
3128 if (!TELOPT_U(TELOPT_NEWENVIRON) &&
3129 TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
3130 if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
3131 return(-1);
3132 TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
3133 wait = 1;
3134 }
3135 #endif /* CK_ENVIRONMENT */
3136
3137 /* Take care of any other telnet options that require handling. */
3138
3139 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
3140 switch (opt) {
3141 case TELOPT_AUTHENTICATION:
3142 case TELOPT_ENCRYPTION:
3143 case TELOPT_TTYPE:
3144 case TELOPT_NAWS:
3145 case TELOPT_BINARY:
3146 case TELOPT_NEWENVIRON:
3147 case TELOPT_SNDLOC:
3148 case TELOPT_XDISPLOC:
3149 case TELOPT_SGA:
3150 case TELOPT_ECHO:
3151 case TELOPT_KERMIT:
3152 case TELOPT_START_TLS:
3153 case TELOPT_FORWARD_X:
3154 break;
3155 break;
3156 default:
3157 if (TELOPT_OK(opt)) {
3158 if (!TELOPT_ME(opt) &&
3159 TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
3160 if (tn_sopt(WILL, opt) < 0)
3161 return(-1);
3162 TELOPT_UNANSWERED_WILL(opt) = 1;
3163 wait = 1;
3164 }
3165 if (!TELOPT_U(opt) &&
3166 TELOPT_U_MODE(opt) >= TN_NG_RQ) {
3167 if (tn_sopt(DO, opt) < 0)
3168 return(-1);
3169 TELOPT_UNANSWERED_DO(opt) = 1;
3170 wait = 1;
3171 }
3172 }
3173 }
3174 }
3175 if (wait) {
3176 if (tn_wait("pre-encrypt") < 0) {
3177 tn_push();
3178 return(-1);
3179 }
3180 wait = 0;
3181 }
3182
3183 #ifdef CK_ENCRYPTION
3184 if (tn_init) /* tn_ini() may be called recursively */
3185 return(0);
3186
3187 if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
3188 TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
3189 if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
3190 return(-1);
3191 TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
3192 wait = 1;
3193 }
3194 if (!TELOPT_U(TELOPT_ENCRYPTION) &&
3195 TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
3196 if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
3197 return(-1);
3198 TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
3199 wait = 1;
3200 }
3201
3202 /* If we are going to encrypt, we want to do it before we send any more */
3203 /* data, especially the terminal type and environment variables. */
3204 if (wait) {
3205 if (tn_wait("post-encrypt") < 0) {
3206 tn_push();
3207 return(-1);
3208 }
3209 wait = 0;
3210 }
3211 #endif /* CK_ENCRYPTION */
3212
3213 tn_sdsb();
3214
3215 if (tn_init) /* tn_ini() may be called recursively */
3216 return(0);
3217
3218 #ifdef IKS_OPTION
3219 /* Kermit Server negotiation must go last */
3220 /* Send U before ME */
3221
3222 if (!TELOPT_U(TELOPT_KERMIT) &&
3223 TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
3224 if (tn_sopt(DO, TELOPT_KERMIT) < 0)
3225 return(-1);
3226 TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
3227 wait = 1;
3228 }
3229 if (!TELOPT_ME(TELOPT_KERMIT) &&
3230 TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
3231 if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
3232 return(-1);
3233 TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
3234 wait = 1;
3235 }
3236 #endif /* IKS_OPTION */
3237
3238 if (wait) {
3239 if (tn_wait("end of telnet negotiations") < 0) {
3240 tn_push();
3241 return(-1);
3242 }
3243 wait = 0;
3244 }
3245
3246 tn_sdsb(); /* Send delayed subnegotiations */
3247 tn_push();
3248 return(0);
3249 }
3250
3251 /* Start a telnet connection. */
3252 /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
3253
3254 int
tn_ini()3255 tn_ini() {
3256 int x;
3257
3258 debug(F101,"tn_ini ttnproto","",ttnproto);
3259 debug(F101,"tn_ini tn_init","",tn_init);
3260
3261 if (ttnet != NET_TCPB) /* Make sure connection is TCP/IP */
3262 return(0);
3263 /*
3264 if (!IS_TELNET())
3265 return(0);
3266 */
3267 if (tn_init) /* Have we done this already? */
3268 return(0); /* Don't do it again. */
3269
3270 tn_reset(); /* Reset telnet parameters */
3271 tn_begun = 0; /* Reset; will be set by tn_start() */
3272
3273 switch ( ttnproto ) {
3274 case NP_RLOGIN:
3275 case NP_K4LOGIN:
3276 case NP_EK4LOGIN:
3277 case NP_K5LOGIN:
3278 case NP_EK5LOGIN:
3279 case NP_K5U2U:
3280 tn_init = 1;
3281 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3282 return(0);
3283 #ifdef COMMENT
3284 /* Jeff's code from 30 Dec 2005 - doesn't work with SSL POP server */
3285 case NP_NONE:
3286 case NP_SSL:
3287 case NP_TLS:
3288 ttnproto = NP_TELNET; /* pretend it's telnet anyway, */
3289 oldplex = duplex; /* save old duplex value */
3290 duplex = 1; /* and set to half duplex for telnet */
3291 if (inserver)
3292 debug(F100,"tn_ini skipping telnet negotiations","",0);
3293 else
3294 tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
3295 tn_push();
3296 return(0);
3297 case NP_SSL_RAW:
3298 case NP_TLS_RAW:
3299 case NP_TCPRAW: /* Raw socket requested. */
3300 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3301 return(0);
3302 #else
3303 /* My code from 4 Dec 2005 - works with SSL POP server */
3304 case NP_NONE:
3305 case NP_SSL:
3306 case NP_TLS: /* If not talking to a telnet port, */
3307 case NP_SSL_RAW: /* SSL and TLS with Telnet */
3308 case NP_TLS_RAW: /* negotiations disabled. */
3309 ttnproto = NP_TELNET; /* pretend it's telnet anyway, */
3310 oldplex = duplex; /* save old duplex value */
3311 duplex = 1; /* and set to half duplex for telnet */
3312 if (inserver)
3313 debug(F100,"tn_ini skipping telnet negotiations","",0);
3314 else
3315 tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
3316 tn_push();
3317 return(0);
3318 case NP_TCPRAW: /* Raw socket requested. */
3319 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3320 return(0);
3321 #endif /* COMMENT */
3322 case NP_KERMIT: /* switching to Telnet protocol */
3323 case NP_SSL_TELNET:
3324 case NP_TLS_TELNET:
3325 debug(F101,"tn_ini switching from XXX to Telnet","",ttnproto);
3326 ttnproto = NP_TELNET;
3327 /* fall through */
3328 default:
3329 /* We are already using a variation on Telnet protocol */
3330 ;
3331 }
3332
3333 x = tn_start();
3334 tn_init = 1; /* Remember successful completion. */
3335
3336 /* Don't send anything else! */
3337 debug(F101,"tn_ini duplex","",duplex);
3338 debug(F101,"tn_ini done, tn_init","",tn_init);
3339 return(x);
3340 }
3341
3342 int
3343 #ifdef CK_ANSIC
tn_hex(CHAR * buf,int buflen,CHAR * data,int datalen)3344 tn_hex(CHAR * buf, int buflen, CHAR * data, int datalen)
3345 #else /* CK_ANSIC */
3346 tn_hex(buf, buflen, data, datalen)
3347 CHAR * buf;
3348 int buflen;
3349 CHAR * data;
3350 int datalen;
3351 #endif /* CK_ANSIC */
3352 {
3353 int i = 0, j = 0, k = 0;
3354 CHAR tmp[16]; /* in case value is treated as negative */
3355 #ifdef COMMENT
3356 int was_hex = 1;
3357
3358 for (k=0; k < datalen; k++) {
3359 if (data[k] < 32 || data[k] >= 127) {
3360 sprintf(tmp,"%s%02X ",was_hex?"":"\" ",data[k]);
3361 was_hex = 1;
3362 } else {
3363 sprintf(tmp,"%s%c",was_hex?"\"":"",data[k]);
3364 was_hex = 0;
3365 }
3366 ckstrncat((char *)buf,tmp,buflen);
3367 }
3368 if (!was_hex)
3369 ckstrncat((char *)buf,"\" ",buflen);
3370 #else /* COMMENT */
3371 if (datalen <= 0 || data == NULL || buf == NULL || buflen <= 0)
3372 return(0);
3373
3374 for (i = 0; i < datalen; i++) {
3375 ckstrncat((char *)buf,"\r\n ",buflen);
3376 for (j = 0 ; (j < 16); j++) {
3377 if ((i + j) < datalen)
3378 sprintf((char *)tmp,
3379 "%s%02x ",
3380 (j == 8 ? "| " : ""),
3381 (unsigned int) data[i + j]
3382 );
3383 else
3384 sprintf((char *)tmp,
3385 "%s ",
3386 (j == 8 ? "| " : "")
3387 );
3388 ckstrncat((char *)buf,(char *)tmp,buflen);
3389 }
3390 ckstrncat((char *)buf," ",buflen);
3391 for (k = 0; (k < 16) && ((i + k) < datalen); k++) {
3392 sprintf((char *)tmp,
3393 "%s%c",
3394 (k == 8 ? " " : ""),
3395 isprint((char)(data[i+k])) ? data[i+k] : '.'
3396 );
3397 ckstrncat((char *)buf,(char *)tmp,buflen);
3398 }
3399 i += j - 1;
3400 } /* end for */
3401 ckstrncat((char *)buf,"\r\n ",buflen);
3402 #endif /* COMMENT */
3403 return(strlen((char *)buf));
3404 }
3405
3406 VOID
tn_debug(s)3407 tn_debug(s) char *s; {
3408 #ifdef NOLOCAL
3409 return;
3410 #else /* NOLOCAL */
3411 #ifdef OS2
3412 void cwrite(unsigned short);
3413 char *p = s;
3414 _PROTOTYP (void os2bold, (void));
3415 extern int tt_type_mode;
3416 #endif /* OS2 */
3417
3418 if (!(tn_deb || debses))
3419 return;
3420 debug(F111,"tn_debug",s,what);
3421 #ifdef OS2
3422 if (1) {
3423 extern unsigned char colorcmd;
3424 colorcmd ^= 0x8 ;
3425 printf("%s\r\n",s);
3426 colorcmd ^= 0x8 ;
3427 }
3428 if (!scrninitialized[VTERM]) {
3429 USHORT x,y;
3430 checkscreenmode();
3431 GetCurPos(&y, &x);
3432 SaveCmdMode(x+1,y+1);
3433 scrninit();
3434 RestoreCmdMode();
3435 }
3436
3437 if ( ISVTNT(tt_type_mode) && ttnum != -1 && !debses )
3438 return;
3439
3440 RequestVscrnMutex( VTERM, SEM_INDEFINITE_WAIT ) ;
3441
3442 os2bold(); /* Toggle boldness */
3443 while (*p)
3444 cwrite((CHAR) *p++); /* Go boldly ... */
3445 os2bold(); /* Toggle boldness back */
3446 if (debses) {
3447 debses = 0;
3448 cwrite((CHAR) '\015');
3449 cwrite((CHAR) '\012');
3450 debses = 1;
3451 } else {
3452 cwrite((CHAR) '\015');
3453 cwrite((CHAR) '\012');
3454 }
3455 ReleaseVscrnMutex(VTERM) ;
3456 #else
3457 if (what != W_CONNECT && what != W_DIALING &&
3458 what != W_COMMAND && what != W_NOTHING)
3459 return; /* CONNECT/command must be active */
3460 conoll(s);
3461 #endif /* OS2 */
3462 #endif /* NOLOCAL */
3463 }
3464
3465 /*
3466 Process in-band Telnet negotiation characters from the remote host.
3467 Call with the telnet IAC character and the current duplex setting
3468 (0 = remote echo, 1 = local echo), and a pointer to a function to call
3469 to read more characters. Returns:
3470 6 if DO LOGOUT was received and accepted
3471 5 if the Kermit start of packet character has changed
3472 4 if state of remote Internet Kermit Service has changed
3473 3 if a quoted IAC was received
3474 2 if local echo must be changed to remote
3475 1 if remote echo must be changed to local
3476 0 if nothing happens or no action necessary
3477 -1 on failure (= internal or i/o error)
3478 */
3479 #ifdef IKS_OPTION
3480 int
tn_siks(cmd)3481 tn_siks(cmd) int cmd; { /* TELNET SEND IKS SUB */
3482 CHAR buf[8];
3483 #ifndef NOXFER
3484 extern CHAR mystch; /* Outgoing Start of Packet Char */
3485 #else
3486 CHAR mystch = '\1';
3487 #endif /* NOXFER */
3488 int n,m,rc;
3489
3490 if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
3491 if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
3492
3493 if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
3494 return(-1);
3495
3496 #ifdef CK_SSL
3497 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
3498 return(0);
3499 }
3500 #endif /* CK_SSL */
3501 if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
3502 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
3503 } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
3504 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3505 } else if (cmd == KERMIT_REQ_STOP)
3506 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
3507 else if (cmd == KERMIT_REQ_START)
3508 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
3509
3510 if (cmd == KERMIT_SOP) {
3511 buf[0] = (CHAR) IAC;
3512 buf[1] = (CHAR) SB;
3513 buf[2] = (CHAR) TELOPT_KERMIT;
3514 buf[3] = (CHAR) (cmd & 0xff);
3515 buf[4] = (CHAR) mystch;
3516 buf[5] = (CHAR) IAC;
3517 buf[6] = (CHAR) SE;
3518 buf[7] = (CHAR) 0;
3519 #ifdef DEBUG
3520 if (tn_deb || debses || deblog)
3521 ckmakmsg( tn_msg_out,TN_MSG_LEN,"TELNET SENT SB KERMIT SOP ",
3522 ckctox(mystch,1)," IAC SE",NULL);
3523 #endif /* DEBUG */
3524 #ifdef OS2
3525 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3526 #endif
3527 #ifdef DEBUG
3528 debug(F101,tn_msg_out,"",cmd);
3529 if (tn_deb || debses) tn_debug(tn_msg_out);
3530 #endif /* DEBUG */
3531 rc = ( ttol(buf,7) < 7 ); /* Send it. */
3532 #ifdef OS2
3533 ReleaseTelnetMutex();
3534 #endif
3535 if (rc)
3536 return(-1);
3537 } else {
3538 buf[0] = (CHAR) IAC;
3539 buf[1] = (CHAR) SB;
3540 buf[2] = (CHAR) TELOPT_KERMIT;
3541 buf[3] = (CHAR) (cmd & 0xff);
3542 buf[4] = (CHAR) IAC;
3543 buf[5] = (CHAR) SE;
3544 buf[6] = (CHAR) 0;
3545
3546 #ifdef DEBUG
3547 if (tn_deb || debses || deblog) {
3548 char * s = 0;
3549 switch (cmd) {
3550 case KERMIT_START: s = "START"; break;
3551 case KERMIT_STOP: s = "STOP"; break;
3552 case KERMIT_REQ_START: s = "REQ-START"; break;
3553 case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
3554 case KERMIT_RESP_START: s = "RESP-START"; break;
3555 case KERMIT_RESP_STOP: s = "RESP-STOP"; break;
3556 }
3557 ckmakmsg( tn_msg_out,TN_MSG_LEN,
3558 "TELNET SENT SB kermit ",s," IAC SE",NULL);
3559 }
3560 #endif /* DEBUG */
3561 #ifdef OS2
3562 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3563 #endif
3564 #ifdef DEBUG
3565 debug(F101,tn_msg_out,"",cmd);
3566 if (tn_deb || debses) tn_debug(tn_msg_out);
3567 #endif /* DEBUG */
3568 rc = ( ttol(buf,6) < 6 ); /* Send it. */
3569 #ifdef OS2
3570 ReleaseTelnetMutex();
3571 #endif
3572 if (rc)
3573 return(-1);
3574 }
3575 return(1);
3576 }
3577 #endif /* IKS_OPTION */
3578
3579 /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
3580 /* returns <= 0 on error, 1 on success */
3581 /* the length returned includes the IAC SE bytes */
3582
3583 int
3584 #ifdef CK_ANSIC /* TELNET SB */
tn_sb(int opt,int * len,int (* fn)(int))3585 tn_sb( int opt, int * len, int (*fn)(int) )
3586 #else
3587 tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
3588 #endif /* CK_ANSIC */
3589 /* tn_sb */ {
3590 int c, x, y, n, m, flag;
3591 /* if (!IS_TELNET()) return(1); */
3592
3593 debug(F100,"Entering tn_sb()","",0);
3594 *len = 0; /* Initialize Len to 0 */
3595 n = flag = 0; /* Flag for when done reading SB */
3596 while (n < TSBUFSIZ) { /* Loop looking for IAC SE */
3597 if ((y = (*fn)(0)) < 0) /* Read a byte */
3598 return(y);
3599 y &= 0xff; /* Make sure it's just 8 bits. */
3600 sb[n++] = (char) y; /* Deposit in buffer. */
3601 if (seslog && sessft == XYFT_D) { /* Take care of session log */
3602 logchar((char) y);
3603 }
3604 if (y == IAC) { /* If this is an IAC */
3605 if (flag) { /* If previous char was IAC */
3606 n--; /* it's quoted, keep one IAC */
3607 flag = 0; /* and turn off the flag. */
3608 } else flag = 1; /* Otherwise set the flag. */
3609 } else if (flag) { /* Something else following IAC */
3610 if (y == SE) /* If not SE, it's a protocol error */
3611 break;
3612 else if (y == DONT) { /* Used DONT instead of SE */
3613 debug(F100,
3614 "TELNET Subnegotiation error - used DONT instead of SE!",
3615 ""
3616 ,0
3617 );
3618 if (tn_deb || debses)
3619 tn_debug(
3620 "TELNET Subnegotiation error - used DONT instead of SE!");
3621 flag = 3;
3622 break;
3623 } else { /* Other protocol error */
3624 flag = 0;
3625 break;
3626 }
3627 }
3628
3629 #ifdef CK_FORWARD_X
3630 if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
3631 n >= (TSBUFSIZ-4) && !flag ) {
3632 /* do not let the buffer over flow */
3633 /* write the data to the channel and continue processing */
3634 /* the incoming data until IAC SE is reached. */
3635 sb[n++] = IAC;
3636 sb[n++] = SE;
3637
3638 #ifdef DEBUG
3639 if ( deblog || tn_deb || debses ) {
3640 int i;
3641 ckmakmsg( tn_msg,TN_MSG_LEN,
3642 "TELNET RCVD SB ",TELOPT(opt),
3643 " DATA(buffer-full) ",NULL);
3644 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[1],n-3);
3645 if (flag == 2)
3646 ckstrncat(tn_msg," SE",TN_MSG_LEN);
3647 else if (flag == 3)
3648 ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
3649 else
3650 ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
3651 debug(F100,tn_msg,"",0);
3652 if (tn_deb || debses)
3653 tn_debug(tn_msg);
3654 }
3655 #endif /* DEBUG */
3656
3657 if ( fwdx_tn_sb(sb,n) < 0 ) {
3658 debug(F100,"fxdx_tn_sb() failed","",0);
3659 /* We can't return though because that would leave */
3660 /* data to be forwarded in the queue to the be sent */
3661 /* to the terminal emulator. */
3662 }
3663 /* reset leave the msg type and channel number in place */
3664 n = 3;
3665 }
3666 #endif /* CK_FORWARD_X */
3667 }
3668 debug(F111,"tn_sb end of while loop","flag",flag);
3669 if (!flag) { /* Make sure we got a valid SB */
3670 debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
3671 if (tn_deb || debses) {
3672 ckmakmsg( tn_msg, TN_MSG_LEN,
3673 "TELNET ", TELOPT(opt),
3674 " Subnegotiation prematurely broken",NULL
3675 );
3676
3677 tn_debug(tn_msg);
3678 }
3679 /* Was -1 but that would be an I/O error, so absorb it and go on. */
3680 return(0);
3681 }
3682 #ifdef DEBUG
3683 if (deblog || tn_deb || debses) {
3684 int i;
3685 char * s[16];
3686 for (i = 0; i < 16; i++)
3687 s[i] = "";
3688 if (opt == TELOPT_NAWS) {
3689 i = 0;
3690 } else {
3691 i = 1;
3692 s[0] = "UNKNOWN";
3693
3694 switch (sb[0]) {
3695 case 0:
3696 if (opt == TELOPT_FORWARD_X)
3697 s[0] = "SCREEN";
3698 else if (opt == TELOPT_KERMIT)
3699 s[0] = "START";
3700 else if (opt == TELOPT_LFLOW)
3701 s[0] = "OFF";
3702 else if (opt == TELOPT_COMPORT)
3703 s[0] = "SIGNATURE";
3704 else
3705 s[0] = "IS";
3706 if (opt == TELOPT_ENCRYPTION) {
3707 i++;
3708 if (sb[1] < ENCTYPE_CNT) {
3709 s[1] = enctype_names[sb[1]];
3710 i++;
3711 switch(sb[2]) {
3712 case 1:
3713 s[2] = "FB64_IV";
3714 break;
3715 case 2:
3716 s[2] = "FB64_IV_OK";
3717 break;
3718 case 3:
3719 s[2] = "FB64_IV_BAD";
3720 break;
3721 case 4:
3722 s[2] = "FB64_CHALLENGE";
3723 break;
3724 case 5:
3725 s[2] = "FB64_RESPONSE";
3726 break;
3727 }
3728 } else {
3729 s[1] = "UNKNOWN";
3730 }
3731 }
3732 if (opt == TELOPT_AUTHENTICATION) {
3733 i += 2;
3734 s[1] = AUTHTYPE_NAME(sb[1]);
3735 s[2] = AUTHMODE_NAME(sb[2]);
3736 if (sb[1]) {
3737 i++;
3738 switch (sb[3]) {
3739 case 0:
3740 switch (sb[1]) {
3741 case AUTHTYPE_NTLM:
3742 s[3] = "NTLM_AUTH";
3743 break;
3744 default:
3745 s[3] = "AUTH";
3746 }
3747 break;
3748 case 1:
3749 switch (sb[1]) {
3750 case AUTHTYPE_SSL:
3751 s[3] = "START";
3752 break;
3753 case AUTHTYPE_NTLM:
3754 s[3] = "NTLM_CHALLENGE";
3755 break;
3756 default:
3757 s[3] = "REJECT";
3758 }
3759 break;
3760 case 2:
3761 switch (sb[1]) {
3762 case AUTHTYPE_NTLM:
3763 s[3] = "NTLM_RESPONSE";
3764 break;
3765 default:
3766 s[3] = "ACCEPT";
3767 }
3768 break;
3769 case 3:
3770 switch (sb[1]) {
3771 case AUTHTYPE_NTLM:
3772 s[3] = "NTLM_ACCEPT";
3773 break;
3774 case 1: /* KERBEROS_v4 */
3775 case 5: /* SRP */
3776 s[3] = "CHALLENGE";
3777 break;
3778 case 2: /* KERBEROS_v5 */
3779 s[3] = "RESPONSE";
3780 break;
3781 case AUTHTYPE_SSL:
3782 s[3] = "REJECT";
3783 break;
3784 }
3785 break;
3786 case 4:
3787 switch (sb[1]) {
3788 case AUTHTYPE_NTLM:
3789 s[3] = "NTLM_REJECT";
3790 break;
3791 case 1: /* KERBEROS_V4 */
3792 case 5: /* SRP */
3793 s[3] = "RESPONSE";
3794 break;
3795 case 2: /* KERBEROS_V5 */
3796 s[3] = "FORWARD";
3797 break;
3798 }
3799 break;
3800 case 5:
3801 switch (sb[1]) {
3802 case 5: /* SRP */
3803 s[3] = "FORWARD";
3804 break;
3805 case 2: /* KERBEROS_V5 */
3806 s[3] = "FORWARD_ACCEPT";
3807 break;
3808 }
3809 break;
3810 case 6:
3811 switch (sb[1]) {
3812 case 5: /* SRP */
3813 s[3] = "FORWARD_ACCEPT";
3814 break;
3815 case 2: /* KERBEROS_V5 */
3816 s[3] = "FORWARD_REJECT";
3817 break;
3818 }
3819 break;
3820 case 7:
3821 switch (sb[1]) {
3822 case 5: /* SRP */
3823 s[3] = "FORWARD_REJECT";
3824 break;
3825 case 2: /* KERBEROS_V5 */
3826 s[3] = "TLS_VERIFY";
3827 break;
3828 }
3829 break;
3830 case 8:
3831 switch (sb[1]) {
3832 case 5: /* SRP */
3833 s[3] = "EXP";
3834 break;
3835 }
3836 break;
3837 case 9:
3838 switch (sb[1]) {
3839 case 5: /* SRP */
3840 s[3] = "PARAMS";
3841 break;
3842 }
3843 break;
3844 }
3845 }
3846 }
3847 break;
3848 case 1:
3849 switch (opt) {
3850 case TELOPT_FORWARD_X:
3851 s[0] = "OPEN";
3852 break;
3853 case TELOPT_LFLOW:
3854 s[0] = "ON";
3855 break;
3856 case TELOPT_KERMIT:
3857 s[0] = "STOP";
3858 break;
3859 case TELOPT_COMPORT:
3860 s[0] = "SET-BAUDRATE";
3861 break;
3862 case TELOPT_AUTHENTICATION:
3863 s[0] = "SEND";
3864 hexbuf[0] = '\0';
3865 for (; i < n-2; i += 2) {
3866 if ( AUTHTYPE_NAME_OK(sb[i]) &&
3867 AUTHMODE_NAME_OK(sb[i]))
3868 ckmakmsg( tn_msg, TN_MSG_LEN,
3869 AUTHTYPE_NAME(sb[i])," ",
3870 AUTHMODE_NAME(sb[i+1])," "
3871 );
3872 else
3873 ckmakxmsg(tn_msg, TN_MSG_LEN,
3874 AUTHTYPE_NAME(sb[i]),
3875 "=",
3876 ckitoa(sb[i]),
3877 " ",
3878 AUTHMODE_NAME(sb[i+1]),
3879 "=",
3880 ckitoa(sb[i+1]),
3881 " ",
3882 NULL,NULL,NULL,NULL
3883 );
3884 ckstrncat(hexbuf,tn_msg,sizeof(hexbuf));
3885 }
3886 s[1] = hexbuf;
3887 break;
3888
3889 case TELOPT_ENCRYPTION:
3890 s[0] = "SUPPORT";
3891 while (i < n-2) {
3892 s[i] = enctype_names[sb[i]];
3893 i++;
3894 }
3895 break;
3896
3897 case TELOPT_START_TLS:
3898 s[0] = "FOLLOWS";
3899 break;
3900 default:
3901 s[0] = "SEND";
3902 }
3903 break;
3904
3905 case 2:
3906 switch (opt) {
3907 case TELOPT_FORWARD_X:
3908 s[0] = "CLOSE";
3909 break;
3910 case TELOPT_LFLOW:
3911 s[0] = "RESTART-ANY";
3912 break;
3913 case TELOPT_KERMIT:
3914 s[0] = "REQ-START";
3915 break;
3916 case TELOPT_COMPORT:
3917 s[0] = "SET-DATASIZE";
3918 break;
3919 case TELOPT_NEWENVIRON:
3920 s[0] = "INFO";
3921 break;
3922 case TELOPT_AUTHENTICATION:
3923 s[0] = "REPLY";
3924 i=4;
3925 s[1] = AUTHTYPE_NAME(sb[1]);
3926 s[2] = AUTHMODE_NAME(sb[2]);
3927 switch (sb[3]) {
3928 case 0:
3929 switch (sb[1]) {
3930 case AUTHTYPE_NTLM:
3931 s[3] = "NTLM_AUTH";
3932 break;
3933 default:
3934 s[3] = "AUTH";
3935 }
3936 break;
3937 case 1:
3938 switch (sb[1]) {
3939 case AUTHTYPE_NTLM:
3940 s[3] = "NTLM_CHALLENGE";
3941 break;
3942 default:
3943 s[3] = "REJECT";
3944 }
3945 break;
3946 case 2:
3947 switch (sb[1]) {
3948 case AUTHTYPE_NTLM:
3949 s[3] = "NTLM_RESPONSE";
3950 break;
3951 default:
3952 s[3] = "ACCEPT";
3953 }
3954 break;
3955 case 3:
3956 switch (sb[1]) {
3957 case AUTHTYPE_NTLM:
3958 s[3] = "NTLM_ACCEPT";
3959 break;
3960 case AUTHTYPE_KERBEROS_V4:
3961 case AUTHTYPE_SRP:
3962 s[3] = "CHALLENGE";
3963 break;
3964 case AUTHTYPE_KERBEROS_V5:
3965 s[3] = "RESPONSE";
3966 break;
3967 }
3968 break;
3969 case 4:
3970 switch (sb[1]) {
3971 case AUTHTYPE_NTLM:
3972 s[3] = "NTLM_REJECT";
3973 break;
3974 case AUTHTYPE_KERBEROS_V4:
3975 case AUTHTYPE_SRP:
3976 s[3] = "RESPONSE";
3977 break;
3978 case AUTHTYPE_KERBEROS_V5:
3979 s[3] = "FORWARD";
3980 break;
3981 }
3982 break;
3983 case 5:
3984 switch (sb[1]) {
3985 case AUTHTYPE_SRP:
3986 s[3] = "FORWARD";
3987 break;
3988 case AUTHTYPE_KERBEROS_V5:
3989 s[3] = "FORWARD_ACCEPT";
3990 break;
3991 }
3992 break;
3993 case 6:
3994 switch (sb[1]) {
3995 case AUTHTYPE_SRP:
3996 s[3] = "FORWARD_ACCEPT";
3997 break;
3998 case AUTHTYPE_KERBEROS_V5:
3999 s[3] = "FORWARD_REJECT";
4000 break;
4001 }
4002 break;
4003 case 7:
4004 switch (sb[1]) {
4005 case AUTHTYPE_SRP:
4006 s[3] = "FORWARD_REJECT";
4007 break;
4008 case AUTHTYPE_KERBEROS_V5:
4009 s[3] = "TLS_VERIFY";
4010 break;
4011 }
4012 break;
4013 case 8:
4014 switch (sb[1]) {
4015 case AUTHTYPE_SRP:
4016 s[3] = "EXP";
4017 break;
4018 }
4019 break;
4020 case 9:
4021 switch (sb[1]) {
4022 case AUTHTYPE_SRP:
4023 s[3] = "PARAMS";
4024 break;
4025 }
4026 break;
4027 }
4028 break;
4029 case TELOPT_ENCRYPTION:
4030 s[0] = "REPLY";
4031 s[1] = enctype_names[sb[1]];
4032 i++;
4033 switch (sb[2]) {
4034 case 1:
4035 i++;
4036 s[2] = "FB64_IV";
4037 break;
4038 case 2:
4039 i++;
4040 s[2] = "FB64_IV_OK";
4041 break;
4042 case 3:
4043 i++;
4044 s[2] = "FB64_IV_BAD";
4045 break;
4046 case 4:
4047 i++;
4048 s[2] = "FB64_CHALLENGE";
4049 break;
4050 case 5:
4051 i++;
4052 s[2] = "FB64_RESPONSE";
4053 break;
4054 }
4055 break;
4056 }
4057 break;
4058 case 3:
4059 switch (opt) {
4060 case TELOPT_FORWARD_X:
4061 s[0] = "DATA";
4062 break;
4063 case TELOPT_LFLOW:
4064 s[0] = "RESTART-XON";
4065 break;
4066 case TELOPT_KERMIT:
4067 s[0] = "REQ-STOP";
4068 break;
4069 case TELOPT_COMPORT:
4070 s[0] = "SET-PARITY";
4071 break;
4072 case TELOPT_AUTHENTICATION:
4073 s[0] = "NAME";
4074 break;
4075 case TELOPT_ENCRYPTION:
4076 s[0] = "START";
4077 break;
4078 }
4079 break;
4080 case 4:
4081 switch (opt) {
4082 case TELOPT_FORWARD_X:
4083 s[0] = "OPTIONS";
4084 break;
4085 case TELOPT_KERMIT:
4086 s[0] = "SOP";
4087 break;
4088 case TELOPT_COMPORT:
4089 s[0] = "SET-STOPSIZE";
4090 break;
4091 case TELOPT_ENCRYPTION:
4092 s[0] = "END";
4093 break;
4094 }
4095 break;
4096 case 5:
4097 switch (opt) {
4098 case TELOPT_FORWARD_X:
4099 s[0] = "OPTION_DATA";
4100 break;
4101 case TELOPT_ENCRYPTION:
4102 s[0] = "REQUEST-START";
4103 break;
4104 case TELOPT_COMPORT:
4105 s[0] = "SET-CONTROL";
4106 break;
4107 }
4108 break;
4109 case 6:
4110 switch (opt) {
4111 case TELOPT_FORWARD_X:
4112 s[0] = "XOFF";
4113 break;
4114 case TELOPT_ENCRYPTION:
4115 s[0] = "REQUEST-END";
4116 break;
4117 case TELOPT_COMPORT:
4118 s[0] = "NOTIFY-LINESTATE";
4119 break;
4120 }
4121 break;
4122 case 7:
4123 switch (opt) {
4124 case TELOPT_FORWARD_X:
4125 s[0] = "XON";
4126 break;
4127 case TELOPT_ENCRYPTION:
4128 s[0] = "ENC-KEYID";
4129 break;
4130 case TELOPT_COMPORT:
4131 s[0] = "NOTIFY-MODEMSTATE";
4132 break;
4133 }
4134 break;
4135 case 8:
4136 switch (opt) {
4137 case TELOPT_KERMIT:
4138 s[0] = "RESP-START";
4139 break;
4140 case TELOPT_ENCRYPTION:
4141 s[0] = "DEC-KEYID";
4142 break;
4143 case TELOPT_COMPORT:
4144 s[0] = "FLOWCONTROL-SUSPEND";
4145 break;
4146 }
4147 break;
4148 case 9:
4149 switch (opt) {
4150 case TELOPT_KERMIT:
4151 s[0] = "RESP-STOP";
4152 break;
4153 case TELOPT_COMPORT:
4154 s[0] = "FLOWCONTROL-RESUME";
4155 break;
4156 }
4157 break;
4158 case 10:
4159 switch (opt) {
4160 case TELOPT_COMPORT:
4161 s[0] = "SET-LINESTATE-MASK";
4162 break;
4163 }
4164 break;
4165 case 11:
4166 switch (opt) {
4167 case TELOPT_COMPORT:
4168 s[0] = "SET-MODEMSTATE-MASK";
4169 break;
4170 }
4171 break;
4172 case 12:
4173 switch (opt) {
4174 case TELOPT_COMPORT:
4175 s[0] = "PURGE-DATA";
4176 break;
4177 }
4178 break;
4179
4180
4181 case 100:
4182 switch (opt) {
4183 case TELOPT_COMPORT:
4184 s[0] = "S_SIGNATURE";
4185 break;
4186 }
4187 break;
4188 case 101:
4189 switch (opt) {
4190 case TELOPT_COMPORT:
4191 s[0] = "S_SET-BAUDRATE";
4192 break;
4193 }
4194 break;
4195 case 102:
4196 switch (opt) {
4197 case TELOPT_COMPORT:
4198 s[0] = "S_SET-DATASIZE";
4199 break;
4200 }
4201 break;
4202 case 103:
4203 switch (opt) {
4204 case TELOPT_COMPORT:
4205 s[0] = "S_SET-PARITY";
4206 break;
4207 }
4208 break;
4209 case 104:
4210 switch (opt) {
4211 case TELOPT_COMPORT:
4212 s[0] = "S_SET-STOPSIZE";
4213 break;
4214 }
4215 break;
4216 case 105:
4217 switch (opt) {
4218 case TELOPT_COMPORT:
4219 s[0] = "S_SET-CONTROL";
4220 break;
4221 }
4222 break;
4223 case 106:
4224 switch (opt) {
4225 case TELOPT_COMPORT:
4226 s[0] = "S_NOTIFY-LINESTATE";
4227 break;
4228 }
4229 break;
4230 case 107:
4231 switch (opt) {
4232 case TELOPT_COMPORT:
4233 s[0] = "S_NOTIFY-MODEMSTATE";
4234 break;
4235 }
4236 break;
4237 case 108:
4238 switch (opt) {
4239 case TELOPT_COMPORT:
4240 s[0] = "S_FLOWCONTROL-SUSPEND";
4241 break;
4242 }
4243 break;
4244 case 109:
4245 switch (opt) {
4246 case TELOPT_COMPORT:
4247 s[0] = "S_FLOWCONTROL-RESUME";
4248 break;
4249 }
4250 break;
4251 case 110:
4252 switch (opt) {
4253 case TELOPT_COMPORT:
4254 s[0] = "S_SET-LINESTATE-MASK";
4255 break;
4256 }
4257 break;
4258 case 111:
4259 switch (opt) {
4260 case TELOPT_COMPORT:
4261 s[0] = "S_SET-MODEMSTATE-MASK";
4262 break;
4263 }
4264 break;
4265 case 112:
4266 switch (opt) {
4267 case TELOPT_COMPORT:
4268 s[0] = "S_PURGE-DATA";
4269 break;
4270 }
4271 break;
4272 }
4273 }
4274 #ifdef M_XENIX
4275 {
4276 int len, param, param_len;
4277 ckmakmsg( tn_msg, TN_MSG_LEN,
4278 "TELNET RCVD SB ",
4279 TELOPT(opt)," ",NULL);
4280 len = strlen(tn_msg);
4281 for (param = 0; param <= 15; param++) {
4282 param_len = strlen(s[param]);
4283 if (param_len > 0) {
4284 strcpy(&tn_msg[len], s[param]);
4285 len += param_len;
4286 tn_msg[len++] = ' ';
4287 }
4288 }
4289 tn_msg[len] = '\0';
4290 }
4291 #else /* M_XENIX */
4292 ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD SB ",TELOPT(opt)," ",
4293 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
4294 {
4295 int i;
4296 for (i = 0; i < 16; i++) {
4297 if (s[i][0]) {
4298 ckstrncat(tn_msg,s[i],TN_MSG_LEN);
4299 ckstrncat(tn_msg," ",TN_MSG_LEN);
4300 }
4301 }
4302 }
4303 #endif /* M_XENIX */
4304 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[i],n-2-i);
4305 if (flag == 2)
4306 ckstrncat(tn_msg," SE",TN_MSG_LEN);
4307 else if (flag == 3)
4308 ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
4309 else
4310 ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
4311 debug(F100,tn_msg,"",0);
4312 if (tn_deb || debses)
4313 tn_debug(tn_msg);
4314 }
4315 debug(F111,"tn_sb","len",n);
4316 #endif /* DEBUG */
4317 *len = n; /* return length */
4318 return(1); /* success */
4319 }
4320
4321 static char rows_buf[16] = { 0, 0 }; /* LINES Environment variable */
4322 static char cols_buf[16] = { 0, 0 }; /* COLUMNS Enviornment variable */
4323 static char term_buf[64] = { 0, 0 }; /* TERM Environment variable */
4324
4325 #ifdef CK_CURSES
4326 #ifndef VMS
4327 #ifndef COHERENT
4328 _PROTOTYP(int tgetent,(char *, char *));
4329 #endif /* COHERENT */
4330 #else
4331 #ifdef __DECC
4332 _PROTOTYP(int tgetent,(char *, char *));
4333 #endif /* __DECC */
4334 #endif /* VMS */
4335 extern char * trmbuf; /* Real curses */
4336 #endif /* CK_CURSES */
4337
4338 #ifdef CK_ENCRYPTION
4339 static int
tn_no_encrypt()4340 tn_no_encrypt()
4341 {
4342 /* Prevent Encryption from being negotiated */
4343 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
4344 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
4345
4346 /* Cancel any negotiation that might have started */
4347 ck_tn_enc_stop();
4348
4349 if (TELOPT_ME(TELOPT_ENCRYPTION) ||
4350 TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION)) {
4351 TELOPT_ME(TELOPT_ENCRYPTION) = 0;
4352 if (tn_sopt(WONT,TELOPT_ENCRYPTION) < 0)
4353 return(-1);
4354 TELOPT_UNANSWERED_WONT(TELOPT_ENCRYPTION) = 1;
4355 }
4356 if (TELOPT_U(TELOPT_ENCRYPTION) ||
4357 TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION)) {
4358 TELOPT_U(TELOPT_ENCRYPTION) = 0;
4359 if (tn_sopt(DONT,TELOPT_ENCRYPTION) < 0)
4360 return(-1);
4361 TELOPT_UNANSWERED_DONT(TELOPT_ENCRYPTION) = 1;
4362 }
4363 return(0);
4364 }
4365 #endif /* CK_ENCRYPTION */
4366
4367 /* The following note came from the old SGA negotiation code. This should */
4368 /* no longer be necessary with the New Telnet negotiation state machine. */
4369 /*
4370 Note: The following is proper behavior, and required for talking to the
4371 Apertus interface to the NOTIS library system, e.g. at Iowa State U:
4372 scholar.iastate.edu. Without this reply, the server hangs forever. This
4373 code should not be loop-inducing, since C-Kermit never sends WILL SGA as
4374 an initial bid, so if DO SGA comes, it is never an ACK.
4375 */
4376 /*
4377 Return values:
4378 -1 = Telnet Option negotiation error
4379 -2 = Connection closed by peer
4380 -3 = Connection closed by us
4381 0 = Success
4382 1 = Echoing on
4383 2 = Echoing off
4384 3 = Quoted IAC
4385 4 = IKS Event
4386 5 = (unassigned)
4387 6 = Logout
4388 */
4389
4390 static int
4391 #ifdef CK_ANSIC /* TELNET DO OPTION */
tn_xdoop(CHAR z,int echo,int (* fn)(int))4392 tn_xdoop(CHAR z, int echo, int (*fn)(int))
4393 #else
4394 tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
4395 #endif /* CK_ANSIC */
4396 /* tn_xdoop */ {
4397 int c, x, y, n, m;
4398 #ifdef IKS_OPTION
4399 extern int server;
4400 #ifdef NOICP
4401 extern int autodl;
4402 int inautodl = 0, cmdadl = 1;
4403 #else
4404 #ifdef CK_AUTODL
4405 extern int autodl, inautodl, cmdadl;
4406 #endif /* CK_AUTODL */
4407 #endif /* NOICP */
4408 #endif /* IKS_OPTION */
4409
4410 /* if (!IS_TELNET()) return(7); */
4411
4412 /* Have IAC, read command character. */
4413
4414 while ((c = (*fn)(0)) == -1); /* Read command character */
4415 if (c < 0)
4416 return(c);
4417 c &= 0xFF; /* Strip high bits */
4418
4419 if (!TELCMD_OK(c)) {
4420 #ifdef DEBUG
4421 if (tn_deb || debses || deblog) {
4422 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD UNKNOWN (",
4423 ckitoa(c),")",NULL);
4424 debug(F101,tn_msg,"",c);
4425 if (tn_deb || debses)
4426 tn_debug(tn_msg);
4427 }
4428 #endif /* DEBUG */
4429 return(0);
4430 }
4431 if (ttnproto == NP_NONE) {
4432 debug(F100,"tn_doop discovered a Telnet command",
4433 "ttnproto = NP_TELNET",0);
4434 ttnproto = NP_TELNET;
4435 }
4436 if (seslog && sessft == XYFT_D) { /* Copy to session log, if any. */
4437 logchar((char)z);
4438 logchar((char)c);
4439 }
4440
4441 if (c == (CHAR) IAC) /* Quoted IAC */
4442 return(3);
4443
4444 if (c < SB) { /* Other command with no arguments. */
4445 #ifdef DEBUG
4446 if (deblog || tn_deb || debses) {
4447 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c),NULL,NULL);
4448 debug(F101,tn_msg,"",c);
4449 if (tn_deb || debses) tn_debug(tn_msg);
4450 }
4451 #endif /* DEBUG */
4452 switch (c) { /* What we would like to do here */
4453 case TN_GA: /* Is substitute ASCII characters */
4454 break; /* for the Telnet Command so that */
4455 case TN_EL: /* the command may be processed by */
4456 break; /* either the internal emulator or */
4457 case TN_EC: /* by the superior process or shell */
4458 break;
4459 case TN_AYT:
4460 #ifdef OS2
4461 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
4462 #endif
4463 ttol((CHAR *)"[Yes]\015\012",7);
4464 #ifdef OS2
4465 ReleaseTelnetMutex();
4466 #endif
4467 break;
4468 case TN_AO:
4469 #ifdef BETADEBUG
4470 bleep(BP_NOTE);
4471 #endif /* BETADEBUG */
4472 break;
4473 case TN_IP:
4474 break;
4475 case BREAK:
4476 break;
4477 case TN_DM:
4478 break;
4479 case TN_NOP:
4480 break;
4481 case SE:
4482 break;
4483 case TN_EOR:
4484 break;
4485 case TN_ABORT:
4486 break;
4487 case TN_SUSP:
4488 break;
4489 case TN_EOF:
4490 break;
4491 case TN_SAK:
4492 break;
4493 }
4494 return(0);
4495 }
4496
4497 /* SB, WILL, WONT, DO, or DONT need more bytes... */
4498
4499 if ((x = (*fn)(0)) < 0) /* Get the option. */
4500 return(x);
4501 x &= 0xff; /* Trim to 8 bits. */
4502
4503 if (seslog && sessft == XYFT_D) { /* Session log */
4504 logchar((char) x);
4505 }
4506 #ifdef DEBUG
4507 if ((deblog || tn_deb || debses) && c != SB) {
4508 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c)," ",TELOPT(x));
4509 debug(F101,tn_msg,"",x);
4510 if (tn_deb || debses) tn_debug(tn_msg);
4511 }
4512 #endif /* DEBUG */
4513 /* Now handle the command */
4514 switch (c) {
4515 case WILL:
4516 #ifdef CK_SSL
4517 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4518 return(0);
4519 #endif /* CK_SSL */
4520 #ifdef CK_FORWARD_X
4521 if (x == TELOPT_FORWARD_X) {
4522 if (!fwdx_server_avail() || !(fwdx_no_encrypt ||
4523 #ifdef CK_SSL
4524 (ssl_active_flag || tls_active_flag)
4525 #else /* CK_SSL */
4526 0
4527 #endif /* CK_SSL */
4528 ||
4529 #ifdef CK_ENCRYPTION
4530 (ck_tn_encrypting() && ck_tn_decrypting())
4531 #else /* CK_ENCRYPTION */
4532 0
4533 #endif /* CK_ENCRYPTION */
4534 )) {
4535 TELOPT_U_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
4536 TELOPT_ME_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
4537 }
4538 }
4539 #endif /* CK_FORWARD_X */
4540 if (!TELOPT_OK(x) || TELOPT_U_MODE(x) == TN_NG_RF) {
4541 if (tn_sopt(DONT,x) < 0)
4542 return(-1);
4543 if (TELOPT_UNANSWERED_DO(x))
4544 TELOPT_UNANSWERED_DO(x) = 0;
4545 } else if (!TELOPT_U(x)) {
4546 if (!TELOPT_UNANSWERED_DO(x)) {
4547 if (tn_sopt(DO,x) < 0)
4548 return -1;
4549 }
4550 if (TELOPT_UNANSWERED_DO(x))
4551 TELOPT_UNANSWERED_DO(x) = 0;
4552 TELOPT_U(x) = 1;
4553
4554 switch (x) {
4555 #ifdef CK_SSL
4556 case TELOPT_START_TLS:
4557 /*
4558 If my proposal is accepted, at this point the Telnet
4559 protocol is turned off and a TLS negotiation takes
4560 place.
4561
4562 Start by sending SB START_TLS FOLLOWS to signal
4563 we are ready. Wait for the peer to send the same
4564 and then start the TLS negotiation.
4565
4566 If the TLS negotiation succeeds we call tn_ini()
4567 again to reset the telnet state machine and restart
4568 the negotiation process over the now secure link.
4569
4570 If the TLS negotiation fails, we call ttclos()
4571 to terminate the connection.
4572
4573 Only the server should receive a WILL START_TLS
4574 */
4575 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
4576 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
4577 break;
4578 #endif /* CK_SSL */
4579
4580 #ifdef CK_AUTHENTICATION
4581 case TELOPT_AUTHENTICATION: {
4582 /* We now have to perform a SB SEND to identify the */
4583 /* supported authentication types to the other side. */
4584 extern int authentication_version;
4585
4586 #ifdef CK_SSL
4587 /* if we have an outstanding DO START_TLS then we must
4588 * wait for the response before we determine what to do
4589 */
4590 if (TELOPT_UNANSWERED_DO(TELOPT_START_TLS)) {
4591 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 1;
4592 break;
4593 }
4594 #endif /* CK_SSL */
4595 authentication_version = AUTHTYPE_AUTO;
4596 ck_tn_auth_request();
4597 break;
4598 }
4599 #endif /* CK_AUTHENTICATION */
4600 #ifdef CK_ENCRYPTION
4601 case TELOPT_ENCRYPTION:
4602 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
4603 TELOPT_U(TELOPT_AUTHENTICATION))
4604 ) {
4605 if (tn_sopt(DONT,x) < 0)
4606 return(-1);
4607 TELOPT_U(x) = 0;
4608 } else {
4609 if (ck_tn_auth_in_progress()) {
4610 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 1;
4611 } else {
4612 /* Perform subnegotiation */
4613 ck_encrypt_send_support();
4614 }
4615 if (!(TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x))
4616 && TELOPT_ME_MODE(x) != TN_NG_RF) {
4617 if (tn_sopt(WILL, x) < 0)
4618 return(-1);
4619 TELOPT_UNANSWERED_WILL(x) = 1;
4620 }
4621 }
4622 break;
4623 #endif /* CK_ENCRYPTION */
4624 #ifdef IKS_OPTION
4625 case TELOPT_KERMIT:
4626 if (!TELOPT_ME(x)) {
4627 /* Tell the other side what Start of Packet Character */
4628 tn_siks(KERMIT_SOP); /* SOP */
4629
4630 if (!TELOPT_UNANSWERED_WILL(x) &&
4631 TELOPT_ME_MODE(x) != TN_NG_RF) {
4632 if (tn_sopt(WILL, x) < 0)
4633 return(-1);
4634 TELOPT_UNANSWERED_WILL(x) = 1;
4635 }
4636 }
4637 break;
4638 #endif /* IKS_OPTION */
4639 case TELOPT_BINARY:
4640 if (!TELOPT_ME(x)) {
4641 if (!TELOPT_UNANSWERED_WILL(x) &&
4642 TELOPT_ME_MODE(x) >= TN_NG_RQ) {
4643 if (tn_sopt(WILL, x) < 0)
4644 return(-1);
4645 TELOPT_UNANSWERED_WILL(x) = 1;
4646 }
4647 }
4648 break;
4649 case TELOPT_ECHO:
4650 if (echo) {
4651 if (TELOPT_UNANSWERED_DO(x))
4652 TELOPT_UNANSWERED_DO(x) = 0;
4653 return(2);
4654 }
4655 break;
4656 case TELOPT_TTYPE:
4657 /* SB TTYPE SEND */
4658 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
4659 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
4660 break;
4661 #ifdef CK_ENVIRONMENT
4662 case TELOPT_NEWENVIRON: /* SB NEW-ENVIRON SEND */
4663 {
4664 char request[6]; /* request it */
4665 sprintf(request,"%cUSER",TEL_ENV_VAR); /* safe */
4666 tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_SEND,request,
4667 strlen(request));
4668 TELOPT_UNANSWERED_SB(TELOPT_NEWENVIRON)=1;
4669 }
4670 break;
4671 #endif /* CK_ENVIRONMENT */
4672 } /* switch */
4673 } else {
4674 if (TELOPT_UNANSWERED_DO(x))
4675 TELOPT_UNANSWERED_DO(x) = 0;
4676 }
4677 break;
4678 case WONT:
4679 #ifdef CK_SSL
4680 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4681 return(0);
4682 #endif /* CK_SSL */
4683 if (TELOPT_U(x) || TELOPT_UNANSWERED_DO(x)) {
4684 /* David Borman says we should not respond DONT when
4685 * the WONT is a response to a DO that we sent.
4686 * Nor should we send one if the state is already WONT
4687 * such as when we do not recognize the option since
4688 * options are initialized in the WONT/DONT state.
4689 */
4690 if (!(TELOPT_UNANSWERED_DO(x) || TELOPT_UNANSWERED_DONT(x)))
4691 if (tn_sopt(DONT,x) < 0)
4692 return(-1);
4693 if (TELOPT_UNANSWERED_DONT(x))
4694 TELOPT_UNANSWERED_DONT(x) = 0;
4695 if (TELOPT_UNANSWERED_DO(x))
4696 TELOPT_UNANSWERED_DO(x) = 0;
4697 if (TELOPT_U(x)) {
4698 TELOPT_U(x) = 0;
4699 }
4700 switch(x) {
4701 #ifdef CK_SSL
4702 case TELOPT_START_TLS:
4703 if (sstelnet) {
4704 if (TELOPT_U_MODE(x) == TN_NG_MU) {
4705 printf("Telnet Start-TLS refused.\n");
4706 ttclos(0);
4707 whyclosed = WC_TELOPT;
4708 return(-3);
4709 }
4710 if (TELOPT_SB(x).start_tls.auth_request) {
4711 extern int authentication_version;
4712 TELOPT_SB(x).start_tls.auth_request = 0;
4713 authentication_version = AUTHTYPE_AUTO;
4714 ck_tn_auth_request();
4715 }
4716 }
4717 break;
4718 #endif /* CK_SSL */
4719 #ifdef CK_AUTHENTICATION
4720 case TELOPT_AUTHENTICATION:
4721 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
4722 printf("Telnet authentication refused.\n");
4723 ttclos(0);
4724 whyclosed = WC_TELOPT;
4725 return(-3);
4726 } else if (TELOPT_U_MODE(x) == TN_NG_RQ) {
4727 TELOPT_U_MODE(x) = TN_NG_AC;
4728 }
4729 if (ck_tn_auth_in_progress())
4730 printf("Telnet authentication refused.\n");
4731 #ifdef CK_ENCRYPTION
4732 if (sstelnet) {
4733 if (tn_no_encrypt()<0)
4734 return(-1);
4735 }
4736 #endif /* CK_ENCRYPTION */
4737 break;
4738 #endif /* CK_AUTHENTICATION */
4739 #ifdef CK_ENCRYPTION
4740 case TELOPT_ENCRYPTION:
4741 ck_tn_enc_stop();
4742 break;
4743 #endif /* CK_ENCRYPTION */
4744 #ifdef IKS_OPTION
4745 case TELOPT_KERMIT:
4746 TELOPT_SB(x).kermit.u_start = 0;
4747 TELOPT_SB(x).kermit.me_req_start = 0;
4748 TELOPT_SB(x).kermit.me_req_stop = 0;
4749 break;
4750 #endif /* IKS_OPTION */
4751 case TELOPT_NAWS: {
4752 /* The client does not support NAWS. */
4753 /* Assume a height of 24 and a width of 80 */
4754 if (sstelnet
4755 #ifdef IKSD
4756 || inserver
4757 #endif /* IKSD */
4758 ) {
4759 int w = 80, h = 24;
4760 #ifndef NOLOCAL
4761 if (tcp_incoming) {
4762 #ifdef OS2
4763 tt_cols[VTERM] = w;
4764 tt_rows[VTERM] = h;
4765 VscrnSetWidth(VTERM, w);
4766 VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
4767 #else /* OS2 */
4768 tt_cols = w;
4769 tt_rows = h;
4770 #endif /* OS2 */
4771 } else {
4772 #ifdef OS2
4773 tt_cols[VCMD] = w;
4774 tt_rows[VCMD] = h;
4775 VscrnSetWidth(VCMD, w);
4776 VscrnSetHeight(VCMD, h);
4777 #endif /* OS2 */
4778 cmd_cols = w;
4779 cmd_rows = h;
4780 }
4781 #else /* NOLOCAL */
4782 cmd_cols = w;
4783 cmd_rows = h;
4784 #endif /* NOLOCAL */
4785 /* Add LINES and COLUMNS to the environment */
4786 ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),
4787 NULL,NULL);
4788 ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),
4789 NULL,NULL);
4790 #ifdef OS2ORUNIX
4791 #ifndef NOPUTENV
4792 putenv(rows_buf);
4793 putenv(cols_buf);
4794 #endif /* NOPUTENV */
4795 #endif /* OS2ORUNIX */
4796 }
4797 break;
4798 }
4799 case TELOPT_ECHO:
4800 if (!echo) {
4801 if (TELOPT_UNANSWERED_DO(x))
4802 TELOPT_UNANSWERED_DO(x) = 0;
4803 return(1);
4804 }
4805 break;
4806 }
4807 } else {
4808 if (TELOPT_UNANSWERED_DONT(x))
4809 TELOPT_UNANSWERED_DONT(x) = 0;
4810 if (TELOPT_UNANSWERED_DO(x))
4811 TELOPT_UNANSWERED_DO(x) = 0;
4812 }
4813 if (TELOPT_U_MODE(x) == TN_NG_MU) {
4814 ckmakmsg( tn_msg,TN_MSG_LEN,
4815 "Peer refuses TELNET DO ",TELOPT(x),
4816 " negotiations - terminating connection",NULL
4817 );
4818 debug(F100,tn_msg,"",0);
4819 if (tn_deb || debses) tn_debug(tn_msg);
4820 printf("%s\n",tn_msg);
4821 ttclos(0);
4822 whyclosed = WC_TELOPT;
4823 return(-3);
4824 }
4825 #ifdef COMMENT
4826 if (x == TELOPT_ECHO && !echo) /* Special handling for echo */
4827 return(1); /* because we allow 'duplex' */
4828 #endif /* COMMENT */
4829 break;
4830
4831 case DO:
4832 #ifdef CK_SSL
4833 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4834 return(0);
4835 #endif /* CK_SSL */
4836 if (!TELOPT_OK(x) || TELOPT_ME_MODE(x) == TN_NG_RF) {
4837 if (tn_sopt(WONT,x) < 0)
4838 return(-1);
4839 if (TELOPT_UNANSWERED_WILL(x))
4840 TELOPT_UNANSWERED_WILL(x) = 0;
4841 } else if (!TELOPT_ME(x)) {
4842 if (!TELOPT_UNANSWERED_WILL(x)) {
4843 if (tn_sopt(WILL,x) < 0)
4844 return(-1);
4845 }
4846 if (TELOPT_UNANSWERED_WILL(x))
4847 TELOPT_UNANSWERED_WILL(x) = 0;
4848 TELOPT_ME(x) = 1;
4849
4850 switch (x) {
4851 #ifdef CK_SSL
4852 case TELOPT_START_TLS:
4853 /*
4854 If my proposal is accepted at this point the Telnet
4855 protocol is turned off and a TLS negotiation takes
4856 place.
4857
4858 Start by sending SB START_TLS FOLLOWS to signal
4859 we are ready. Wait for the peer to send the same
4860 and then start the TLS negotiation.
4861
4862 If the TLS negotiation succeeds we call tn_ini()
4863 again to reset the telnet state machine and restart
4864 the negotiation process over the now secure link.
4865
4866 If the TLS negotiation fails, we call ttclos()
4867 to terminate the connection. Then we set the
4868 U_MODE and ME_MODE for TELOPT_START_TLS to REFUSE
4869 and then call ttopen() to create a new connection
4870 to the same host but this time do not attempt
4871 TLS security.
4872
4873 Only the client should receive DO START_TLS.
4874 */
4875 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
4876 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
4877 break;
4878 #endif /* CK_SSL */
4879
4880 #ifdef CK_AUTHENTICATION
4881 case TELOPT_AUTHENTICATION: {
4882 /* We don't know what authentication we are using yet */
4883 /* but it is not NULL until a failure is detected so */
4884 /* use AUTO in the meantime. */
4885 extern int authentication_version;
4886 authentication_version = AUTHTYPE_AUTO;
4887 break;
4888 }
4889 #endif /* CK_AUTHENTICATION */
4890 #ifdef CK_ENCRYPTION
4891 case TELOPT_ENCRYPTION:
4892 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
4893 TELOPT_U(TELOPT_AUTHENTICATION))
4894 ) {
4895 if (tn_sopt(WONT,x) < 0)
4896 return(-1);
4897 TELOPT_ME(x) = 0;
4898 } else {
4899 if (!(TELOPT_U(x) || TELOPT_UNANSWERED_DO(x))
4900 && TELOPT_U_MODE(x) != TN_NG_RF) {
4901 if (tn_sopt(DO, x) < 0)
4902 return(-1);
4903 TELOPT_UNANSWERED_DO(x) = 1;
4904 }
4905 }
4906 break;
4907 #endif /* CK_ENCRYPTION */
4908 #ifdef IKS_OPTION
4909 case TELOPT_KERMIT:
4910 /* If currently processing Kermit server packets, must tell the other side */
4911
4912 debug(F111,"tn_doop","what",what);
4913 debug(F111,"tn_doop","server",server);
4914 #ifdef CK_AUTODL
4915 debug(F111,"tn_doop","autodl",autodl);
4916 debug(F111,"tn_doop","inautodl",inautodl);
4917 debug(F111,"tn_doop","cmdadl",cmdadl);
4918 #endif /* CK_AUTODL */
4919
4920 if (server
4921 #ifdef CK_AUTODL
4922 || (local && ((what == W_CONNECT && autodl) ||
4923 (what != W_CONNECT && inautodl)))
4924 || (!local && cmdadl)
4925 #endif /* CK_AUTODL */
4926 ) {
4927 tn_siks(KERMIT_START); /* START */
4928 }
4929 if (!TELOPT_U(x)) {
4930 /* Tell the other side what Start of Packet Character */
4931 tn_siks(KERMIT_SOP); /* SOP */
4932 if (!TELOPT_UNANSWERED_DO(x) &&
4933 TELOPT_U_MODE(x) != TN_NG_RF) {
4934 if (tn_sopt(DO, x) < 0)
4935 return(-1);
4936 TELOPT_UNANSWERED_DO(x) = 1;
4937 }
4938 }
4939 break;
4940 #endif /* IKS_OPTION */
4941
4942 case TELOPT_BINARY:
4943 if (!TELOPT_U(x)) {
4944 if (!TELOPT_UNANSWERED_DO(x) &&
4945 TELOPT_U_MODE(x) >= TN_NG_RQ) {
4946 if (tn_sopt(DO, x) < 0)
4947 return(-1);
4948 TELOPT_UNANSWERED_DO(x) = 1;
4949 }
4950 }
4951 break;
4952 case TELOPT_NAWS:
4953 #ifdef CK_NAWS
4954 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4955 if (tn_snaws() < 0)
4956 return(-1);
4957 } else {
4958 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 1;
4959 }
4960 #endif /* CK_NAWS */
4961 break;
4962 case TELOPT_LOGOUT:
4963 ttclos(0); /* And then hangup */
4964 whyclosed = WC_TELOPT;
4965 return(6);
4966 #ifdef CK_SNDLOC
4967 case TELOPT_SNDLOC:
4968 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4969 if (tn_sndloc() < 0)
4970 return(-1);
4971 } else {
4972 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 1;
4973 }
4974 break;
4975 #endif /* CK_SNDLOC */
4976 #ifdef CK_FORWARD_X
4977 case TELOPT_FORWARD_X:
4978 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4979 if (fwdx_send_options() < 0) {
4980 if (tn_sopt(DONT,x) < 0)
4981 return(-1);
4982 TELOPT_UNANSWERED_DONT(x) = 1;
4983 }
4984 } else {
4985 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 1;
4986 }
4987 break;
4988 #endif /* CK_FORWARD_X */
4989 #ifdef TN_COMPORT
4990 case TELOPT_COMPORT: {
4991 extern int reliable;
4992 if (!tn_delay_sb || !tn_outst(0) || tn_init) {
4993 if (tn_sndcomport() < 0)
4994 return(-1);
4995 } else {
4996 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 1;
4997 }
4998 /* Telnet -> Serial -> ??? is not a reliable connection. */
4999 reliable = SET_OFF;
5000 break;
5001 }
5002 #endif /* TN_COMPORT */
5003 } /* switch */
5004 } else {
5005 if (TELOPT_UNANSWERED_WILL(x))
5006 TELOPT_UNANSWERED_WILL(x) = 0;
5007 }
5008 break;
5009
5010 case DONT:
5011 #ifdef CK_SSL
5012 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
5013 return(0);
5014 #endif /* CK_SSL */
5015 if (TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x)) {
5016 /* David Borman says we should not respond WONT when
5017 * the DONT is a response to a WILL that we sent.
5018 * Nor should we send one if the state is already WONT
5019 * such as when we do not recognize the option since
5020 * options are initialized in the WONT/DONT state.
5021 */
5022 if (!(TELOPT_UNANSWERED_WILL(x) || TELOPT_UNANSWERED_WONT(x)))
5023 if (tn_sopt(WONT,x) < 0)
5024 return(-1);
5025
5026 if (TELOPT_UNANSWERED_WILL(x))
5027 TELOPT_UNANSWERED_WILL(x) = 0;
5028 if (TELOPT_UNANSWERED_WONT(x))
5029 TELOPT_UNANSWERED_WONT(x) = 0;
5030 if (TELOPT_ME(x))
5031 TELOPT_ME(x) = 0;
5032
5033 switch (x) {
5034 #ifdef CK_SSL
5035 case TELOPT_START_TLS:
5036 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5037 printf("Telnet Start-TLS refused.\n");
5038 ttclos(0);
5039 whyclosed = WC_TELOPT;
5040 return(-3);
5041 }
5042 break;
5043 #endif /* CK_SSL */
5044 #ifdef CK_AUTHENTICATION
5045 case TELOPT_AUTHENTICATION:
5046 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5047 #ifdef CK_SSL
5048 if (tls_active_flag) {
5049 TELOPT_ME_MODE(x) = TN_NG_AC;
5050 break;
5051 } else
5052 #endif /* CK_SSL */
5053 {
5054 printf("Telnet authentication refused.\n");
5055 ttclos(0);
5056 whyclosed = WC_TELOPT;
5057 return(-3);
5058 }
5059 } else if (TELOPT_ME_MODE(x) == TN_NG_RQ) {
5060 TELOPT_ME_MODE(x) = TN_NG_AC;
5061 }
5062 if (ck_tn_auth_in_progress())
5063 printf("Telnet authentication refused.\n");
5064 #ifdef CK_ENCRYPTION
5065 if (!sstelnet) {
5066 if (tn_no_encrypt()<0)
5067 return(-1);
5068 }
5069 #endif /* CK_ENCRYPTION */
5070 break;
5071 #endif /* CK_AUTHENTICATION */
5072 case TELOPT_ENCRYPTION:
5073 #ifdef CK_ENCRYPTION
5074 ck_tn_enc_stop();
5075 #endif /* CK_ENCRYPTION */
5076 break;
5077 case TELOPT_KERMIT:
5078 #ifdef IKS_OPTION
5079 TELOPT_SB(x).kermit.me_start = 0;
5080 /* Begin section added 2013-04-12 */
5081 /*
5082 The idea here is to nullify any outstanding Telnet Kermit subnegotiations.
5083 The first three should do the trick, but they don't.
5084 Setting TELOPT_U(TELOPT_KERMIT) to 0, however, does.
5085 TELOPT_ME(TELOPT_KERMIT) = 0;
5086 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
5087 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
5088 */
5089 TELOPT_U(TELOPT_KERMIT) = 0;
5090 /* End section added 2013-04-12 */
5091 #endif /* IKS_OPTION */
5092 break;
5093 default:
5094 break;
5095 } /* switch */
5096 } else {
5097 if (TELOPT_UNANSWERED_WILL(x))
5098 TELOPT_UNANSWERED_WILL(x) = 0;
5099 if (TELOPT_UNANSWERED_WONT(x))
5100 TELOPT_UNANSWERED_WONT(x) = 0;
5101 }
5102 if (TELOPT_ME_MODE(x) == TN_NG_MU) {
5103 ckmakmsg( tn_msg,TN_MSG_LEN,
5104 "Peer refuses TELNET WILL ",TELOPT(x),
5105 " negotiations - terminating connection",
5106 NULL
5107 );
5108 debug(F100,tn_msg,"",0);
5109 if (tn_deb || debses) tn_debug(tn_msg);
5110 printf("%s\n",tn_msg);
5111 ttclos(0);
5112 whyclosed = WC_TELOPT;
5113 return(-3);
5114 }
5115 break;
5116 case SB:
5117 if ((y = tn_sb(x,&n,fn)) <= 0)
5118 return(y);
5119
5120 #ifdef CK_SSL
5121 /* Do not process subnegotiations other than START_TLS after we */
5122 /* have agreed to begin the TLS negotiation sequence. */
5123 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows &&
5124 x != TELOPT_START_TLS)
5125 break;
5126 #endif /* CK_SSL */
5127
5128 if (!TELOPT_OK(x)) {
5129 ckhexdump("unknown telnet subnegotiation",sb,n);
5130 break;
5131 } else if ( !(TELOPT_ME(x) || TELOPT_U(x)) ) {
5132 ckhexdump("telnet option not negotiated",sb,n);
5133 if (!tn_sb_bug)
5134 break;
5135 if (TELOPT_UNANSWERED_WILL(x)) {
5136 TELOPT_UNANSWERED_WILL(x) = 0;
5137 TELOPT_U(x) = 1;
5138 ckmakmsg(tn_msg,TN_MSG_LEN,
5139 "TELNET DO ",TELOPT(x),
5140 "(implied by receipt of SB - protocol error ignored)",
5141 NULL
5142 );
5143 debug(F100,tn_msg,"",0);
5144 if (tn_deb || debses) tn_debug(tn_msg);
5145 }
5146 if (TELOPT_UNANSWERED_DO(x)) {
5147 TELOPT_UNANSWERED_DO(x) = 0;
5148 TELOPT_ME(x) = 1;
5149 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET WILL ",TELOPT(x),
5150 " (implied by receipt of SB - protocol error ignored)",
5151 NULL);
5152 debug(F100,tn_msg,"",0);
5153 if (tn_deb || debses) tn_debug(tn_msg);
5154 }
5155 }
5156
5157 TELOPT_UNANSWERED_SB(x)=0;
5158 switch (x) {
5159 #ifdef CK_FORWARD_X
5160 case TELOPT_FORWARD_X:
5161 return(fwdx_tn_sb(sb, n));
5162 #endif /* CK_FORWARD_X */
5163 #ifdef CK_SSL
5164 case TELOPT_START_TLS: {
5165 /*
5166 the other side is saying SB START_TLS FOLLOWS
5167 the incoming channel is now ready for starting the
5168 TLS negotiation.
5169 */
5170 int def_tls_u_mode, def_tls_me_mode;
5171 int def_enc_u_mode, def_enc_me_mode;
5172 int rc = 0;
5173
5174 if (sb[0] != 1) {
5175 break;
5176 }
5177
5178 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 1;
5179 /* Preserve the default modes and make sure we will */
5180 /* refuse START_TLS when we retry. */
5181 if (sstelnet) {
5182 def_tls_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_START_TLS);
5183 def_tls_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS);
5184 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
5185 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
5186 #ifdef CK_ENCRYPTION
5187 def_enc_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
5188 def_enc_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
5189 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5190 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
5191 #endif /* CK_ENCRYPTION */
5192 } else {
5193 def_tls_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_START_TLS);
5194 def_tls_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS);
5195 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
5196 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
5197 #ifdef CK_ENCRYPTION
5198 def_enc_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
5199 def_enc_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
5200 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5201 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
5202 #endif /* CK_ENCRYPTION */
5203 }
5204 /* Negotiate TLS */
5205 ttnproto = NP_TLS;
5206 tn_init = 0;
5207 tn_begun = 0;
5208 if (ck_tn_tls_negotiate()<0) {
5209 /* we failed. disconnect and if we are the client */
5210 /* then reconnect and try without START_TLS. */
5211 extern char * line;
5212 int x = -1;
5213 extern int mdmtyp;
5214
5215 if (sstelnet) {
5216 printf("TLS failed: Disconnecting.\n");
5217 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5218 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5219 #ifdef CK_ENCRYPTION
5220 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5221 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5222 #endif /* CK_ENCRYPTION */
5223 ttclos(0);
5224 whyclosed = WC_TELOPT;
5225 ttnproto = NP_TELNET;
5226 rc = -3;
5227 } else {
5228 #ifndef NOLOCAL
5229 extern int tls_norestore;
5230 #endif /* NOLOCAL */
5231 printf("TLS failed: Disconnecting...\n");
5232 #ifdef CK_ENCRYPTION
5233 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5234 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5235 #endif /* CK_ENCRYPTION */
5236 /* if START_TLS is not REQUIRED, then retry without it */
5237 if ( def_tls_me_mode != TN_NG_MU ) {
5238 extern char ttname[];
5239 #ifndef NOLOCAL
5240 tls_norestore = 1;
5241 #endif /* NOLOCAL */
5242 ttclos(0);
5243 whyclosed = WC_TELOPT;
5244 #ifndef NOLOCAL
5245 tls_norestore = 0;
5246 #endif /* NOLOCAL */
5247 ttnproto = NP_TELNET;
5248 printf("Reconnecting without TLS.\n");
5249 sleep(2);
5250 if (ttopen(ttname,&x,mdmtyp,0)<0)
5251 rc = -3;
5252 } else {
5253 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) =
5254 def_tls_u_mode;
5255 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) =
5256 def_tls_me_mode;
5257 ttclos(0);
5258 whyclosed = WC_TELOPT;
5259 ttnproto = NP_TELNET;
5260 rc = -3;
5261 }
5262 }
5263 } else {
5264 #ifdef CK_AUTHENTICATION
5265 /* we succeeded. restart telnet negotiations from */
5266 /* the beginning. However, if we have received a */
5267 /* client certificate and we are a server, then do */
5268 /* not offer TELOPT_AUTH. */
5269 if ( ck_tn_auth_valid() == AUTH_VALID ) {
5270 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_AC;
5271 TELOPT_DEF_S_ME_MODE(TELOPT_AUTHENTICATION)= TN_NG_AC;
5272 }
5273 #endif /* CK_AUTHENTICATION */
5274 ttnproto = NP_TELNET;
5275 if (tn_ini() < 0)
5276 if (ttchk() < 0)
5277 rc = -1;
5278 }
5279 /* Restore the default modes */
5280 if (sstelnet) {
5281 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5282 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5283 #ifdef CK_ENCRYPTION
5284 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5285 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5286 #endif /* CK_ENCRYPTION */
5287 } else {
5288 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5289 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5290 #ifdef CK_ENCRYPTION
5291 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5292 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5293 #endif /* CK_ENCRYPTION */
5294 }
5295 return(rc);
5296 }
5297 #endif /* CK_SSL */
5298 #ifdef CK_AUTHENTICATION
5299 case TELOPT_AUTHENTICATION:
5300 if (ck_tn_sb_auth((char *)sb,n) < 0) {
5301 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
5302 ttclos(0);
5303 whyclosed = WC_TELOPT;
5304 return(-3);
5305 } else if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5306 ttclos(0);
5307 whyclosed = WC_TELOPT;
5308 return(-3);
5309 } else {
5310 if (TELOPT_ME_MODE(x) == TN_NG_RQ)
5311 TELOPT_ME_MODE(x) = TN_NG_AC;
5312 if (TELOPT_U_MODE(x) == TN_NG_RQ)
5313 TELOPT_U_MODE(x) = TN_NG_AC;
5314 }
5315 if (TELOPT_ME(x)) {
5316 TELOPT_ME(x) = 0;
5317 if (tn_sopt(WONT,x) < 0)
5318 return(-1);
5319 }
5320 if (TELOPT_U(x)) {
5321 TELOPT_U(x) = 0;
5322 if (tn_sopt(DONT,x) < 0)
5323 return(-1);
5324 }
5325 #ifdef CK_ENCRYPTION
5326 if (tn_no_encrypt()<0)
5327 return(-1);
5328 #endif /* CK_ENCRYPTION */
5329 } else {
5330 #ifdef CK_ENCRYPTION
5331 if (!ck_tn_auth_in_progress()) { /* we are finished */
5332 if (ck_tn_authenticated() == AUTHTYPE_SSL) {
5333 /* TLS was successful. Disable ENCRYPTION */
5334 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5335 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5336 }
5337 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send) {
5338 ck_encrypt_send_support();
5339 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
5340 }
5341 }
5342 #endif /* CK_ENCRYPTION */
5343 }
5344 break;
5345 #endif /* CK_AUTHENTICATION */
5346 #ifdef CK_ENCRYPTION
5347 case TELOPT_ENCRYPTION:
5348 if (ck_tn_sb_encrypt((char *)sb, n) < 0) {
5349 if (TELOPT_U_MODE(x) == TN_NG_MU ||
5350 TELOPT_ME_MODE(x) == TN_NG_MU)
5351 {
5352 ttclos(0);
5353 whyclosed = WC_TELOPT;
5354 return(-3);
5355 } else {
5356 if (TELOPT_ME_MODE(x) == TN_NG_RQ)
5357 TELOPT_ME_MODE(x) = TN_NG_AC;
5358 if (TELOPT_U_MODE(x) == TN_NG_RQ)
5359 TELOPT_U_MODE(x) = TN_NG_AC;
5360 }
5361 if (TELOPT_ME(x)) {
5362 TELOPT_ME(x) = 0;
5363 if (tn_sopt(WONT,x) < 0)
5364 return(-1);
5365 }
5366 if (TELOPT_U(x)) {
5367 TELOPT_U(x) = 0;
5368 if (tn_sopt(DONT,x) < 0)
5369 return(-1);
5370 }
5371 }
5372 break;
5373 #endif /* CK_ENCRYPTION */
5374 #ifdef IKS_OPTION
5375 case TELOPT_KERMIT:
5376 return(iks_tn_sb(sb, n-2));
5377 #endif /* IKS_OPTION */
5378 #ifdef TN_COMPORT
5379 case TELOPT_COMPORT:
5380 return(tnc_tn_sb(sb, n-2));
5381 #endif /* TN_COMPORT */
5382 case TELOPT_TTYPE:
5383 switch (sb[0]) {
5384 case TELQUAL_SEND: /* SEND terminal type? */
5385 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5386 if (tn_sttyp() < 0) /* Yes, so send it. */
5387 return(-1);
5388 } else {
5389 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 1;
5390 }
5391 break;
5392 case TELQUAL_IS: { /* IS terminal type? */
5393 /* IS terminal type -- remote gave us its current type */
5394 int i = 0;
5395 #ifndef OS2
5396 CHAR oldterm[64], *p;
5397 #endif /* OS2 */
5398 /* Isolate the specified terminal type string */
5399 while (sb[i++] != IAC) {
5400 if (i == 40 || /* max len of term string - RFC */
5401 sb[i] == IAC) {
5402 sb[i] = '\0';
5403 break;
5404 }
5405 }
5406 #ifdef OS2
5407 #ifndef NOTERM
5408 strupr(&(sb[1])); /* Upper case it */
5409 for (i = 0; i <= max_tt; i++) { /* find it in our list */
5410 if (!strcmp(&(sb[1]),tt_info[i].x_name)
5411 && i != TT_VTNT) /* can't support VTNT as server */
5412 {
5413 /* Set terminal type to the one chosen */
5414 if (i != tt_type)
5415 settermtype(i,0);
5416 break;
5417 }
5418 }
5419 if (i > max_tt &&
5420 strcmp(&(sb[1]),TELOPT_SB(TELOPT_TTYPE).term.type)) {
5421 /* Couldn't find the specified term type */
5422 sb[40] = '\0';
5423 strcpy(TELOPT_SB(TELOPT_TTYPE).term.type,&(sb[1]));
5424 /* SB TTYPE SEND */
5425 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
5426 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
5427 }
5428 #endif /* NOTERM */
5429 #else /* OS2 */
5430 p = (CHAR *) getenv("TERM");
5431 if (p)
5432 ckstrncpy((char *)oldterm,(char *)p,63);
5433 else
5434 oldterm[0] = '\0';
5435 cklower((char *)&(sb[1])); /* Lower case new term */
5436 ckmakmsg(term_buf,64,"TERM=",(char *)&(sb[1]),NULL,NULL);
5437 #ifdef OS2ORUNIX
5438 #ifndef NOPUTENV
5439 putenv(term_buf);
5440 #endif /* NOPUTENV */
5441 #endif /* OS2ORUNIX */
5442 #ifdef CK_CURSES
5443 #ifndef MYCURSES
5444 #ifndef COHERENT
5445 if (trmbuf) {
5446 if (tgetent(trmbuf,(char *)&sb[1]) < 1) {
5447 /* Unsupported terminal. If new and old terminal */
5448 /* types do not match, ask for another type. */
5449 if (strcmp((char *)oldterm,(char *)&sb[1])) {
5450 /* SB TTYPE SEND */
5451 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
5452 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
5453 }
5454 }
5455 }
5456 #endif /* COHERENT */
5457 #endif /* MYCURSES */
5458 #endif /* CK_CURSES */
5459 #endif /* OS2 */
5460 }
5461 }
5462 break;
5463 #ifdef CK_ENVIRONMENT
5464 #ifdef CK_XDISPLOC
5465 case TELOPT_XDISPLOC: /* Send X-Display Location */
5466 if (sb[0] == TELQUAL_SEND) {/* SEND X-Display Loc? */
5467 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5468 if (tn_sxdisploc() < 0) /* Yes, so send it. */
5469 return(-1);
5470 } else {
5471 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 1;
5472 }
5473 }
5474 /* IS -- X Display Location (not supported) */
5475 else if (sb[0] == TELQUAL_IS) {
5476 int i = 0;
5477 /* Isolate the specified X-display string */
5478 while (sb[i++] != IAC) {
5479 if (i >= TSBUFSIZ)
5480 return (-1);
5481 if (sb[i] == IAC) {
5482 sb[i] = '\0';
5483 break;
5484 }
5485 }
5486 debug(F110,"TELNET SB XDISPLOC IS",&sb[1],0);
5487 }
5488 break;
5489 #endif /* CK_XDISPLOC */
5490 #endif /* CK_ENVIRONMENT */
5491 case TELOPT_NAWS:
5492 if (sstelnet
5493 #ifdef IKSD
5494 || inserver
5495 #endif /* IKSD */
5496 ) {
5497 int w = 0, h = 0;
5498 int i = 0;
5499 /* At this point sb[] should contain width and height */
5500 if (sb[i] == IAC) i++;
5501 w = (sb[i++] << 8); /* save upper height */
5502 if (sb[i] == IAC) i++;
5503 w += sb[i++]; /* save the width */
5504 if (sb[i] == IAC) i++;
5505 h = (sb[i++] << 8); /* save upper height */
5506 if (sb[i] == IAC) i++;
5507 h += sb[i++];
5508 debug(F111,"tn_doop NAWS SB","width",w);
5509 debug(F111,"tn_doop NAWS SB","height",h);
5510
5511 if (w == 0)
5512 w = 80;
5513 if (h == 0)
5514 h = 24;
5515 #ifndef NOLOCAL
5516 if (tcp_incoming || inserver) {
5517 #ifdef OS2
5518 tt_cols[VTERM] = w;
5519 tt_rows[VTERM] = h;
5520 VscrnSetWidth(VTERM, w);
5521 VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
5522 #ifdef IKSD
5523 if (inserver) {
5524 cmd_cols = tt_cols[VCMD] = w;
5525 cmd_rows = tt_rows[VCMD] = h;
5526 VscrnSetWidth(VCMD, w);
5527 VscrnSetHeight(VCMD, h);
5528 }
5529 #endif /* IKSD */
5530 #else /* OS2 */
5531 tt_cols = w;
5532 tt_rows = h;
5533 #endif /* OS2 */
5534 } else {
5535 #ifdef OS2
5536 tt_cols[VCMD] = w;
5537 tt_rows[VCMD] = h;
5538 VscrnSetWidth(VCMD, w);
5539 VscrnSetHeight(VCMD, h);
5540 #endif /* OS2 */
5541 cmd_cols = w;
5542 cmd_rows = h;
5543 }
5544 #else /* NOLOCAL */
5545 cmd_cols = w;
5546 cmd_rows = h;
5547 #endif /* NOLOCAL */
5548
5549 /* Add LINES and COLUMNS to the environment */
5550 ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),NULL,NULL);
5551 ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),NULL,NULL);
5552 #ifdef OS2ORUNIX
5553 #ifndef NOPUTENV
5554 putenv(rows_buf);
5555 putenv(cols_buf);
5556 #endif /* NOPUTENV */
5557 #endif /* OS2ORUNIX */
5558 }
5559 break;
5560 #ifdef CK_ENVIRONMENT
5561 case TELOPT_NEWENVIRON:
5562 switch (sb[0]) {
5563 case TELQUAL_IS: /* IS */
5564 case TELQUAL_INFO: /* INFO */
5565 if (sb[0] == TELQUAL_IS)
5566 debug(F101,"tn_doop NEW-ENV SB IS","",n-3);
5567 else
5568 debug(F101,"tn_doop NEW-ENV SB INFO","",n-3);
5569 if (sstelnet || inserver) { /* Yes, receive it. */
5570 if (tn_rnenv((CHAR *)&sb[1],n-3) < 0)
5571 return(-1);
5572 }
5573 break;
5574 case TELQUAL_SEND: /* SEND */
5575 if ( sstelnet || inserver ) /* ignore if server */
5576 break;
5577 /* We need to take the sb[] and build a structure */
5578 /* containing all of the variables and types that */
5579 /* we are supposed to keep track of and send to */
5580 /* the host, then call tn_snenv(). */
5581 /* Or we can punt ... */
5582 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5583 if (tn_snenv((CHAR *)&sb[1],n-3) < 0) /* Yes, send it. */
5584 return(-1);
5585 } else {
5586 #ifndef VMS
5587 CHAR * xxx;
5588 xxx = (CHAR *) malloc(n-1);
5589 #else
5590 unsigned char * xxx;
5591 xxx = (unsigned char *) malloc(n-1);
5592 #endif /* VMS */
5593 /* Postpone sending until end of tn_ini() */
5594 TELOPT_SB(TELOPT_NEWENVIRON).env.str = xxx;
5595 if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
5596 memcpy((char *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
5597 (char *)&sb[1],n-3);
5598 TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-3] = IAC;
5599 TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-2] = '\0';
5600 TELOPT_SB(TELOPT_NEWENVIRON).env.len = n-3;
5601 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 1;
5602 }
5603 }
5604 break;
5605 }
5606 break;
5607 #endif /* CK_ENVIRONMENT */
5608 #ifdef CK_SNDLOC
5609 case TELOPT_SNDLOC: {
5610 if ( deblog ) {
5611 sb[n-2] = '\0';
5612 debug(F110,"TELNET Send-Location",sb,0);
5613 }
5614 break;
5615 }
5616 #endif /* CK_SNDLOC */
5617 } /* switch */
5618 break;
5619 }
5620 return(0);
5621 }
5622
5623 int
5624 #ifdef CK_ANSIC /* TELNET DO OPTION */
tn_doop(CHAR z,int echo,int (* fn)(int))5625 tn_doop(CHAR z, int echo, int (*fn)(int))
5626 #else
5627 tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
5628 #endif /* CK_ANSIC */
5629 /* tn_doop */ {
5630 int x=0, y=0;
5631
5632 debug(F101,"tn_doop char","",z);
5633 debug(F101,"tn_doop ttnproto","",ttnproto);
5634
5635 if (!IS_TELNET()) return(3);
5636
5637 #ifdef CK_SSL
5638 debug(F101,"tn_doop ssl_raw_flag","",ssl_raw_flag);
5639 if (ssl_raw_flag || tls_raw_flag) return(7);
5640 #endif /* CK_SSL */
5641 debug(F100,"tn_doop ttnproto proceeding...","",0);
5642
5643 if (z != (CHAR) IAC) {
5644 debug(F101,"tn_doop bad call","",z);
5645 return(-1);
5646 }
5647 if (ttnet != NET_TCPB) /* Check network type */
5648 return(0);
5649 if (ttnproto != NP_TELNET &&
5650 ttnproto != NP_NONE) /* Check protocol */
5651 return(0);
5652
5653 x = tn_xdoop(z,echo,fn);
5654 if (x >= 0 && !tn_begun) {
5655 y = tn_start();
5656 }
5657 return(y < 0 ? y : x);
5658 }
5659
5660 #ifdef CK_ENVIRONMENT
5661
5662 /* Telnet receive new environment */
5663 /* Returns -1 on error, 0 if nothing happens, 1 on success */
5664 /* In order for this code to work, sb[len] == IAC */
5665 /* We currently only support the USER environment variable */
5666
5667 int
5668 #ifdef CK_ANSIC
tn_rnenv(CHAR * sb,int len)5669 tn_rnenv(CHAR * sb, int len)
5670 #else
5671 tn_rnenv(sb, len) CHAR * sb; int len;
5672 #endif /* CK_ANSIC */
5673 /* tn_rnenv */ { /* Receive new environment */
5674 char varname[17];
5675 char value[65];
5676 char * reply = 0, * s = 0;
5677 int i,j,k,n; /* Worker. */
5678 int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR, */
5679 /* 3 for VALUE in progress */
5680
5681 if (ttnet != NET_TCPB) return(0);
5682 if (ttnproto != NP_TELNET) return(0);
5683 if (sb == NULL) return(-1);
5684
5685 if (len == 0) return(1);
5686
5687 /*
5688 Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
5689 follow here until done...
5690 */
5691 for (i = 0, j = 0, k = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5692 switch (sb[i]) {
5693 case TEL_ENV_VAR: /* VAR */
5694 case TEL_ENV_USERVAR: /* USERVAR */
5695 case IAC: /* End of the list */
5696 switch (type) {
5697 case 0: /* Nothing in progress */
5698 /* If we get IAC only, then that means there were */
5699 /* no environment variables to send. we are done */
5700 if (j == 0 && sb[i] == IAC)
5701 return(1);
5702 case 1: /* VAR in progress */
5703 case 2: /* USERVAR in progress */
5704 case 3: /* VALUE in progress */
5705 value[k] = '\0';
5706 varname[j] = '\0';
5707 debug(F111,"tn_rnenv varname",varname,type);
5708 debug(F111,"tn_rnenv value",value,type);
5709 if (!strcmp(varname,"USER")) {
5710 #ifdef CK_AUTHENTICATION
5711 if (ck_tn_auth_valid() != AUTH_VALID) {
5712 extern char szUserNameRequested[];
5713 debug(F100,"tn_rnenv != AUTH_VALID","",0);
5714 ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
5715 ckstrncpy(uidbuf,value,UIDBUFLEN);
5716 #ifdef CK_SSL
5717 if (ssl_active_flag) {
5718 if ( tls_is_user_valid(ssl_con, uidbuf) ) {
5719 extern char szUserNameAuthenticated[];
5720 ckstrncpy(szUserNameAuthenticated,uidbuf,
5721 UIDBUFLEN);
5722 auth_finished(AUTH_VALID);
5723 }
5724 } else if (tls_active_flag) {
5725 if ( tls_is_user_valid(tls_con, uidbuf) ) {
5726 extern char szUserNameAuthenticated[];
5727 ckstrncpy(szUserNameAuthenticated,uidbuf,
5728 UIDBUFLEN);
5729 auth_finished(AUTH_VALID);
5730 }
5731 }
5732 #endif /* CK_SSL */
5733 } else { /* AUTH_VALID */
5734 int x = 0;
5735 debug(F110,"tn_rnenv AUTH_VALID uidbuf",uidbuf,0);
5736
5737 #ifdef OS2
5738 x = ckstrcmp(value,uidbuf,-1,0); /* case insensitive */
5739 #ifdef NT
5740 /* NTLM authentication returns names of the form */
5741 /* DOMAIN\user. We need to check to see of the */
5742 /* USER VAR contains a domain name or not. If */
5743 /* not, then we do not want to change state if */
5744 /* the uidbuf matches the USER VAR when the */
5745 /* DOMAIN is ignored. */
5746 if ( x && ck_tn_authenticated() == AUTHTYPE_NTLM ) {
5747 char * s1=NULL, * s2=NULL;
5748 int len1, len2, i;
5749
5750 len1 = strlen(value);
5751 for ( i=len1-1 ; i>=0 ; i--) {
5752 if ( value[i] == '\\' ) {
5753 s1 = &value[i+1]; /* DOMAIN found */
5754 break;
5755 }
5756 }
5757
5758 if ( s1 == NULL ) {
5759 len2 = strlen(uidbuf);
5760 for ( i=len2-1 ; i>=0 ; i--) {
5761 if ( uidbuf[i] == '\\' ) {
5762 s2 = &uidbuf[i+1]; /* DOMAIN found */
5763 break;
5764 }
5765 }
5766
5767 if ( s2 )
5768 x = ckstrcmp(value,s2,-1,0);
5769 }
5770 }
5771 #endif /* NT */
5772 #else /* OS2 */
5773 x = ckstrcmp(value,uidbuf,-1,1); /* case sensitive */
5774 #endif /* OS2 */
5775 if ( x ) {
5776 extern char szUserNameRequested[];
5777 ckstrncpy(uidbuf,value,UIDBUFLEN);
5778 ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
5779 auth_finished(AUTH_USER);
5780 #ifdef CK_SSL
5781 if (ssl_active_flag || tls_active_flag) {
5782 if ( tls_is_user_valid(ssl_con, uidbuf) )
5783 auth_finished(AUTH_VALID);
5784 }
5785 #endif /* CK_SSL */
5786 }
5787 }
5788 #else /* CK_AUTHENTICATION */
5789 ckstrncpy(uidbuf,value,UIDBUFLEN);
5790 #endif /* CK_AUTHENTICATION */
5791 }
5792 break;
5793 }
5794 varname[0] = '\0';
5795 value[0] = '\0';
5796 j = 0;
5797 k = 0;
5798 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
5799 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
5800 0
5801 );
5802 break;
5803 case TEL_ENV_VALUE: /* VALUE */
5804 if ( type == 1 || type == 2 )
5805 type = 3;
5806 break;
5807 case TEL_ENV_ESC: /* ESC */
5808 /* Take next character literally */
5809 if ( ++i >= len )
5810 break;
5811 /* otherwise, fallthrough so byte will be added to string. */
5812 default:
5813 switch (type) {
5814 case 1: /* VAR in progress */
5815 case 2: /* USERVAR in progress */
5816 if ( j < 16 )
5817 varname[j++] = sb[i];
5818 break;
5819 case 3:
5820 if ( k < 64 )
5821 value[k++] = sb[i];
5822 break;
5823 }
5824 }
5825 }
5826 return(0);
5827 }
5828
5829 /* These are for Microsoft SFU version 2 Telnet Server */
5830 #define SFUTLNTVER "SFUTLNTVER"
5831 #define SFUTLNTMODE "SFUTLNTMODE"
5832 #define SFUTLNTVER_VALUE "2"
5833 #define SFUTLNTMODE_VALUE "console" /* The other value is "stream" */
5834
5835 /* Telnet send new environment */
5836 /* Returns -1 on error, 0 if nothing happens, 1 on success */
5837 /* In order for this code to work, sb[len] == IAC */
5838
5839 int
5840 #ifdef CK_ANSIC
tn_snenv(CHAR * sb,int len)5841 tn_snenv(CHAR * sb, int len)
5842 #else
5843 tn_snenv(sb, len) CHAR * sb; int len;
5844 #endif /* CK_ANSIC */
5845 /* tn_snenv */ { /* Send new environment */
5846 char varname[16];
5847 char * reply = 0, * s = 0;
5848 int i,j,n; /* Worker. */
5849 int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR in progress */
5850 extern int ck_lcname;
5851 char localuidbuf[UIDBUFLEN]; /* (Initialized just below) */
5852 char * uu = uidbuf;
5853 char * disp = NULL;
5854
5855 localuidbuf[0] = '\0';
5856 if (ttnet != NET_TCPB) return(0);
5857 if (ttnproto != NP_TELNET) return(0);
5858 if (!sb) return(-1);
5859
5860 #ifdef CK_SSL
5861 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
5862 return(0);
5863 }
5864 #endif /* CK_SSL */
5865
5866 #ifdef CK_FORWARD_X
5867 if (TELOPT_U(TELOPT_FORWARD_X)) {
5868 disp = NULL;
5869 } else
5870 #endif /* CK_FORWARD_X */
5871 disp = (char *)tn_get_display();
5872
5873 if (ck_lcname) {
5874 ckstrncpy(localuidbuf,uidbuf,UIDBUFLEN);
5875 cklower(localuidbuf);
5876 uu = localuidbuf;
5877 }
5878
5879 ckhexdump((CHAR *)"tn_snenv sb[]",sb,len);
5880 debug(F110,"tn_snenv uidbuf",uidbuf,0);
5881 debug(F110,"tn_snenv localuidbuf",localuidbuf,0);
5882 debug(F110,"tn_snenv tn_env_sys",tn_env_sys,0);
5883 debug(F110,"tn_snenv tn_env_disp",tn_env_disp,0);
5884 debug(F110,"tn_snenv disp",disp,0);
5885
5886 /* First determine the size of the buffer we will need */
5887 for (i = 0, j = 0, n = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5888 switch (sb[i]) {
5889 case TEL_ENV_VAR: /* VAR */
5890 case TEL_ENV_USERVAR: /* USERVAR */
5891 case IAC: /* End of the list */
5892 switch (type) {
5893 case 0: /* Nothing in progress */
5894 /* If we get IAC only, then that means send all */
5895 /* VAR and USERVAR. */
5896 if (!(j == 0 && sb[i] == IAC))
5897 break;
5898 case 1: /* VAR in progress */
5899 varname[j] = '\0' ;
5900 if (!varname[0]) { /* Send All */
5901 if (uu[0])
5902 n += strlen(uu) + 4 + 2;
5903 if (tn_env_job[0])
5904 n += strlen(tn_env_job) + 3 + 2;
5905 if (tn_env_acct[0])
5906 n += strlen(tn_env_acct) + 4 + 2;
5907 if (tn_env_prnt[0])
5908 n += strlen(tn_env_prnt) + 7 + 2;
5909 if (tn_env_sys[0])
5910 n += strlen(tn_env_sys) + 10 + 2;
5911 if (disp)
5912 n += strlen(disp) + 7 + 2;
5913 } else if (!strcmp(varname,"USER") && uu[0])
5914 n += strlen(uu) + 4 + 2;
5915 else if (!strcmp(varname,"JOB") && tn_env_job[0])
5916 n += strlen(tn_env_job) + 3 + 2;
5917 else if (!strcmp(varname,"ACCT") && tn_env_acct[0])
5918 n += strlen(tn_env_acct) + 4 + 2;
5919 else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0])
5920 n += strlen(tn_env_prnt) + 7 + 2;
5921 else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0])
5922 n += strlen(tn_env_sys) + 10 + 2;
5923 else if (!strcmp(varname,"DISPLAY") && disp)
5924 n += strlen(disp) + 7 + 2;
5925 /* If we get IAC only, then that means send all */
5926 /* VAR and USERVAR. */
5927 if (!(j == 0 && sb[i] == IAC))
5928 break;
5929 case 2: /* USERVAR in progress */
5930 varname[j] = '\0' ;
5931 if (!varname[0]) { /* Send All */
5932 int x;
5933 for ( x=0 ; x<8 ; x++ ) {
5934 if ( tn_env_uservar[x][0] &&
5935 tn_env_uservar[x][1] )
5936 n += strlen(tn_env_uservar[x][0])
5937 + strlen(tn_env_uservar[x][1]) + 2;
5938 }
5939 if ( tn_sfu ) {
5940 /* For compatibility with Microsoft Telnet Server */
5941 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
5942 n += strlen(SFUTLNTMODE) +
5943 strlen(SFUTLNTMODE_VALUE) + 2;
5944 }
5945 #ifdef CK_SNDLOC
5946 if ( tn_loc && tn_loc[0] )
5947 n += strlen("LOCATION") + strlen(tn_loc) + 2;
5948 #endif /* CK_SNDLOC */
5949 }
5950 else if (tn_sfu && !strcmp(varname,SFUTLNTVER))
5951 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
5952 else if (tn_sfu && !strcmp(varname,SFUTLNTMODE))
5953 n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
5954 #ifdef CK_SNDLOC
5955 else if ( tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION"))
5956 n += strlen("LOCATION") + strlen(tn_loc) + 2;
5957 #endif /* CK_SNDLOC */
5958 else {
5959 int x;
5960 for ( x=0 ; x<8 ; x++ ) {
5961 if ( tn_env_uservar[x][0] &&
5962 tn_env_uservar[x][1] &&
5963 !strcmp(varname,tn_env_uservar[x][0]))
5964 n += strlen(tn_env_uservar[x][0])
5965 + strlen(tn_env_uservar[x][1]) + 2;
5966 }
5967 }
5968 break;
5969 }
5970 varname[0] = '\0';
5971 j = 0;
5972 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
5973 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
5974 0
5975 );
5976 break;
5977 case TEL_ENV_VALUE: /* VALUE */
5978 /* Protocol Error */
5979 debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
5980 if (tn_deb || debses)
5981 tn_debug("TELNET Subnegotiation error - VALUE in SEND");
5982 return(0);
5983 case TEL_ENV_ESC: /* ESC */
5984 if (++i >= len)
5985 break;
5986 default:
5987 if (j < 16 )
5988 varname[j++] = sb[i];
5989 }
5990 }
5991 reply = malloc(n + 16); /* Leave room for IAC stuff */
5992 if (!reply) {
5993 debug(F100, "TELNET Subnegotiation error - malloc failed", "",0);
5994 if (tn_deb || debses)
5995 tn_debug("TELNET Subnegotiation error - malloc failed");
5996
5997 /* Send a return packet with no variables so that the host */
5998 /* may continue with additional negotiations */
5999 if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,"",0) < 0)
6000 return(-1);
6001 return(0);
6002 }
6003
6004 /* Now construct the real reply */
6005
6006 n = 0; /* Start at beginning of buffer */
6007 /*
6008 Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
6009 follow here until done...
6010 */
6011 for (i = 0, j = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
6012 switch (sb[i]) {
6013 case TEL_ENV_VAR: /* VAR */
6014 case TEL_ENV_USERVAR: /* USERVAR */
6015 case IAC: /* End of the list */
6016 switch (type) {
6017 case 0: /* Nothing in progress */
6018 /* If we get IAC only, then that means send all */
6019 /* VAR and USERVAR. */
6020 if (!(j == 0 && sb[i] == IAC))
6021 break;
6022 case 1: /* VAR in progress */
6023 varname[j] = '\0';
6024 if (!varname[0]) {
6025 /* Send All */
6026 if (uu[0]) {
6027 reply[n] = TEL_ENV_VAR; /* VAR */
6028 strcpy(&reply[n+1],"USER");
6029 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6030 strcpy(&reply[n+6],uu);
6031 n += strlen(uu) + 4 + 2;
6032 }
6033 if (tn_env_job[0]) {
6034 reply[n] = TEL_ENV_VAR; /* VAR */
6035 strcpy(&reply[n+1],"JOB");
6036 reply[n+4] = TEL_ENV_VALUE; /* VALUE */
6037 strcpy(&reply[n+5],tn_env_job);
6038 n += strlen(tn_env_job) + 3 + 2;
6039 }
6040 if (tn_env_acct[0]) {
6041 reply[n] = TEL_ENV_VAR; /* VAR */
6042 strcpy(&reply[n+1],"ACCT");
6043 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6044 strcpy(&reply[n+6],tn_env_acct);
6045 n += strlen(tn_env_acct) + 4 + 2;
6046 }
6047 if (tn_env_prnt[0]) {
6048 reply[n] = TEL_ENV_VAR; /* VAR */
6049 strcpy(&reply[n+1],"PRINTER");
6050 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6051 strcpy(&reply[n+9],tn_env_prnt);
6052 n += strlen(tn_env_prnt) + 7 + 2;
6053 }
6054 if (tn_env_sys[0]) {
6055 reply[n] = TEL_ENV_VAR; /* VAR */
6056 strcpy(&reply[n+1],"SYSTEMTYPE");
6057 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6058 strcpy(&reply[n+12],tn_env_sys);
6059 n += strlen(tn_env_sys) + 10 + 2;
6060 }
6061 if (disp) {
6062 reply[n] = TEL_ENV_VAR; /* VAR */
6063 strcpy(&reply[n+1],"DISPLAY");
6064 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6065 strcpy(&reply[n+9],disp);
6066 n += strlen(disp) + 7 + 2;
6067 }
6068 } else if (!strcmp(varname,"USER") && uu[0]) {
6069 reply[n] = TEL_ENV_VAR; /* VAR */
6070 strcpy(&reply[n+1],"USER");
6071 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6072 strcpy(&reply[n+6],uu);
6073 n += strlen(uu) + 4 + 2;
6074 } else if (!strcmp(varname,"JOB") && tn_env_job[0]) {
6075 reply[n] = TEL_ENV_VAR; /* VAR */
6076 strcpy(&reply[n+1],"JOB");
6077 reply[n+4] = TEL_ENV_VALUE; /* VALUE */
6078 strcpy(&reply[n+5],tn_env_job);
6079 n += strlen(tn_env_job) + 3 + 2;
6080 } else if (!strcmp(varname,"ACCT") && tn_env_acct[0]) {
6081 reply[n] = TEL_ENV_VAR; /* VAR */
6082 strcpy(&reply[n+1],"ACCT");
6083 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6084 strcpy(&reply[n+6],tn_env_acct);
6085 n += strlen(tn_env_acct) + 4 + 2;
6086 } else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0]) {
6087 reply[n] = TEL_ENV_VAR; /* VAR */
6088 strcpy(&reply[n+1],"PRINTER");
6089 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6090 strcpy(&reply[n+9],tn_env_prnt);
6091 n += strlen(tn_env_prnt) + 7 + 2;
6092 } else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0]) {
6093 reply[n] = TEL_ENV_VAR; /* VAR */
6094 strcpy(&reply[n+1],"SYSTEMTYPE");
6095 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6096 strcpy(&reply[n+12],tn_env_sys);
6097 n += strlen(tn_env_sys) + 10 + 2;
6098 } else if (!strcmp(varname,"DISPLAY") && disp) {
6099 reply[n] = TEL_ENV_VAR; /* VAR */
6100 strcpy(&reply[n+1],"DISPLAY");
6101 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6102 strcpy(&reply[n+9],disp);
6103 n += strlen(disp) + 7 + 2;
6104 }
6105 /* If we get IAC only, then that means send all */
6106 /* VAR and USERVAR. */
6107 if (!(j == 0 && sb[i] == IAC))
6108 break;
6109 case 2: /* USERVAR in progress */
6110 varname[j] = '\0';
6111 if (!varname[0]) {
6112 /* Send All */
6113 int x,y;
6114 for ( x=0 ; x<8 ; x++ ) {
6115 if ( tn_env_uservar[x][0] &&
6116 tn_env_uservar[x][1] ) {
6117 reply[n] = TEL_ENV_USERVAR; /* VAR */
6118 y = strlen(tn_env_uservar[x][0]);
6119 strcpy(&reply[n+1],tn_env_uservar[x][0]);
6120 reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
6121 strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
6122 n += y+strlen(tn_env_uservar[x][1])+2;
6123 }
6124 }
6125 if ( tn_sfu ) {
6126 /* Compatibility with Microsoft Telnet Server */
6127 reply[n] = TEL_ENV_USERVAR; /* VAR */
6128 strcpy(&reply[n+1],SFUTLNTVER);
6129 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6130 strcpy(&reply[n+12],SFUTLNTVER_VALUE);
6131 n += strlen(SFUTLNTVER)+strlen(SFUTLNTVER_VALUE)+2;
6132
6133 reply[n] = TEL_ENV_USERVAR; /* VAR */
6134 strcpy(&reply[n+1],SFUTLNTMODE);
6135 reply[n+12] = TEL_ENV_VALUE; /* VALUE */
6136 strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
6137 n += strlen(SFUTLNTMODE)+strlen(SFUTLNTMODE_VALUE)+2;
6138 }
6139 if (tn_loc && tn_loc[0]) {
6140 reply[n] = TEL_ENV_USERVAR; /* VAR */
6141 strcpy(&reply[n+1],"LOCATION");
6142 reply[n+9] = TEL_ENV_VALUE; /* VALUE */
6143 strcpy(&reply[n+10],tn_loc);
6144 n += strlen("LOCATION") + strlen(tn_loc) + 2;
6145 }
6146 } else if (tn_sfu && !strcmp(varname,SFUTLNTVER)) {
6147 reply[n] = TEL_ENV_USERVAR; /* VAR */
6148 strcpy(&reply[n+1],SFUTLNTVER);
6149 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6150 strcpy(&reply[n+12],SFUTLNTVER_VALUE);
6151 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
6152 } else if (tn_sfu && !strcmp(varname,SFUTLNTMODE)) {
6153 reply[n] = TEL_ENV_USERVAR; /* VAR */
6154 strcpy(&reply[n+1],SFUTLNTMODE);
6155 reply[n+12] = TEL_ENV_VALUE; /* VALUE */
6156 strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
6157 n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
6158 }
6159 #ifdef CK_SNDLOC
6160 else if (tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION")){
6161 reply[n] = TEL_ENV_USERVAR; /* VAR */
6162 strcpy(&reply[n+1],"LOCATION");
6163 reply[n+9] = TEL_ENV_VALUE; /* VALUE */
6164 strcpy(&reply[n+10],tn_loc);
6165 n += strlen("LOCATION") + strlen(tn_loc) + 2;
6166 }
6167 #endif /* CK_SNDLOC */
6168 else {
6169 int x,y;
6170 for ( x=0 ; x<8 ; x++ ) {
6171 if ( tn_env_uservar[x][0] &&
6172 tn_env_uservar[x][1] &&
6173 !strcmp(varname,tn_env_uservar[x][0])) {
6174 reply[n] = TEL_ENV_USERVAR; /* VAR */
6175 y = strlen(tn_env_uservar[x][0]);
6176 strcpy(&reply[n+1],tn_env_uservar[x][0]);
6177 reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
6178 strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
6179 n += y+strlen(tn_env_uservar[x][1])+2;
6180 }
6181 }
6182 }
6183 break;
6184 }
6185 varname[0] = '\0';
6186 j = 0;
6187 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
6188 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
6189 0
6190 );
6191 break;
6192 case TEL_ENV_VALUE: /* VALUE */
6193 /* Protocol Error */
6194 debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
6195 if (tn_deb || debses)
6196 tn_debug("TELNET Subnegotiation error - VALUE in SEND");
6197 return(0); /* Was -1 but that would be taken as */
6198 /* an I/O error, so absorb it and go on. */
6199 case TEL_ENV_ESC: /* ESC */
6200 /* Not sure what this for. Quote next character? */
6201 break;
6202 default:
6203 varname[j++] = sb[i];
6204 }
6205 }
6206 if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,reply,n) < 0) {
6207 free(reply);
6208 return(-1);
6209 }
6210 free(reply);
6211 return(1);
6212 }
6213 #endif /* CK_ENVIRONMENT */
6214
6215 /* Telnet send terminal type */
6216 /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
6217
6218 int
tn_sttyp()6219 tn_sttyp() { /* Send telnet terminal type. */
6220 char *ttn; /* Name of terminal type. */
6221 #ifdef OS2
6222 static int alias = -1; /* which alias are we using ? */
6223 int settype = 0;
6224 #endif /* OS2 */
6225 int i, rc; /* Worker. */
6226 int tntermflg = 0;
6227
6228 if (ttnet != NET_TCPB) return(0);
6229 if (ttnproto != NP_TELNET) return(0);
6230
6231 if (!TELOPT_ME(TELOPT_TTYPE)) return(0);
6232
6233 #ifdef CK_SSL
6234 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6235 return(0);
6236 }
6237 #endif /* CK_SSL */
6238 ttn = NULL;
6239
6240 #ifndef NOTERM
6241 #ifdef OS2
6242 if (!tn_term) {
6243 if (ttnum == -1) {
6244 ttnum = tt_type;
6245 settype = 0;
6246 alias = -1;
6247 } else if (ttnumend) {
6248 ttnumend = 0;
6249 settype = 0;
6250 } else {
6251 if (tt_info[tt_type].x_aliases[++alias] == NULL) {
6252 if (--tt_type < 0)
6253 tt_type = max_tt;
6254 if (ttnum == tt_type)
6255 ttnumend = 1;
6256 settype = 1;
6257 alias = -1;
6258 }
6259 }
6260 if (tt_type >= 0 && tt_type <= max_tt) {
6261 if (alias == -1)
6262 ttn = tt_info[tt_type].x_name;
6263 else
6264 ttn = tt_info[tt_type].x_aliases[alias];
6265 } else
6266 ttn = NULL;
6267 }
6268 else settype = 0;
6269 #endif /* OS2 */
6270 #endif /* NOTERM */
6271
6272 if (tn_term) { /* Terminal type override? */
6273 debug(F110,"tn_sttyp",tn_term,0);
6274 if (*tn_term) {
6275 ttn = tn_term;
6276 tntermflg = 1;
6277 }
6278 } else debug(F100,"tn_sttyp no term override","",0);
6279
6280 #ifndef datageneral
6281 if (!ttn) { /* If no override, */
6282 ttn = getenv("TERM"); /* get it from the environment. */
6283 }
6284 #endif /* datageneral */
6285 if ((ttn == ((char *)0)) || ((int)strlen(ttn) >= TSBUFSIZ))
6286 ttn = "UNKNOWN";
6287 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6288 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6289 sb_out[2] = TELOPT_TTYPE; /* Terminal Type */
6290 sb_out[3] = (CHAR) 0; /* Is... */
6291 for (i = 4; *ttn; ttn++,i++) { /* Copy and uppercase it */
6292 #ifdef VMS
6293 if (!tntermflg && *ttn == '-' &&
6294 (!strcmp(ttn,"-80") || !strcmp(ttn,"-132")))
6295 break;
6296 else
6297 #endif /* VMS */
6298 sb_out[i] = (char) ((!tntermflg && islower(*ttn)) ?
6299 toupper(*ttn) :
6300 *ttn);
6301 }
6302 ttn = (char *)sb_out; /* Point back to beginning */
6303 #ifdef DEBUG
6304 if (deblog || tn_deb || debses) {
6305 sb_out[i] = '\0'; /* For debugging */
6306 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
6307 TELOPT(TELOPT_TTYPE)," IS ",(char *)sb_out+4," IAC SE",
6308 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6309 }
6310 #endif /* DEBUG */
6311 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6312 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6313 #ifdef OS2
6314 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6315 #endif
6316 #ifdef DEBUG
6317 debug(F100,tn_msg_out,"",0);
6318 if (tn_deb || debses) tn_debug(tn_msg_out);
6319 #endif /* DEBUG */
6320 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6321 #ifdef OS2
6322 ReleaseTelnetMutex();
6323 #endif
6324 if (rc)
6325 return(-1);
6326 #ifndef NOTERM
6327 #ifdef OS2
6328 if (settype)
6329 settermtype(tt_type,0);
6330 else {
6331 ipadl25();
6332 VscrnIsDirty(VTERM);
6333 }
6334 #endif /* OS2 */
6335 #endif /* NOTERM */
6336 return(1);
6337 }
6338
6339 #ifdef CK_ENVIRONMENT
6340 #ifdef CK_XDISPLOC
6341
6342 /* Telnet send xdisplay location */
6343 /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
6344
6345 int
tn_sxdisploc()6346 tn_sxdisploc() { /* Send telnet X display location. */
6347 char * disp=NULL;
6348 int i,rc;
6349
6350 if (ttnet != NET_TCPB) return(0);
6351 if (ttnproto != NP_TELNET) return(0);
6352
6353 if (!TELOPT_ME(TELOPT_XDISPLOC)) return(0);
6354
6355 #ifdef CK_SSL
6356 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6357 return(0);
6358 }
6359 #endif /* CK_SSL */
6360
6361 #ifdef CK_FORWARD_X
6362 if (TELOPT_U(TELOPT_FORWARD_X)) {
6363 disp = NULL;
6364 } else
6365 #endif /* CK_FORWARD_X */
6366 disp = (char *)tn_get_display();
6367 debug(F110,"tn_sxdisploc",disp,0);
6368
6369 if (!disp) {
6370 /* Can't do both, send WONT */
6371 if (tn_sopt(WONT,TELOPT_XDISPLOC) < 0)
6372 return(-1);
6373 TELOPT_UNANSWERED_WONT(TELOPT_XDISPLOC) = 1;
6374 return(0);
6375 }
6376
6377 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6378 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6379 sb_out[2] = TELOPT_XDISPLOC; /* X-Display Location */
6380 sb_out[3] = (CHAR) 0; /* Is... */
6381 for (i = 4; *disp; disp++,i++) { /* Copy and uppercase it */
6382 sb_out[i] = (char) *disp;
6383 }
6384 #ifdef DEBUG
6385 if (deblog || tn_deb || debses) {
6386 sb_out[i] = '\0'; /* For debugging */
6387 ckmakxmsg( tn_msg_out,TN_MSG_LEN,
6388 "TELNET SENT SB ",TELOPT(TELOPT_XDISPLOC),
6389 " IS ",(char *)sb_out+4," IAC SE",
6390 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6391 }
6392 #endif /* DEBUG */
6393 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6394 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6395 #ifdef OS2
6396 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6397 #endif
6398 #ifdef DEBUG
6399 debug(F100,tn_msg_out,"",0);
6400 if (tn_deb || debses) tn_debug(tn_msg_out);
6401 #endif /* DEBUG */
6402 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6403 #ifdef OS2
6404 ReleaseTelnetMutex();
6405 #endif
6406 if (rc)
6407 return(-1);
6408 return(1);
6409 }
6410 #endif /* CK_XDISPLOC */
6411 #endif /* CK_ENVIRONMENT */
6412
6413 #ifdef CK_FORWARD_X
6414 int
tn_sndfwdx()6415 tn_sndfwdx() { /* Send Fwd X Screen number to host */
6416 unsigned char screen = 0;
6417 char * disp;
6418 int i,rc;
6419
6420 /* if (!IS_TELNET()) return(0); */
6421
6422 if (!TELOPT_U(TELOPT_FORWARD_X)) return(0);
6423 #ifdef CK_SSL
6424 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6425 return(0);
6426 }
6427 #endif /* CK_SSL */
6428
6429 /*
6430 * The format of the DISPLAY variable is [<host>:]<display>[.<screen>]
6431 * where <host> is an optional DNS name or ip address with a default of
6432 * the localhost; the screen defaults to 0
6433 */
6434
6435 disp = (char *)tn_get_display();
6436 if (disp) {
6437 int colon,dot;
6438 colon = ckindex(":",disp,0,0,1);
6439 dot = ckindex(".",&disp[colon],0,0,1);
6440
6441 if ( dot ) {
6442 screen = atoi(&disp[colon+dot]);
6443 }
6444 } else {
6445 screen = 0;
6446 }
6447
6448 i = 0;
6449 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
6450 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
6451 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
6452 sb_out[i++] = FWDX_SCREEN; /* Screen */
6453 sb_out[i++] = screen;
6454 if ( screen == IAC )
6455 sb_out[i++] = IAC;
6456 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6457 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6458 #ifdef DEBUG
6459 if (deblog || tn_deb || debses) {
6460 ckmakxmsg( tn_msg_out,TN_MSG_LEN,
6461 "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
6462 " SCREEN ",ckctox(screen,1)," IAC SE",
6463 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6464 }
6465 #endif /* DEBUG */
6466 #ifdef OS2
6467 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6468 #endif
6469 #ifdef DEBUG
6470 debug(F100,tn_msg_out,"",0);
6471 if (tn_deb || debses) tn_debug(tn_msg_out);
6472 #endif /* DEBUG */
6473 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6474 #ifdef OS2
6475 ReleaseTelnetMutex();
6476 #endif
6477 if (rc)
6478 return(-1);
6479 return(0);
6480 }
6481 #endif /* CK_FORWARD_X */
6482
6483 #ifdef CK_SNDLOC
6484 int
tn_sndloc()6485 tn_sndloc() { /* Send location. */
6486 int i,rc; /* Worker. */
6487 char *ttloc;
6488
6489 /* if (!IS_TELNET()) return(0); */
6490
6491 if (!TELOPT_ME(TELOPT_SNDLOC)) return(0);
6492
6493 #ifdef CK_SSL
6494 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6495 return(0);
6496 }
6497 #endif /* CK_SSL */
6498 ttloc = (tn_loc ? tn_loc : ""); /* In case we are being called even */
6499 /* though there is no location. */
6500 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6501 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6502 sb_out[2] = TELOPT_SNDLOC; /* Location */
6503 for (i = 3; *ttloc && i < TSBUFSIZ; ttloc++,i++) /* Copy it */
6504 sb_out[i] = (char) *ttloc;
6505 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6506 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6507
6508 #ifdef DEBUG
6509 if (deblog || tn_deb || debses) {
6510 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
6511 "TELNET SENT SB ",TELOPT(TELOPT_SNDLOC)," ",(char *)sb_out+3,
6512 " IAC SE", NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6513 }
6514 #endif /* DEBUG */
6515 #ifdef OS2
6516 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6517 #endif
6518 #ifdef DEBUG
6519 debug(F100,tn_msg_out,"",0);
6520 if (tn_deb || debses) tn_debug(tn_msg_out);
6521 #endif /* DEBUG */
6522 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6523 #ifdef OS2
6524 ReleaseTelnetMutex();
6525 #endif
6526 if (rc)
6527 return(-1);
6528 sb_out[i-2] = '\0'; /* For debugging */
6529 return(0);
6530 }
6531 #endif /* CK_SNDLOC */
6532
6533 #ifdef CK_NAWS /* NAWS = Negotiate About Window Size */
6534 int
tn_snaws()6535 tn_snaws() { /* Send terminal width and height, RFC 1073 */
6536 #ifndef NOLOCAL
6537 CHAR sb_out[24]; /* multiple threads */
6538 int i = 0,rc;
6539 #ifdef OS2
6540 int x = VscrnGetWidth(VTERM),
6541 y = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0);
6542 #else /* OS2 */
6543 int x = tt_cols, y = tt_rows;
6544 #endif /* OS2 */
6545
6546 if (ttnet != NET_TCPB) return(0);
6547 if (ttnproto != NP_TELNET) return(0);
6548 if (!TELOPT_ME(TELOPT_NAWS)) return(0);
6549
6550 #ifdef CK_SSL
6551 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6552 return(0);
6553 }
6554 #endif /* CK_SSL */
6555 if (x < 0) x = 0;
6556 if (y < 0) y = 0;
6557
6558 if (x == TELOPT_SB(TELOPT_NAWS).naws.x && /* Only send if changed */
6559 y == TELOPT_SB(TELOPT_NAWS).naws.y
6560 )
6561 return(0);
6562 TELOPT_SB(TELOPT_NAWS).naws.x = x; /* Remember the size */
6563 TELOPT_SB(TELOPT_NAWS).naws.y = y;
6564
6565 sb_out[i++] = (CHAR) IAC; /* Send the subnegotiation */
6566 sb_out[i++] = (CHAR) SB;
6567 sb_out[i++] = TELOPT_NAWS;
6568 sb_out[i++] = (CHAR) (x >> 8) & 0xff;
6569 if ((CHAR) sb_out[i-1] == (CHAR) IAC) /* IAC in data must be doubled */
6570 sb_out[i++] = (CHAR) IAC;
6571 sb_out[i++] = (CHAR) (x & 0xff);
6572 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6573 sb_out[i++] = (CHAR) IAC;
6574 sb_out[i++] = (CHAR) (y >> 8) & 0xff;
6575 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6576 sb_out[i++] = (CHAR) IAC;
6577 sb_out[i++] = (CHAR) (y & 0xff);
6578 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6579 sb_out[i++] = (CHAR) IAC;
6580 sb_out[i++] = (CHAR) IAC;
6581 sb_out[i++] = (CHAR) SE;
6582 #ifdef DEBUG
6583 if (deblog || tn_deb || debses) {
6584 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB NAWS ",
6585 ckitoa(x)," ",ckitoa(y)," IAC SE",
6586 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6587 }
6588 #endif /* DEBUG */
6589 #ifdef OS2
6590 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6591 #endif
6592 #ifdef DEBUG
6593 debug(F100,tn_msg_out,"",0);
6594 if (tn_deb || debses) tn_debug(tn_msg_out);
6595 #endif /* DEBUG */
6596 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6597 #ifdef OS2
6598 ReleaseTelnetMutex();
6599 #endif
6600 if (rc)
6601 return(-1);
6602 #endif /* NOLOCAL */
6603 return (0);
6604 }
6605 #endif /* CK_NAWS */
6606
6607 #ifdef TN_COMPORT
6608 static char * tnc_signature = NULL;
6609 static int tnc_ls_mask = 0;
6610 static int tnc_ls = 0;
6611 static int tnc_ms_mask = 255;
6612 static int tnc_ms = 0;
6613 static int tnc_oflow = 0;
6614 static int tnc_iflow = 0;
6615 static int tnc_bps = 0;
6616 static int tnc_datasize = 0;
6617 static int tnc_parity = 0;
6618 static int tnc_stopbit = 0;
6619 static int tnc_break = 0;
6620 static int tnc_dtr = 0;
6621 static int tnc_rts = 0;
6622 static int tnc_suspend_xmit = 0;
6623 static int tnc_bps_index = -1;
6624
6625 int
6626 #ifdef CK_ANSIC
tnc_init(void)6627 tnc_init(void)
6628 #else /* CK_ANSIC */
6629 tnc_init()
6630 #endif /* CK_ANSIC */
6631 /* tnc_init */ {
6632 debug(F100,"tnc_init","",0);
6633
6634 /* if (!IS_TELNET()) return(0); */
6635
6636 if (tnc_signature) {
6637 free(tnc_signature);
6638 tnc_signature = NULL;
6639 }
6640 tnc_ls_mask = 0;
6641 tnc_ls = 0;
6642 tnc_ms_mask = 255;
6643 tnc_ms = 0;
6644 tnc_oflow = 0;
6645 tnc_iflow = 0;
6646 tnc_bps = 0;
6647 tnc_datasize = 0;
6648 tnc_parity = 0;
6649 tnc_stopbit = 0;
6650 tnc_break = 0;
6651 tnc_dtr = 0;
6652 tnc_rts = 0;
6653 tnc_suspend_xmit = 0;
6654 tnc_bps_index = -1;
6655 return(0);
6656 }
6657
6658 int
6659 #ifdef CK_ANSIC
tn_sndcomport(void)6660 tn_sndcomport(void)
6661 #else /* CK_ANSIC */
6662 tn_sndcomport()
6663 #endif /* CK_ANSIC */
6664 /* tn_sndcomport */ {
6665 int baud, datasize, parity, stopsize, oflow, iflow;
6666 CONST char * signature;
6667
6668 /* if (!IS_TELNET()) return(0); */
6669
6670 debug(F100,"tnc_sndcomport","",0);
6671 signature = tnc_get_signature();
6672 baud = tnc_get_baud();
6673 datasize = tnc_get_datasize();
6674 parity = tnc_get_parity();
6675 stopsize = tnc_get_stopsize();
6676 oflow = tnc_get_oflow();
6677 iflow = tnc_get_iflow();
6678 tnc_set_ls_mask(255);
6679 tnc_set_ms_mask(255);
6680 return(0);
6681 }
6682
6683 int
6684 #ifdef CK_ANSIC
tnc_wait(CHAR * msg,int ms)6685 tnc_wait(CHAR * msg, int ms)
6686 #else /* CK_ANSIC */
6687 tnc_wait(msg, ms) CHAR * msg; int ms;
6688 #endif /* CK_ANSIC */
6689 /* tnc_wait */ {
6690 int rc, tn_wait_save = tn_wait_flg;
6691
6692 /* if (!IS_TELNET()) return(0); */
6693
6694 debug(F111,"tnc_wait","begin",ms);
6695 if ( ms )
6696 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 1;
6697 else
6698 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 1;
6699 tn_wait_flg = 1;
6700 rc = tn_wait((char *)msg);
6701 tn_push();
6702 debug(F110,"tnc_wait","end",0);
6703 tn_wait_flg = tn_wait_save;
6704 return(rc);
6705 }
6706
6707 /* Returns -1 on error, 0 on success */
6708 /* In order for this code to work, sb[len] == IAC */
6709
6710 int
6711 #ifdef CK_ANSIC
tnc_tn_sb(CHAR * sb,int len)6712 tnc_tn_sb(CHAR * sb, int len)
6713 #else
6714 tnc_tn_sb(sb, len) CHAR * sb; int len;
6715 #endif /* CK_ANSIC */
6716 /* tnc_tn_sb */ {
6717 if (ttnet != NET_TCPB) return(0);
6718 if (ttnproto != NP_TELNET) return(0);
6719 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
6720
6721 if (!sb) return(-1);
6722
6723 #ifdef CK_SSL
6724 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6725 return(0);
6726 }
6727 #endif /* CK_SSL */
6728
6729 debug(F111,"tnc_tn_sb","sb[0]",sb[0]);
6730 debug(F111,"tnc_tn_sb","len",len);
6731
6732 switch (sb[0]) {
6733 case TNC_C2S_SIGNATURE:
6734 case TNC_S2C_SIGNATURE:
6735 debug(F111,"tnc_tn_sb","signature",len);
6736 if (len == 1) {
6737 tnc_send_signature("Kermit Telnet Com Port Option");
6738 } else {
6739 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6740 if (tnc_signature)
6741 free(tnc_signature);
6742 tnc_signature = malloc(len);
6743 if (tnc_signature) {
6744 memcpy(tnc_signature,&sb[1],len-1);
6745 tnc_signature[len-1] = '\0';
6746 }
6747 }
6748 break;
6749
6750 case TNC_C2S_SET_BAUDRATE:
6751 case TNC_S2C_SET_BAUDRATE: {
6752 long baudrate;
6753 char * br = (char *)&baudrate;
6754 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6755 if (len == 2) {
6756 /* Actual behavior of the Access Server... */
6757 debug(F111,"tnc_tn_sb","baudrate index",sb[1]);
6758 tnc_bps_index = 1;
6759 switch (sb[1]) {
6760 case TNC_BPS_300:
6761 tnc_bps = 300;
6762 break;
6763 case TNC_BPS_600:
6764 tnc_bps = 600;
6765 break;
6766 case TNC_BPS_1200:
6767 tnc_bps = 1200;
6768 break;
6769 case TNC_BPS_2400:
6770 tnc_bps = 2400;
6771 break;
6772 case TNC_BPS_4800:
6773 tnc_bps = 4800;
6774 break;
6775 case TNC_BPS_9600:
6776 tnc_bps = 9600;
6777 break;
6778 case TNC_BPS_14400:
6779 tnc_bps = 14400;
6780 break;
6781 case TNC_BPS_19200:
6782 tnc_bps = 19200;
6783 break;
6784 case TNC_BPS_28800:
6785 tnc_bps = 28800;
6786 break;
6787 case TNC_BPS_38400:
6788 tnc_bps = 38400;
6789 break;
6790 case TNC_BPS_57600:
6791 tnc_bps = 57600;
6792 break;
6793 case TNC_BPS_115200:
6794 tnc_bps = 115200;
6795 break;
6796 case TNC_BPS_230400:
6797 tnc_bps = 230400;
6798 break;
6799 case TNC_BPS_460800:
6800 tnc_bps = 460800;
6801 break;
6802 default:
6803 tnc_bps = -1;
6804 }
6805 } else if (len == 5) {
6806 /* This section attempts to follow RFC 2217 */
6807 tnc_bps_index = 0;
6808 br[0] = sb[1];
6809 br[1] = sb[2];
6810 br[2] = sb[3];
6811 br[3] = sb[4];
6812 #ifdef datageneral
6813 /* AOS/VS doesn't have ntohl() but MV's are big-endian */
6814 tnc_bps = baudrate;
6815 #else
6816 tnc_bps = ntohl(baudrate);
6817 #endif /* datageneral */
6818 debug(F111,"tnc_tn_sb","baudrate rfc",tnc_bps);
6819 } else {
6820 debug(F111,"tnc_tn_sb","baudrate invalid len",len);
6821 return(-1);
6822 }
6823 break;
6824 }
6825 case TNC_C2S_SET_DATASIZE:
6826 case TNC_S2C_SET_DATASIZE:
6827 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6828 if (len < 2)
6829 return(-1);
6830 tnc_datasize = sb[1];
6831 debug(F111,"tnc_tn_sb","datasize",sb[1]);
6832 break;
6833
6834 case TNC_C2S_SET_PARITY:
6835 case TNC_S2C_SET_PARITY:
6836 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6837 if (len < 2)
6838 return(-1);
6839 tnc_parity = sb[1];
6840 debug(F111,"tnc_tn_sb","parity",sb[1]);
6841 break;
6842
6843 case TNC_C2S_SET_STOPSIZE:
6844 case TNC_S2C_SET_STOPSIZE:
6845 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6846 if (len < 2)
6847 return(-1);
6848 tnc_stopbit = sb[1];
6849 debug(F111,"tnc_tn_sb","stopsize",sb[1]);
6850 break;
6851
6852 case TNC_C2S_SET_CONTROL:
6853 case TNC_S2C_SET_CONTROL:
6854 if (len < 2) {
6855 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6856 return(-1);
6857 }
6858
6859 #ifdef COMMENT
6860 /* This line should be removed when testing is complete. */
6861 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6862 #endif /* COMMENT */
6863
6864 switch ( sb[1] ) {
6865 case TNC_CTL_OFLOW_REQUEST:
6866 /* determine local outbound flow control and send to peer */
6867 /* Cisco IOS returns 0 (TNC_CTL_OFLOW_REQUEST) when attempting */
6868 /* to set the inbound flow control if it is not supported */
6869 /* separately from outbound flow control. So must reset */
6870 /* wait for sb flag. */
6871 debug(F110,"tnc_tn_sb","oflow request",0);
6872 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6873 break;
6874 case TNC_CTL_OFLOW_NONE:
6875 case TNC_CTL_OFLOW_XON_XOFF:
6876 case TNC_CTL_OFLOW_RTS_CTS:
6877 case TNC_CTL_OFLOW_DCD:
6878 case TNC_CTL_OFLOW_DSR:
6879 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6880 tnc_oflow = sb[1];
6881 debug(F111,"tnc_tn_sb","oflow",sb[1]);
6882 break;
6883 case TNC_CTL_BREAK_REQUEST:
6884 /* determine local break state and send to peer */
6885 debug(F110,"tnc_tn_sb","break request",0);
6886 break;
6887 case TNC_CTL_BREAK_ON:
6888 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6889 tnc_break = 1;
6890 debug(F110,"tnc_tn_sb","break on",0);
6891 break;
6892
6893 case TNC_CTL_BREAK_OFF:
6894 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6895 tnc_break = 0;
6896 debug(F110,"tnc_tn_sb","break off",0);
6897 break;
6898
6899 case TNC_CTL_DTR_REQUEST:
6900 /* determine local dtr state and send to peer */
6901 debug(F110,"tnc_tn_sb","dtr request",0);
6902 break;
6903
6904 case TNC_CTL_DTR_ON:
6905 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6906 tnc_dtr = 1;
6907 debug(F110,"tnc_tn_sb","dtr on",0);
6908 break;
6909
6910 case TNC_CTL_DTR_OFF:
6911 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6912 tnc_dtr = 0;
6913 debug(F110,"tnc_tn_sb","dtr off",0);
6914 break;
6915
6916 case TNC_CTL_RTS_REQUEST:
6917 /* determine local rts state and send to peer */
6918 debug(F110,"tnc_tn_sb","rts request",0);
6919 break;
6920
6921 case TNC_CTL_RTS_ON:
6922 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6923 tnc_rts = 1;
6924 debug(F110,"tnc_tn_sb","rts on",0);
6925 break;
6926
6927 case TNC_CTL_RTS_OFF:
6928 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6929 tnc_rts = 0;
6930 debug(F110,"tnc_tn_sb","rts off",0);
6931 break;
6932
6933 case TNC_CTL_IFLOW_REQUEST:
6934 /* determine local inbound flow control and send to peer */
6935 debug(F110,"tnc_tn_sb","iflow request",0);
6936 break;
6937
6938 case TNC_CTL_IFLOW_NONE:
6939 case TNC_CTL_IFLOW_XON_XOFF:
6940 case TNC_CTL_IFLOW_RTS_CTS:
6941 case TNC_CTL_IFLOW_DTR:
6942 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6943 tnc_iflow = sb[1];
6944 debug(F111,"tnc_tn_sb","iflow",sb[1]);
6945 break;
6946 default:
6947 return(-1);
6948 }
6949 break;
6950
6951 case TNC_C2S_NOTIFY_LINESTATE:
6952 case TNC_S2C_SEND_LS:
6953 if (len < 2)
6954 return(-1);
6955 tnc_ls = sb[1];
6956 debug(F111,"tnc_tn_sb","linestate",sb[1]);
6957 if (tn_deb || debses) {
6958 if (tnc_ls & TNC_MS_DATA_READY )
6959 tn_debug(" ComPort Linestate Data Ready");
6960 if (tnc_ls & TNC_MS_OVERRUN_ERROR )
6961 tn_debug(" ComPort Linestate Overrun Error");
6962 if (tnc_ls & TNC_MS_PARITY_ERROR )
6963 tn_debug(" ComPort Linestate Parity Error");
6964 if (tnc_ls & TNC_MS_FRAME_ERROR )
6965 tn_debug(" ComPort Linestate Framing Error");
6966 if (tnc_ls & TNC_MS_BREAK_ERROR )
6967 tn_debug(" ComPort Linestate Break Detect Error");
6968 if (tnc_ls & TNC_MS_HR_EMPTY )
6969 tn_debug(" ComPort Linestate Holding Register Empty");
6970 if (tnc_ls & TNC_MS_SR_EMPTY )
6971 tn_debug(" ComPort Linestate Shift Register Empty");
6972 if (tnc_ls & TNC_MS_TIMEOUT_ERROR )
6973 tn_debug(" ComPort Linestate Timeout Error");
6974 }
6975 break;
6976
6977 case TNC_C2S_NOTIFY_MODEMSTATE:
6978 case TNC_S2C_SEND_MS:
6979 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
6980 if (len < 2)
6981 return(-1);
6982 tnc_ms = sb[1];
6983 debug(F111,"tnc_tn_sb","modemstate",sb[1]);
6984 if (tn_deb || debses) {
6985 if (tnc_ms & TNC_MS_CTS_DELTA )
6986 tn_debug(" ComPort Modemstate CTS State Change");
6987 if (tnc_ms & TNC_MS_DSR_DELTA )
6988 tn_debug(" ComPort Modemstate DSR State Change");
6989 if (tnc_ms & TNC_MS_EDGE_RING )
6990 tn_debug(" ComPort Modemstate Trailing Edge Ring Detector On");
6991 else
6992 tn_debug(" ComPort Modemstate Trailing Edge Ring Detector Off");
6993 if (tnc_ms & TNC_MS_RLSD_DELTA )
6994 tn_debug(" ComPort Modemstate RLSD State Change");
6995 if (tnc_ms & TNC_MS_CTS_SIG )
6996 tn_debug(" ComPort Modemstate CTS Signal On");
6997 else
6998 tn_debug(" ComPort Modemstate CTS Signal Off");
6999 if (tnc_ms & TNC_MS_DSR_SIG )
7000 tn_debug(" ComPort Modemstate DSR Signal On");
7001 else
7002 tn_debug(" ComPort Modemstate DSR Signal Off");
7003 if (tnc_ms & TNC_MS_RI_SIG )
7004 tn_debug(" ComPort Modemstate Ring Indicator On");
7005 else
7006 tn_debug(" ComPort Modemstate Ring Indicator Off");
7007 if (tnc_ms & TNC_MS_RLSD_SIG )
7008 tn_debug(" ComPort Modemstate RLSD Signal On");
7009 else
7010 tn_debug(" ComPort Modemstate RLSD Signal Off");
7011 }
7012 break;
7013
7014 case TNC_C2S_FLOW_SUSPEND:
7015 case TNC_S2C_FLOW_SUSPEND:
7016 debug(F110,"tnc_tn_sb","flow suspend",0);
7017 tnc_suspend_xmit = 1;
7018 break;
7019
7020 case TNC_C2S_FLOW_RESUME:
7021 case TNC_S2C_FLOW_RESUME:
7022 debug(F110,"tnc_tn_sb","flow resume",0);
7023 tnc_suspend_xmit = 0;
7024 break;
7025
7026 case TNC_C2S_SET_LS_MASK:
7027 case TNC_S2C_SET_LS_MASK:
7028 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
7029 if (len < 2)
7030 return(-1);
7031 debug(F111,"tnc_tn_sb","linestate mask",sb[1]);
7032 tnc_ls_mask = sb[1];
7033 break;
7034
7035 case TNC_C2S_SET_MS_MASK:
7036 case TNC_S2C_SET_MS_MASK:
7037 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
7038 if (len < 2)
7039 return(-1);
7040 debug(F111,"tnc_tn_sb","modemstate mask",sb[1]);
7041 tnc_ls_mask = sb[1];
7042 break;
7043
7044 case TNC_C2S_PURGE:
7045 case TNC_S2C_PURGE:
7046 if (len < 2)
7047 return(-1);
7048 debug(F111,"tnc_tn_sb","purge",sb[1]);
7049 switch ( sb[1] ) {
7050 case TNC_PURGE_RECEIVE:
7051 case TNC_PURGE_TRANSMIT:
7052 case TNC_PURGE_BOTH:
7053 /* purge local buffers */
7054 break;
7055 default:
7056 return(-1);
7057 }
7058 break;
7059 default:
7060 return(-1);
7061 }
7062 return(0);
7063 }
7064
7065 CONST char *
7066 #ifdef CK_ANSIC
tnc_get_signature(void)7067 tnc_get_signature(void)
7068 #else /* CK_ANSIC */
7069 tnc_get_signature()
7070 #endif /* CK_ANSIC */
7071 /* tnc_get_signature */ {
7072 /* send IAC SB COM-PORT SIGNATURE IAC SE */
7073 /* wait for response */
7074 int i = 0, rc;
7075
7076 if (ttnet != NET_TCPB) return(NULL);
7077 if (ttnproto != NP_TELNET) return(NULL);
7078
7079 if (!TELOPT_ME(TELOPT_COMPORT)) return(NULL);
7080
7081 #ifdef CK_SSL
7082 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7083 return(NULL);
7084 }
7085 #endif /* CK_SSL */
7086
7087 if ( tnc_signature )
7088 return(tnc_signature);
7089
7090 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7091 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7092 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7093 sb_out[i++] = TNC_C2S_SIGNATURE; /* Signature */
7094 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7095 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7096
7097 #ifdef DEBUG
7098 if (deblog || tn_deb || debses) {
7099 ckmakmsg(tn_msg_out,TN_MSG_LEN,
7100 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7101 " SIGNATURE IAC SE", NULL);
7102 }
7103 #endif /* DEBUG */
7104 #ifdef OS2
7105 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7106 #endif
7107 #ifdef DEBUG
7108 debug(F100,tn_msg_out,"",0);
7109 if (tn_deb || debses) tn_debug(tn_msg_out);
7110 #endif /* DEBUG */
7111 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7112 #ifdef OS2
7113 ReleaseTelnetMutex();
7114 #endif
7115 if (rc)
7116 return(NULL);
7117
7118 if (tnc_wait((CHAR *)"comport signature request",0) < 0) {
7119 tn_push();
7120 return(NULL);
7121 }
7122 debug(F110,"tnc_get_signature",tnc_signature,0);
7123 return(tnc_signature);
7124 }
7125
7126 int
7127 #ifdef CK_ANSIC
tnc_send_signature(char * signature)7128 tnc_send_signature(char * signature)
7129 #else /* CK_ANSIC */
7130 tnc_send_signature(signature) char * signature;
7131 #endif /* CK_ANSIC */
7132 /* tnc_send_signature */ {
7133 /* send IAC SB COM-PORT SIGNATURE <text> IAC SE */
7134 int i = 0, j = 0, rc;
7135
7136 debug(F110,"tnc_send_signature",signature,0);
7137
7138 if (!signature || !signature[0])
7139 return(0);
7140
7141 if (ttnet != NET_TCPB) return(0);
7142 if (ttnproto != NP_TELNET) return(0);
7143
7144 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7145
7146 #ifdef CK_SSL
7147 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7148 return(0);
7149 }
7150 #endif /* CK_SSL */
7151
7152 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7153 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7154 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7155 sb_out[i++] = TNC_C2S_SIGNATURE; /* Signature */
7156 for (; signature[j]; i++,j++)
7157 sb_out[i] = signature[j];
7158 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7159 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7160
7161 #ifdef DEBUG
7162 if (deblog || tn_deb || debses) {
7163 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7164 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7165 " SIGNATURE ", signature, " IAC SE", NULL,
7166 NULL,NULL,NULL,NULL,NULL,NULL);
7167 }
7168 #endif /* DEBUG */
7169 #ifdef OS2
7170 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7171 #endif
7172 #ifdef DEBUG
7173 debug(F100,tn_msg_out,"",0);
7174 if (tn_deb || debses) tn_debug(tn_msg_out);
7175 #endif /* DEBUG */
7176 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7177 #ifdef OS2
7178 ReleaseTelnetMutex();
7179 #endif
7180 if (rc)
7181 return(-1);
7182 return(0);
7183 }
7184
7185 int
7186 #ifdef CK_ANSIC
tnc_set_baud(long baud)7187 tnc_set_baud( long baud )
7188 #else /* CK_ANSIC */
7189 tnc_set_baud(baud) long baud;
7190 #endif /* CK_ANSIC */
7191 /* tnc_set_baud */ {
7192 /* send IAC SB COM-PORT SET-BAUD <value(4)> IAC SE */
7193 /* wait for response */
7194 /* 0 is used to request the current baud rate and */
7195 /* may not be sent by this func */
7196 /* return new host value */
7197
7198 /*
7199 * the above comes from the RFC. But that is not what I am seeing
7200 * instead I appear to be seeing to following:
7201 *
7202 * Value Baud
7203 * 1 ?
7204 * 2 ?
7205 * 3 300
7206 * 4 600
7207 * 5 1200
7208 * 6 2400
7209 * 7 4800 ?
7210 * 8 9600
7211 * 9 ?
7212 * 10 19200 ?
7213 * 11 ?
7214 * 12 38400
7215 * 13 57600 ?
7216 * 14 115200
7217 * 15 230400 ?
7218 * 16 460800 ?
7219 */
7220
7221 int i = 0, rc;
7222 #ifdef datageneral
7223 /* AOS/VS doesn't have htonl() but MV's are big-endian */
7224 long net_baud = baud;
7225 #else
7226 long net_baud = htonl(baud);
7227 #endif /* datageneral */
7228 CHAR b;
7229
7230 debug(F111,"tnc_set_baud","begin",baud);
7231
7232 if (ttnet != NET_TCPB) return(0);
7233 if (ttnproto != NP_TELNET) return(0);
7234
7235 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7236
7237 #ifdef CK_SSL
7238 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7239 return(0);
7240 }
7241 #endif /* CK_SSL */
7242
7243 if (baud <= 0)
7244 return(0);
7245
7246 if ( net_baud != 0 && net_baud == tnc_bps)
7247 return(tnc_bps);
7248
7249 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7250 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7251 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7252 sb_out[i++] = TNC_C2S_SET_BAUDRATE; /* Set Baud Rate */
7253
7254 if (tnc_bps_index) {
7255 /* IOS Access Server */
7256 if (baud <= 300)
7257 b = TNC_BPS_300;
7258 else if (baud <= 600)
7259 b = TNC_BPS_600;
7260 else if (baud <= 1200)
7261 b = TNC_BPS_1200;
7262 else if (baud <= 2400)
7263 b = TNC_BPS_2400;
7264 else if (baud <= 4800)
7265 b = TNC_BPS_4800;
7266 else if (baud <= 9600)
7267 b = TNC_BPS_9600;
7268 else if (baud <= 14400)
7269 b = TNC_BPS_14400;
7270 else if (baud <= 19200)
7271 b = TNC_BPS_19200;
7272 else if (baud <= 28800)
7273 b = TNC_BPS_28800;
7274 else if (baud <= 38400)
7275 b = TNC_BPS_38400;
7276 else if (baud <= 57600)
7277 b = TNC_BPS_57600;
7278 else if (baud <= 115200)
7279 b = TNC_BPS_115200;
7280 else if (baud <= 230400)
7281 b = TNC_BPS_230400;
7282 else
7283 b = TNC_BPS_460800;
7284 sb_out[i++] = b;
7285 } else {
7286 /* RFC 2217 */
7287 sb_out[i++] = ((char *)&net_baud)[0];
7288 sb_out[i++] = ((char *)&net_baud)[1];
7289 sb_out[i++] = ((char *)&net_baud)[2];
7290 sb_out[i++] = ((char *)&net_baud)[3];
7291 }
7292 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7293 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7294
7295 #ifdef DEBUG
7296 if (deblog || tn_deb || debses) {
7297 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7298 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7299 " SET-BAUD-RATE ", ckltoa(baud)," IAC SE", NULL,
7300 NULL,NULL,NULL,NULL,NULL,NULL);
7301 }
7302 #endif /* DEBUG */
7303
7304 #ifdef OS2
7305 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7306 #endif
7307 #ifdef DEBUG
7308 debug(F100,tn_msg_out,"",0);
7309 if (tn_deb || debses) tn_debug(tn_msg_out);
7310 #endif /* DEBUG */
7311 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7312 #ifdef OS2
7313 ReleaseTelnetMutex();
7314 #endif
7315 if (rc)
7316 return(-1);
7317
7318 if (tnc_wait((CHAR *)"comport set baud rate",0) < 0) {
7319 tn_push();
7320 return(-1);
7321 }
7322 debug(F111,"tnc_set_baud","end",tnc_bps);
7323 return(tnc_bps);
7324 }
7325
7326 int
7327 #ifdef CK_ANSIC
tnc_get_baud(void)7328 tnc_get_baud(void)
7329 #else /* CK_ANSIC */
7330 tnc_get_baud()
7331 #endif /* CK_ANSIC */
7332 /* tnc_get_baud */ {
7333 /* send IAC SB COM-PORT SET-BAUD <value(4)=0> IAC SE */
7334 /* wait for response */
7335 int i = 0, rc;
7336
7337 debug(F110,"tnc_get_baud","begin",0);
7338
7339 if (ttnet != NET_TCPB) return(0);
7340 if (ttnproto != NP_TELNET) return(0);
7341
7342 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7343
7344 #ifdef CK_SSL
7345 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7346 return(0);
7347 }
7348 #endif /* CK_SSL */
7349
7350 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7351 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7352 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7353 sb_out[i++] = TNC_C2S_SET_BAUDRATE; /* Set Baud Rate */
7354
7355 if (tnc_bps_index > 0) {
7356 /* Access Server */
7357 sb_out[i++] = 0;
7358 } else {
7359 /* RFC 2217 */
7360 sb_out[i++] = 0;
7361 sb_out[i++] = 0;
7362 sb_out[i++] = 0;
7363 sb_out[i++] = 0;
7364 }
7365 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7366 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7367
7368 #ifdef DEBUG
7369 if (deblog || tn_deb || debses) {
7370 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7371 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7372 " SET-BAUD-RATE ", ckltoa(0)," IAC SE", NULL,
7373 NULL,NULL,NULL,NULL,NULL,NULL);
7374 }
7375 #endif /* DEBUG */
7376 #ifdef OS2
7377 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7378 #endif
7379 #ifdef DEBUG
7380 debug(F100,tn_msg_out,"",0);
7381 if (tn_deb || debses) tn_debug(tn_msg_out);
7382 #endif /* DEBUG */
7383 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7384 #ifdef OS2
7385 ReleaseTelnetMutex();
7386 #endif
7387 if (rc)
7388 return(-1);
7389
7390 if (tnc_wait((CHAR *)"comport get baud rate",0) < 0) {
7391 tn_push();
7392 return(-1);
7393 }
7394 debug(F111,"tnc_get_baud","end",tnc_bps);
7395 return(tnc_bps);
7396 }
7397
7398 int
7399 #ifdef CK_ANSIC
tnc_set_datasize(int datasize)7400 tnc_set_datasize(int datasize)
7401 #else /* CK_ANSIC */
7402 tnc_set_datasize(datasize) int datasize;
7403 #endif /* CK_ANSIC */
7404 /* tnc_set_datasize */ {
7405 /* IAC SB COM-PORT SET_DATASIZE <value(1)> IAC SE */
7406 /* Valid <value>s are 5 through 8 */
7407 /* Wait for response */
7408 /* return new host value */
7409
7410 int i = 0, rc;
7411
7412 debug(F111,"tnc_set_datasize","begin",datasize);
7413
7414 if (ttnet != NET_TCPB) return(0);
7415 if (ttnproto != NP_TELNET) return(0);
7416
7417 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7418
7419 #ifdef CK_SSL
7420 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7421 return(0);
7422 }
7423 #endif /* CK_SSL */
7424
7425 if ( !(datasize >= 5 && datasize <= 8) )
7426 return(0);
7427
7428 if ( datasize != 0 && datasize == tnc_datasize )
7429 return(tnc_datasize);
7430
7431 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7432 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7433 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7434 sb_out[i++] = TNC_C2S_SET_DATASIZE; /* Set DataSize */
7435 sb_out[i++] = (unsigned char)(datasize & 0xFF);
7436 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7437 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7438
7439 #ifdef DEBUG
7440 if (deblog || tn_deb || debses) {
7441 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7442 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7443 " SET-DATASIZE ", ckitoa(datasize)," IAC SE", NULL,
7444 NULL,NULL,NULL,NULL,NULL,NULL);
7445 }
7446 #endif /* DEBUG */
7447 #ifdef OS2
7448 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7449 #endif
7450 #ifdef DEBUG
7451 debug(F100,tn_msg_out,"",0);
7452 if (tn_deb || debses) tn_debug(tn_msg_out);
7453 #endif /* DEBUG */
7454 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7455 #ifdef OS2
7456 ReleaseTelnetMutex();
7457 #endif
7458 if (rc)
7459 return(-1);
7460
7461 if (tnc_wait((CHAR *)"comport set datasize",0) < 0) {
7462 tn_push();
7463 return(-1);
7464 }
7465 debug(F111,"tnc_set_datasize","end",tnc_datasize);
7466 return(tnc_datasize);
7467 }
7468
7469 int
7470 #ifdef CK_ANSIC
tnc_get_datasize(void)7471 tnc_get_datasize(void)
7472 #else /* CK_ANSIC */
7473 tnc_get_datasize()
7474 #endif /* CK_ANSIC */
7475 /* tnc_get_datasize */ {
7476 /* IAC SB COM-PORT SET_DATASIZE <value(1)=0> IAC SE */
7477 /* Wait for response */
7478 int i = 0, rc;
7479
7480 debug(F110,"tnc_get_datasize","begin",0);
7481
7482 if (ttnet != NET_TCPB) return(0);
7483 if (ttnproto != NP_TELNET) return(0);
7484
7485 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7486
7487 #ifdef CK_SSL
7488 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7489 return(0);
7490 }
7491 #endif /* CK_SSL */
7492
7493 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7494 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7495 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7496 sb_out[i++] = TNC_C2S_SET_DATASIZE; /* Set DataSize */
7497 sb_out[i++] = 0;
7498 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7499 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7500
7501 #ifdef DEBUG
7502 if (deblog || tn_deb || debses) {
7503 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7504 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7505 " SET-DATASIZE ", ckltoa(0)," IAC SE", NULL,
7506 NULL,NULL,NULL,NULL,NULL,NULL);
7507 }
7508 #endif /* DEBUG */
7509 #ifdef OS2
7510 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7511 #endif
7512 #ifdef DEBUG
7513 debug(F100,tn_msg_out,"",0);
7514 if (tn_deb || debses) tn_debug(tn_msg_out);
7515 #endif /* DEBUG */
7516 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7517 #ifdef OS2
7518 ReleaseTelnetMutex();
7519 #endif
7520 if (rc)
7521 return(-1);
7522
7523 if (tnc_wait((CHAR *)"comport get datasize",0) < 0) {
7524 tn_push();
7525 return(-1);
7526 }
7527 debug(F111,"tnc_get_datasize","end",tnc_datasize);
7528 return(tnc_datasize);
7529 }
7530
7531 int
7532 #ifdef CK_ANSIC
tnc_set_parity(int parity)7533 tnc_set_parity(int parity)
7534 #else /* CK_ANSIC */
7535 tnc_set_parity(parity) int parity;
7536 #endif /* CK_ANSIC */
7537 /* tnc_set_parity */ {
7538 /* IAC SB COM-PORT SET_PARITY <value(1)> IAC SE */
7539 /* Value Parity
7540 * 1 None
7541 * 2 Odd
7542 * 3 Even
7543 * 4 Mark
7544 * 5 Space
7545 */
7546 /* Wait for response. Return new host value. */
7547 int i = 0, rc;
7548
7549 debug(F110,"tnc_set_parity","begin",parity);
7550
7551 if (ttnet != NET_TCPB) return(0);
7552 if (ttnproto != NP_TELNET) return(0);
7553
7554 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7555
7556 #ifdef CK_SSL
7557 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7558 return(0);
7559 }
7560 #endif /* CK_SSL */
7561
7562 if ( !(parity >= 1 && parity <= 5) )
7563 return(0);
7564
7565 if ( parity != 0 && parity == tnc_parity )
7566 return(tnc_parity);
7567
7568 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7569 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7570 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7571 sb_out[i++] = TNC_C2S_SET_PARITY; /* Set Parity */
7572 sb_out[i++] = (unsigned char)(parity & 0xFF);
7573 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7574 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7575
7576 #ifdef DEBUG
7577 if (deblog || tn_deb || debses) {
7578 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7579 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7580 " SET-PARITY ", ckitoa(parity)," IAC SE", NULL,
7581 NULL,NULL,NULL,NULL,NULL,NULL);
7582 }
7583 #endif /* DEBUG */
7584 #ifdef OS2
7585 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7586 #endif
7587 #ifdef DEBUG
7588 debug(F100,tn_msg_out,"",0);
7589 if (tn_deb || debses) tn_debug(tn_msg_out);
7590 #endif /* DEBUG */
7591 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7592 #ifdef OS2
7593 ReleaseTelnetMutex();
7594 #endif
7595 if (rc)
7596 return(-1);
7597
7598 if (tnc_wait((CHAR *)"comport set parity",0) < 0) {
7599 tn_push();
7600 return(-1);
7601 }
7602 debug(F111,"tnc_set_parity","end",tnc_parity);
7603 return(tnc_parity);
7604 }
7605
7606 int
7607 #ifdef CK_ANSIC
tnc_get_parity(void)7608 tnc_get_parity(void)
7609 #else /* CK_ANSIC */
7610 tnc_get_parity()
7611 #endif /* CK_ANSIC */
7612 /* tnc_get_parity */ {
7613 /* IAC SB COM-PORT SET_PARITY <value(1)=0> IAC SE */
7614 /* wait for response */
7615 int i = 0, rc;
7616
7617 debug(F110,"tnc_get_parity","begin",0);
7618 if (ttnet != NET_TCPB) return(0);
7619 if (ttnproto != NP_TELNET) return(0);
7620
7621 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7622
7623 #ifdef CK_SSL
7624 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7625 return(0);
7626 }
7627 #endif /* CK_SSL */
7628
7629 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7630 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7631 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7632 sb_out[i++] = TNC_C2S_SET_PARITY; /* Set Parity */
7633 sb_out[i++] = 0;
7634 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7635 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7636
7637 #ifdef DEBUG
7638 if (deblog || tn_deb || debses) {
7639 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7640 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7641 " SET-PARITY ", ckitoa(0)," IAC SE", NULL,
7642 NULL,NULL,NULL,NULL,NULL,NULL);
7643 }
7644 #endif /* DEBUG */
7645 #ifdef OS2
7646 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7647 #endif
7648 #ifdef DEBUG
7649 debug(F100,tn_msg_out,"",0);
7650 if (tn_deb || debses) tn_debug(tn_msg_out);
7651 #endif /* DEBUG */
7652 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7653 #ifdef OS2
7654 ReleaseTelnetMutex();
7655 #endif
7656 if (rc)
7657 return(-1);
7658
7659 if (tnc_wait((CHAR *)"comport get parity",0) < 0) {
7660 tn_push();
7661 return(-1);
7662 }
7663 debug(F111,"tnc_get_parity","end",tnc_parity);
7664 return(tnc_parity);
7665 }
7666
7667 int
7668 #ifdef CK_ANSIC
tnc_set_stopsize(int stopsize)7669 tnc_set_stopsize(int stopsize)
7670 #else /* CK_ANSIC */
7671 tnc_set_stopsize(stopsize) int stopsize;
7672 #endif /* CK_ANSIC */
7673 /* tnc_set_stopsize */ {
7674 /* IAC SB COM-PORT SET_STOPSIZE <value(1)> IAC SE */
7675 /* Value Stop Bit Size
7676 * 1 1
7677 * 2 2
7678 * 3 1.5
7679 */
7680 /* Wait for response. Return new host value. */
7681 int i = 0, rc;
7682
7683 debug(F111,"tnc_set_stopsize","begin",stopsize);
7684 if (ttnet != NET_TCPB) return(0);
7685 if (ttnproto != NP_TELNET) return(0);
7686
7687 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7688
7689 #ifdef CK_SSL
7690 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7691 return(0);
7692 }
7693 #endif /* CK_SSL */
7694
7695 if (!(stopsize >= 1 && stopsize <= 3) )
7696 return(0);
7697
7698 if ( stopsize != 0 && stopsize == tnc_stopbit )
7699 return(tnc_stopbit);
7700
7701 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7702 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7703 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7704 sb_out[i++] = TNC_C2S_SET_STOPSIZE; /* Set Stop Bits */
7705 sb_out[i++] = (unsigned char)(stopsize & 0xFF);
7706 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7707 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7708
7709 #ifdef DEBUG
7710 if (deblog || tn_deb || debses) {
7711 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7712 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7713 " SET-STOPSIZE ", ckitoa(stopsize)," IAC SE", NULL,
7714 NULL,NULL,NULL,NULL,NULL,NULL);
7715 }
7716 #endif /* DEBUG */
7717 #ifdef OS2
7718 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7719 #endif
7720 #ifdef DEBUG
7721 debug(F100,tn_msg_out,"",0);
7722 if (tn_deb || debses) tn_debug(tn_msg_out);
7723 #endif /* DEBUG */
7724 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7725 #ifdef OS2
7726 ReleaseTelnetMutex();
7727 #endif
7728 if (rc)
7729 return(-1);
7730
7731 if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
7732 tn_push();
7733 return(-1);
7734 }
7735 debug(F111,"tnc_set_stopsize","end",tnc_stopbit);
7736 return(tnc_stopbit);
7737 }
7738
7739 int
7740 #ifdef CK_ANSIC
tnc_get_stopsize(void)7741 tnc_get_stopsize(void)
7742 #else /* CK_ANSIC */
7743 tnc_get_stopsize()
7744 #endif /* CK_ANSIC */
7745 /* tnc_get_stopsize */ {
7746 /* IAC SB COM-PORT SET_STOPSIZE <value(1)=0> IAC SE */
7747 /* Wait for response */
7748 int i = 0, rc;
7749
7750 debug(F110,"tnc_get_stopsize","begin",0);
7751 if (ttnet != NET_TCPB) return(0);
7752 if (ttnproto != NP_TELNET) return(0);
7753
7754 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7755
7756 #ifdef CK_SSL
7757 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7758 return(0);
7759 }
7760 #endif /* CK_SSL */
7761
7762 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7763 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7764 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7765 sb_out[i++] = TNC_C2S_SET_STOPSIZE; /* Set Stop Bits */
7766 sb_out[i++] = 0;
7767 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7768 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7769
7770 #ifdef DEBUG
7771 if (deblog || tn_deb || debses) {
7772 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7773 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7774 " SET-STOPSIZE ", ckitoa(0)," IAC SE", NULL,
7775 NULL,NULL,NULL,NULL,NULL,NULL);
7776 }
7777 #endif /* DEBUG */
7778 #ifdef OS2
7779 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7780 #endif
7781 #ifdef DEBUG
7782 debug(F100,tn_msg_out,"",0);
7783 if (tn_deb || debses) tn_debug(tn_msg_out);
7784 #endif /* DEBUG */
7785 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7786 #ifdef OS2
7787 ReleaseTelnetMutex();
7788 #endif
7789 if (rc)
7790 return(-1);
7791
7792 if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
7793 tn_push();
7794 return(-1);
7795 }
7796 debug(F111,"tnc_get_stopsize","end",tnc_stopbit);
7797 return(tnc_stopbit);
7798 }
7799
7800 int
7801 #ifdef CK_ANSIC
tnc_set_oflow(int control)7802 tnc_set_oflow(int control)
7803 #else /* CK_ANSIC */
7804 tnc_set_oflow(control) int control;
7805 #endif /* CK_ANSIC */
7806 /* tnc_set_oflow */ {
7807 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7808 /* Value Flow Control
7809 * 1 No Flow Control
7810 * 2 Xon/Xoff
7811 * 3 Rts/Cts
7812 * 17 DCD
7813 * 19 DSR
7814 */
7815 /* wait for response, return new host value. */
7816 int i = 0, rc;
7817
7818 debug(F111,"tnc_set_oflow","begin",control);
7819 if (ttnet != NET_TCPB) return(0);
7820 if (ttnproto != NP_TELNET) return(0);
7821
7822 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7823
7824 #ifdef CK_SSL
7825 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7826 return(0);
7827 }
7828 #endif /* CK_SSL */
7829
7830 if (control != 1 && control != 2 && control != 3 &&
7831 control != 17 && control != 19)
7832 return(0);
7833
7834 if ( control != 0 && control == tnc_oflow )
7835 return(tnc_oflow);
7836
7837 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7838 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7839 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7840 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7841 sb_out[i++] = (unsigned char)(control & 0xFF);
7842 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7843 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7844
7845 #ifdef DEBUG
7846 if (deblog || tn_deb || debses) {
7847 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7848 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7849 " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
7850 NULL,NULL,NULL,NULL,NULL,NULL);
7851 }
7852 #endif /* DEBUG */
7853 #ifdef OS2
7854 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7855 #endif
7856 #ifdef DEBUG
7857 debug(F100,tn_msg_out,"",0);
7858 if (tn_deb || debses) tn_debug(tn_msg_out);
7859 #endif /* DEBUG */
7860 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7861 #ifdef OS2
7862 ReleaseTelnetMutex();
7863 #endif
7864 if (rc)
7865 return(-1);
7866
7867 if (tnc_wait((CHAR *)"comport set outbound flow control",0) < 0) {
7868 tn_push();
7869 return(-1);
7870 }
7871 debug(F111,"tnc_set_oflow","end",tnc_oflow);
7872 return(tnc_oflow);
7873 }
7874
7875 int
7876 #ifdef CK_ANSIC
tnc_get_oflow(void)7877 tnc_get_oflow(void)
7878 #else /* CK_ANSIC */
7879 tnc_get_oflow()
7880 #endif /* CK_ANSIC */
7881 /* tnc_get_oflow */ {
7882 /* IAC SB COM_PORT SET_CONTROL <value(1)=0> IAC SE */
7883 /* wait for response */
7884 int i = 0, rc;
7885
7886 debug(F110,"tnc_get_oflow","begin",0);
7887 if (ttnet != NET_TCPB) return(0);
7888 if (ttnproto != NP_TELNET) return(0);
7889
7890 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7891
7892 #ifdef CK_SSL
7893 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7894 return(0);
7895 }
7896 #endif /* CK_SSL */
7897
7898 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7899 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7900 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7901 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7902 sb_out[i++] = TNC_CTL_OFLOW_REQUEST;
7903 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7904 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7905
7906 #ifdef DEBUG
7907 if (deblog || tn_deb || debses) {
7908 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7909 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7910 " SET-CONTROL ",
7911 ckitoa(TNC_CTL_OFLOW_REQUEST),
7912 " IAC SE", NULL,
7913 NULL,NULL,NULL,NULL,NULL,NULL);
7914 }
7915 #endif /* DEBUG */
7916 #ifdef OS2
7917 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7918 #endif
7919 #ifdef DEBUG
7920 debug(F100,tn_msg_out,"",0);
7921 if (tn_deb || debses) tn_debug(tn_msg_out);
7922 #endif /* DEBUG */
7923 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7924 #ifdef OS2
7925 ReleaseTelnetMutex();
7926 #endif
7927 if (rc)
7928 return(-1);
7929
7930 if (tnc_wait((CHAR *)"comport get outbound flow control",0) < 0) {
7931 tn_push();
7932 return(-1);
7933 }
7934 debug(F111,"tnc_get_oflow","end",tnc_oflow);
7935 return(tnc_oflow);
7936 }
7937
7938 int
7939 #ifdef CK_ANSIC
tnc_set_iflow(int control)7940 tnc_set_iflow(int control)
7941 #else /* CK_ANSIC */
7942 tnc_set_iflow(control) int control;
7943 #endif /* CK_ANSIC */
7944 /* tnc_set_iflow */ {
7945 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7946 /* Value Flow Control
7947 * 14 No Flow Control
7948 * 15 Xon/Xoff
7949 * 16 Rts/Cts
7950 * 18 DTR
7951 */
7952 /* wait for response, return new host value. */
7953 int i = 0, rc;
7954
7955 debug(F111,"tnc_set_iflow","begin",control);
7956 if (ttnet != NET_TCPB) return(0);
7957 if (ttnproto != NP_TELNET) return(0);
7958
7959 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7960
7961 #ifdef CK_SSL
7962 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7963 return(0);
7964 }
7965 #endif /* CK_SSL */
7966
7967 if (control != 14 && control != 15 && control != 16 && control != 18)
7968 return(0);
7969
7970 if ( control != 0 && control == tnc_iflow )
7971 return(tnc_iflow);
7972
7973 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7974 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7975 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7976 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7977 sb_out[i++] = (unsigned char)(control & 0xFF);
7978 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7979 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7980
7981 #ifdef DEBUG
7982 if (deblog || tn_deb || debses) {
7983 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7984 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7985 " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
7986 NULL,NULL,NULL,NULL,NULL,NULL);
7987 }
7988 #endif /* DEBUG */
7989 #ifdef OS2
7990 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7991 #endif
7992 #ifdef DEBUG
7993 debug(F100,tn_msg_out,"",0);
7994 if (tn_deb || debses) tn_debug(tn_msg_out);
7995 #endif /* DEBUG */
7996 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7997 #ifdef OS2
7998 ReleaseTelnetMutex();
7999 #endif
8000 if (rc)
8001 return(-1);
8002
8003 if (tnc_wait((CHAR *)"comport set inbound flow control",0) < 0) {
8004 tn_push();
8005 return(-1);
8006 }
8007 debug(F111,"tnc_set_iflow","end",tnc_iflow);
8008 return(tnc_iflow);
8009 }
8010
8011 int
8012 #ifdef CK_ANSIC
tnc_get_iflow(void)8013 tnc_get_iflow(void)
8014 #else /* CK_ANSIC */
8015 tnc_get_iflow()
8016 #endif /* CK_ANSIC */
8017 /* tnc_get_iflow */ {
8018 /* IAC SB COM_PORT SET_CONTROL <value(1)=13> IAC SE */
8019 /* wait for response */
8020 int i = 0, rc;
8021
8022 debug(F110,"tnc_get_iflow","begin",0);
8023 if (ttnet != NET_TCPB) return(0);
8024 if (ttnproto != NP_TELNET) return(0);
8025
8026 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8027
8028 #ifdef CK_SSL
8029 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8030 return(0);
8031 }
8032 #endif /* CK_SSL */
8033
8034 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8035 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8036 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8037 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8038 sb_out[i++] = TNC_CTL_IFLOW_REQUEST;
8039 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8040 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8041
8042 #ifdef DEBUG
8043 if (deblog || tn_deb || debses) {
8044 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8045 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8046 " SET-CONTROL ",
8047 ckitoa(TNC_CTL_IFLOW_REQUEST),
8048 " IAC SE", NULL,
8049 NULL,NULL,NULL,NULL,NULL,NULL);
8050 }
8051 #endif /* DEBUG */
8052 #ifdef OS2
8053 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8054 #endif
8055 #ifdef DEBUG
8056 debug(F100,tn_msg_out,"",0);
8057 if (tn_deb || debses) tn_debug(tn_msg_out);
8058 #endif /* DEBUG */
8059 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8060 #ifdef OS2
8061 ReleaseTelnetMutex();
8062 #endif
8063 if (rc)
8064 return(-1);
8065
8066 if (tnc_wait((CHAR *)"comport get inbound flow control",0) < 0) {
8067 tn_push();
8068 return(-1);
8069 }
8070 debug(F111,"tnc_get_iflow","end",tnc_iflow);
8071 return(tnc_iflow);
8072 }
8073
8074 int
8075 #ifdef CK_ANSIC
tnc_set_break_state(int onoff)8076 tnc_set_break_state(int onoff)
8077 #else /* CK_ANSIC */
8078 tnc_set_break_state(onoff) int onoff;
8079 #endif /* CK_ANSIC */
8080 /* tnc_set_break_state */ {
8081 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8082 /* Value Break State
8083 * 5 On
8084 * 6 Off
8085 */
8086 /* wait for response, return new host value. */
8087 int i = 0, rc;
8088
8089 debug(F111,"tnc_set_break_state","begin",onoff);
8090 if (ttnet != NET_TCPB) return(0);
8091 if (ttnproto != NP_TELNET) return(0);
8092
8093 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8094
8095 #ifdef CK_SSL
8096 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8097 return(0);
8098 }
8099 #endif /* CK_SSL */
8100
8101 if ( onoff != 0 && onoff == tnc_break )
8102 return(tnc_break);
8103
8104 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8105 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8106 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8107 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8108 sb_out[i++] = onoff ?
8109 TNC_CTL_BREAK_ON : TNC_CTL_BREAK_OFF;
8110 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8111 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8112
8113 #ifdef DEBUG
8114 if (deblog || tn_deb || debses) {
8115 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8116 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8117 " SET-CONTROL ",
8118 onoff ? "BREAK-ON" : "BREAK-OFF",
8119 " IAC SE", NULL,
8120 NULL,NULL,NULL,NULL,NULL,NULL);
8121 }
8122 #endif /* DEBUG */
8123 #ifdef OS2
8124 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8125 #endif
8126 #ifdef DEBUG
8127 debug(F100,tn_msg_out,"",0);
8128 if (tn_deb || debses) tn_debug(tn_msg_out);
8129 #endif /* DEBUG */
8130 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8131 #ifdef OS2
8132 ReleaseTelnetMutex();
8133 #endif
8134 if (rc)
8135 return(-1);
8136
8137 if (tnc_wait((CHAR *)"comport set break state",0) < 0) {
8138 tn_push();
8139 return(-1);
8140 }
8141 debug(F111,"tnc_set_break_state","end",tnc_break);
8142 return(tnc_break);
8143 }
8144
8145 int
8146 #ifdef CK_ANSIC
tnc_get_break_state(void)8147 tnc_get_break_state(void)
8148 #else /* CK_ANSIC */
8149 tnc_get_break_state()
8150 #endif /* CK_ANSIC */
8151 /* tnc_get_break_state */ {
8152 /* IAC SB COM_PORT SET_CONTROL <value(1)=4> IAC SE */
8153 /* wait for response */
8154 int i = 0, rc;
8155
8156 debug(F110,"tnc_get_break_state","begin",0);
8157 if (ttnet != NET_TCPB) return(0);
8158 if (ttnproto != NP_TELNET) return(0);
8159
8160 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8161
8162 #ifdef CK_SSL
8163 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8164 return(0);
8165 }
8166 #endif /* CK_SSL */
8167
8168 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8169 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8170 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8171 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8172 sb_out[i++] = TNC_CTL_BREAK_REQUEST;
8173 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8174 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8175
8176 #ifdef DEBUG
8177 if (deblog || tn_deb || debses) {
8178 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8179 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8180 " SET-CONTROL ",
8181 "BREAK-REQUEST",
8182 " IAC SE", NULL,
8183 NULL,NULL,NULL,NULL,NULL,NULL);
8184 }
8185 #endif /* DEBUG */
8186 #ifdef OS2
8187 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8188 #endif
8189 #ifdef DEBUG
8190 debug(F100,tn_msg_out,"",0);
8191 if (tn_deb || debses) tn_debug(tn_msg_out);
8192 #endif /* DEBUG */
8193 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8194 #ifdef OS2
8195 ReleaseTelnetMutex();
8196 #endif
8197 if (rc)
8198 return(-1);
8199
8200 if (tnc_wait((CHAR *)"comport get break state",0) < 0) {
8201 tn_push();
8202 return(-1);
8203 }
8204 debug(F111,"tnc_get_break_state","end",tnc_break);
8205 return(tnc_break);
8206 }
8207
8208 int
8209 #ifdef CK_ANSIC
tnc_set_dtr_state(int onoff)8210 tnc_set_dtr_state(int onoff)
8211 #else /* CK_ANSIC */
8212 tnc_set_dtr_state(onoff) int onoff;
8213 #endif /* CK_ANSIC */
8214 /* tnc_set_dtr_state */ {
8215 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8216 /* Value Dtr State
8217 * 8 On
8218 * 9 Off
8219 */
8220 /* wait for response, return new host value. */
8221 int i = 0, rc;
8222
8223 debug(F111,"tnc_set_dtr_state","begin",onoff);
8224 if (ttnet != NET_TCPB) return(0);
8225 if (ttnproto != NP_TELNET) return(0);
8226
8227 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8228
8229 #ifdef CK_SSL
8230 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8231 return(0);
8232 }
8233 #endif /* CK_SSL */
8234
8235 if ( onoff != 0 && onoff == tnc_dtr )
8236 return(tnc_dtr);
8237
8238 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8239 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8240 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8241 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8242 sb_out[i++] = onoff ?
8243 TNC_CTL_DTR_ON : TNC_CTL_DTR_OFF;
8244 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8245 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8246
8247 #ifdef DEBUG
8248 if (deblog || tn_deb || debses) {
8249 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8250 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8251 " SET-CONTROL ",
8252 onoff ? "DTR-ON" : "DTR-OFF",
8253 " IAC SE", NULL,
8254 NULL,NULL,NULL,NULL,NULL,NULL);
8255 }
8256 #endif /* DEBUG */
8257 #ifdef OS2
8258 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8259 #endif
8260 #ifdef DEBUG
8261 debug(F100,tn_msg_out,"",0);
8262 if (tn_deb || debses) tn_debug(tn_msg_out);
8263 #endif /* DEBUG */
8264 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8265 #ifdef OS2
8266 ReleaseTelnetMutex();
8267 #endif
8268 if (rc)
8269 return(-1);
8270
8271 if (tnc_wait((CHAR *)"comport set dtr state",0) < 0) {
8272 tn_push();
8273 return(-1);
8274 }
8275 debug(F111,"tnc_set_dtr_state","end",tnc_dtr);
8276 return(tnc_dtr);
8277 }
8278
8279 int
8280 #ifdef CK_ANSIC
tnc_get_dtr_state(void)8281 tnc_get_dtr_state(void)
8282 #else /* CK_ANSIC */
8283 tnc_get_dtr_state()
8284 #endif /* CK_ANSIC */
8285 /* tnc_get_dtr_state */ {
8286 /* IAC SB COM_PORT SET_CONTROL <value(1)=7> IAC SE */
8287 /* wait for response */
8288 int i = 0, rc;
8289
8290 debug(F110,"tnc_get_dtr_state","begin",0);
8291 if (ttnet != NET_TCPB) return(0);
8292 if (ttnproto != NP_TELNET) return(0);
8293
8294 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8295
8296 #ifdef CK_SSL
8297 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8298 return(0);
8299 }
8300 #endif /* CK_SSL */
8301
8302 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8303 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8304 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8305 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8306 sb_out[i++] = TNC_CTL_DTR_REQUEST;
8307 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8308 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8309
8310 #ifdef DEBUG
8311 if (deblog || tn_deb || debses) {
8312 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8313 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8314 " SET-CONTROL ",
8315 "DTR-REQUEST",
8316 " IAC SE", NULL,
8317 NULL,NULL,NULL,NULL,NULL,NULL);
8318 }
8319 #endif /* DEBUG */
8320 #ifdef OS2
8321 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8322 #endif
8323 #ifdef DEBUG
8324 debug(F100,tn_msg_out,"",0);
8325 if (tn_deb || debses) tn_debug(tn_msg_out);
8326 #endif /* DEBUG */
8327 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8328 #ifdef OS2
8329 ReleaseTelnetMutex();
8330 #endif
8331 if (rc)
8332 return(-1);
8333
8334 if (tnc_wait((CHAR *)"comport get dtr state",0) < 0) {
8335 tn_push();
8336 return(-1);
8337 }
8338 debug(F111,"tnc_get_dtr_state","end",tnc_dtr);
8339 return(tnc_dtr);
8340 }
8341
8342 int
8343 #ifdef CK_ANSIC
tnc_set_rts_state(int onoff)8344 tnc_set_rts_state(int onoff)
8345 #else /* CK_ANSIC */
8346 tnc_set_rts_state(onoff) int onoff;
8347 #endif /* CK_ANSIC */
8348 /* tnc_set_rts_state */ {
8349 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8350 /* Value Rts State
8351 * 5 On
8352 * 6 Off
8353 */
8354 /* wait for response, return new host value. */
8355 int i = 0, rc;
8356
8357 debug(F111,"tnc_set_rts_state","begin",onoff);
8358 if (ttnet != NET_TCPB) return(0);
8359 if (ttnproto != NP_TELNET) return(0);
8360
8361 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8362
8363 #ifdef CK_SSL
8364 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8365 return(0);
8366 }
8367 #endif /* CK_SSL */
8368
8369 if ( onoff != 0 && onoff == tnc_rts )
8370 return(tnc_rts);
8371
8372 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8373 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8374 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8375 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8376 sb_out[i++] = onoff ?
8377 TNC_CTL_RTS_ON : TNC_CTL_RTS_OFF;
8378 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8379 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8380
8381 #ifdef DEBUG
8382 if (deblog || tn_deb || debses) {
8383 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8384 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8385 " SET-CONTROL ",
8386 onoff ? "RTS-ON" : "RTS-OFF",
8387 " IAC SE", NULL,
8388 NULL,NULL,NULL,NULL,NULL,NULL);
8389 }
8390 #endif /* DEBUG */
8391 #ifdef OS2
8392 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8393 #endif
8394 #ifdef DEBUG
8395 debug(F100,tn_msg_out,"",0);
8396 if (tn_deb || debses) tn_debug(tn_msg_out);
8397 #endif /* DEBUG */
8398 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8399 #ifdef OS2
8400 ReleaseTelnetMutex();
8401 #endif
8402 if (rc)
8403 return(-1);
8404
8405 if (tnc_wait((CHAR *)"comport set rts state",0) < 0) {
8406 tn_push();
8407 return(-1);
8408 }
8409 debug(F111,"tnc_set_rts_state","end",tnc_rts);
8410 return(tnc_rts);
8411 }
8412
8413 int
8414 #ifdef CK_ANSIC
tnc_get_rts_state(void)8415 tnc_get_rts_state(void)
8416 #else /* CK_ANSIC */
8417 tnc_get_rts_state()
8418 #endif /* CK_ANSIC */
8419 /* tnc_get_rts_state */ {
8420 /* IAC SB COM_PORT SET_CONTROL <value(1)=10> IAC SE */
8421 /* wait for response */
8422 int i = 0, rc;
8423
8424 debug(F110,"tnc_get_rts_state","begin",0);
8425 if (ttnet != NET_TCPB) return(0);
8426 if (ttnproto != NP_TELNET) return(0);
8427
8428 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8429
8430 #ifdef CK_SSL
8431 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8432 return(0);
8433 }
8434 #endif /* CK_SSL */
8435
8436 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8437 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8438 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8439 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8440 sb_out[i++] = TNC_CTL_RTS_REQUEST;
8441 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8442 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8443
8444 #ifdef DEBUG
8445 if (deblog || tn_deb || debses) {
8446 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8447 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8448 " SET-CONTROL ",
8449 "RTS-REQUEST",
8450 " IAC SE", NULL,
8451 NULL,NULL,NULL,NULL,NULL,NULL);
8452 }
8453 #endif /* DEBUG */
8454 #ifdef OS2
8455 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8456 #endif
8457 #ifdef DEBUG
8458 debug(F100,tn_msg_out,"",0);
8459 if (tn_deb || debses) tn_debug(tn_msg_out);
8460 #endif /* DEBUG */
8461 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8462 #ifdef OS2
8463 ReleaseTelnetMutex();
8464 #endif
8465 if (rc)
8466 return(-1);
8467
8468 if (tnc_wait((CHAR *)"comport get rts state",0) < 0) {
8469 tn_push();
8470 return(-1);
8471 }
8472 debug(F111,"tnc_get_rts_state","end",tnc_rts);
8473 return(tnc_rts);
8474 }
8475
8476 int
8477 #ifdef CK_ANSIC
tnc_set_ls_mask(int mask)8478 tnc_set_ls_mask(int mask)
8479 #else /* CK_ANSIC */
8480 tnc_set_ls_mask(mask) int mask;
8481 #endif /* CK_ANSIC */
8482 /* tnc_set_ls_mask */ {
8483 /* IAC SB COM_PORT SET_LINESTATE_MASK <value(1)> IAC SE */
8484 /* Bit Meaning
8485 * 0 Data Ready
8486 * 1 Overrun Error
8487 * 2 Parity Error
8488 * 3 Framing Error
8489 * 4 Break Detect Error
8490 * 5 Transfer Holding Register Empty
8491 * 6 Transfer Shift Register Empty
8492 * 7 Timeout Error
8493 */
8494 int i = 0, rc;
8495
8496 debug(F111,"tnc_set_ls_mask","begin",mask);
8497 if (ttnet != NET_TCPB) return(0);
8498 if (ttnproto != NP_TELNET) return(0);
8499
8500 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8501
8502 #ifdef CK_SSL
8503 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8504 return(0);
8505 }
8506 #endif /* CK_SSL */
8507
8508 if ( mask != 0 && mask == tnc_ls_mask )
8509 return(tnc_ls_mask);
8510
8511 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8512 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8513 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8514 sb_out[i++] = TNC_C2S_SET_LS_MASK;
8515 sb_out[i++] = (unsigned char)(mask & 0xFF);
8516 if (sb_out[i-1] == IAC )
8517 sb_out[i++] = IAC;
8518 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8519 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8520
8521 #ifdef DEBUG
8522 if (deblog || tn_deb || debses) {
8523 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8524 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8525 " SET-LINESTATE-MASK ",
8526 ckitoa(mask & 0xFF),
8527 " IAC SE", NULL,
8528 NULL,NULL,NULL,NULL,NULL,NULL);
8529 }
8530 #endif /* DEBUG */
8531 #ifdef OS2
8532 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8533 #endif
8534 #ifdef DEBUG
8535 debug(F100,tn_msg_out,"",0);
8536 if (tn_deb || debses) tn_debug(tn_msg_out);
8537 #endif /* DEBUG */
8538 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8539 #ifdef OS2
8540 ReleaseTelnetMutex();
8541 #endif
8542 if (rc)
8543 return(-1);
8544
8545 tnc_ls_mask = mask;
8546 debug(F111,"tnc_set_ls_mask","end",tnc_ls_mask);
8547 return(0);
8548 }
8549
8550 int
8551 #ifdef CK_ANSIC
tnc_get_ls_mask(void)8552 tnc_get_ls_mask(void)
8553 #else /* CK_ANSIC */
8554 tnc_get_ls_mask()
8555 #endif /* CK_ANSIC */
8556 /* tnc_get_ls_mask */ {
8557 debug(F101,"tnc_get_ls_mask","",tnc_ls_mask);
8558 return(tnc_ls_mask);
8559 }
8560
8561 int
8562 #ifdef CK_ANSIC
tnc_get_ls(void)8563 tnc_get_ls(void)
8564 #else /* CK_ANSIC */
8565 tnc_get_ls()
8566 #endif /* CK_ANSIC */
8567 /* tnc_get_ls */ {
8568 int ls = tnc_ls;
8569 debug(F101,"tnc_get_ls","",tnc_ls);
8570 return(ls);
8571 }
8572
8573 int
8574 #ifdef CK_ANSIC
tnc_set_ms_mask(int mask)8575 tnc_set_ms_mask(int mask)
8576 #else /* CK_ANSIC */
8577 tnc_set_ms_mask(mask) int mask;
8578 #endif /* CK_ANSIC */
8579 /* tnc_set_ms_mask */ {
8580 /* IAC SB COM_PORT SET_MODEMSTATE_MASK <value(1)> IAC SE */
8581 /* Bit Meaning
8582 * 0 Delta Clear To Send
8583 * 1 Delta Data Set Ready
8584 * 2 Trailing Edge Ring Detector
8585 * 3 Delta Receive Line Signal (Carrier) Detect
8586 * 4 Clear To Send Signal State
8587 * 5 Data-Set-Ready Signal State
8588 * 6 Ring Indicator
8589 * 7 Receive Line Signal (Carrier) Detect
8590 */
8591
8592 int i = 0, rc;
8593
8594 debug(F111,"tnc_set_ms_mask","begin",mask);
8595 if (ttnet != NET_TCPB) return(0);
8596 if (ttnproto != NP_TELNET) return(0);
8597
8598 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8599
8600 #ifdef CK_SSL
8601 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8602 return(0);
8603 }
8604 #endif /* CK_SSL */
8605
8606 if ( mask != 0 && mask == tnc_ms_mask )
8607 return(tnc_ms_mask);
8608
8609 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8610 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8611 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8612 sb_out[i++] = TNC_C2S_SET_MS_MASK;
8613 sb_out[i++] = (unsigned char)(mask & 0xFF);
8614 if (sb_out[i-1] == IAC )
8615 sb_out[i++] = IAC;
8616 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8617 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8618
8619 #ifdef DEBUG
8620 if (deblog || tn_deb || debses) {
8621 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8622 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8623 " SET-MODEMSTATE-MASK ",
8624 ckitoa(mask & 0xFF),
8625 " IAC SE", NULL,
8626 NULL,NULL,NULL,NULL,NULL,NULL);
8627 }
8628 #endif /* DEBUG */
8629 #ifdef OS2
8630 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8631 #endif
8632 #ifdef DEBUG
8633 debug(F100,tn_msg_out,"",0);
8634 if (tn_deb || debses) tn_debug(tn_msg_out);
8635 #endif /* DEBUG */
8636 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8637 #ifdef OS2
8638 ReleaseTelnetMutex();
8639 #endif
8640 if (rc)
8641 return(-1);
8642
8643 tnc_ms_mask = mask;
8644 debug(F111,"tnc_set_ms_mask","end",tnc_ms_mask);
8645 return(0);
8646 }
8647
8648 int
8649 #ifdef CK_ANSIC
tnc_get_ms_mask(void)8650 tnc_get_ms_mask(void)
8651 #else /* CK_ANSIC */
8652 tnc_get_ms_mask()
8653 #endif /* CK_ANSIC */
8654 /* tnc_get_ms_mask */ {
8655 debug(F101,"tnc_get_gs_mask","",tnc_ms_mask);
8656 return(tnc_ms_mask);
8657 }
8658
8659 int
8660 #ifdef CK_ANSIC
tnc_get_ms(void)8661 tnc_get_ms(void)
8662 #else /* CK_ANSIC */
8663 tnc_get_ms()
8664 #endif /* CK_ANSIC */
8665 /* tnc_get_ms */ {
8666 int ms = tnc_ms;
8667 debug(F101,"tnc_get_ms","",tnc_ms);
8668 return(ms);
8669 }
8670
8671 int
8672 #ifdef CK_ANSIC
tnc_send_purge_data(int mode)8673 tnc_send_purge_data(int mode)
8674 #else /* CK_ANSIC */
8675 tnc_send_purge_data(mode) int mode;
8676 #endif /* CK_ANSIC */
8677 /* tnc_send_purge_data */ {
8678 /* IAC SB COM_PORT PURGE_DATA <value(1)> IAC SE */
8679 /* Value Meaning
8680 * 1 Purge access server receive data buffer
8681 * 2 Purge access server transmit data buffer
8682 * 3 Purge access server receive and transmit data buffers
8683 */
8684 /* No response */
8685 int i = 0, rc;
8686
8687 debug(F111,"tnc_send_purge_data","begin",mode);
8688 if (ttnet != NET_TCPB) return(0);
8689 if (ttnproto != NP_TELNET) return(0);
8690
8691 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8692
8693 #ifdef CK_SSL
8694 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8695 return(0);
8696 }
8697 #endif /* CK_SSL */
8698
8699 if ( !(mode >= 1 && mode <= 3) )
8700 return(0);
8701
8702 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8703 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8704 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8705 sb_out[i++] = TNC_C2S_PURGE;
8706 sb_out[i++] = (unsigned char)(mode & 0xFF);
8707 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8708 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8709
8710 #ifdef DEBUG
8711 if (deblog || tn_deb || debses) {
8712 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8713 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8714 " PURGE-DATA ",
8715 ckitoa(mode & 0xFF),
8716 " IAC SE", NULL,
8717 NULL,NULL,NULL,NULL,NULL,NULL);
8718 }
8719 #endif /* DEBUG */
8720 #ifdef OS2
8721 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8722 #endif
8723 #ifdef DEBUG
8724 debug(F100,tn_msg_out,"",0);
8725 if (tn_deb || debses) tn_debug(tn_msg_out);
8726 #endif /* DEBUG */
8727 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8728 #ifdef OS2
8729 ReleaseTelnetMutex();
8730 #endif
8731 if (rc)
8732 return(-1);
8733 debug(F110,"tnc_send_purge_data","end",0);
8734 return(0);
8735 }
8736
8737 int
8738 #ifdef CK_ANSIC
tnc_flow_suspended(void)8739 tnc_flow_suspended(void)
8740 #else /* CK_ANSIC */
8741 tnc_flow_suspended()
8742 #endif /* CK_ANSIC */
8743 /* tnc_flow_suspended */ {
8744 debug(F111,"tnc_flow_suspended","",tnc_suspend_xmit);
8745 return(tnc_suspend_xmit);
8746 }
8747
8748 int
8749 #ifdef CK_ANSIC
tnc_suspend_flow(void)8750 tnc_suspend_flow(void)
8751 #else /* CK_ANSIC */
8752 tnc_suspend_flow()
8753 #endif /* CK_ANSIC */
8754 /* tnc_suspend_flow */ {
8755 /* IAC SB COM_PORT FLOWCONTROL_SUSPEND IAC SE */
8756 int i = 0, rc;
8757
8758 debug(F110,"tnc_suspend_flow","begin",0);
8759 if (ttnet != NET_TCPB) return(0);
8760 if (ttnproto != NP_TELNET) return(0);
8761
8762 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8763
8764 #ifdef CK_SSL
8765 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8766 return(0);
8767 }
8768 #endif /* CK_SSL */
8769
8770 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8771 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8772 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8773 sb_out[i++] = TNC_C2S_FLOW_SUSPEND;
8774 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8775 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8776
8777 #ifdef DEBUG
8778 if (deblog || tn_deb || debses) {
8779 ckmakmsg(tn_msg_out,TN_MSG_LEN,
8780 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8781 " FLOWCONTROL-SUSPEND IAC SE", NULL);
8782 }
8783 #endif /* DEBUG */
8784 #ifdef OS2
8785 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8786 #endif
8787 #ifdef DEBUG
8788 debug(F100,tn_msg_out,"",0);
8789 if (tn_deb || debses) tn_debug(tn_msg_out);
8790 #endif /* DEBUG */
8791 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8792 #ifdef OS2
8793 ReleaseTelnetMutex();
8794 #endif
8795 if (rc)
8796 return(-1);
8797 debug(F110,"tnc_suspend_flow","end",0);
8798 return(0);
8799 }
8800
8801 int
8802 #ifdef CK_ANSIC
tnc_resume_flow(void)8803 tnc_resume_flow(void)
8804 #else /* CK_ANSIC */
8805 tnc_resume_flow()
8806 #endif /* CK_ANSIC */
8807 /* tnc_resume_flow */ {
8808 /* IAC SB COM_PORT FLOWCONTROL_RESUME IAC SE */
8809 int i = 0, rc;
8810
8811 debug(F110,"tnc_resume_flow","begin",0);
8812 if (ttnet != NET_TCPB) return(0);
8813 if (ttnproto != NP_TELNET) return(0);
8814
8815 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8816
8817 #ifdef CK_SSL
8818 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8819 return(0);
8820 }
8821 #endif /* CK_SSL */
8822
8823 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8824 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8825 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8826 sb_out[i++] = TNC_C2S_FLOW_RESUME;
8827 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8828 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8829
8830 #ifdef DEBUG
8831 if (deblog || tn_deb || debses) {
8832 ckmakmsg(tn_msg_out,TN_MSG_LEN,
8833 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8834 " FLOWCONTROL-RESUME IAC SE", NULL);
8835 }
8836 #endif /* DEBUG */
8837 #ifdef OS2
8838 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8839 #endif
8840 #ifdef DEBUG
8841 debug(F100,tn_msg_out,"",0);
8842 if (tn_deb || debses) tn_debug(tn_msg_out);
8843 #endif /* DEBUG */
8844 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8845 #ifdef OS2
8846 ReleaseTelnetMutex();
8847 #endif
8848 if (rc)
8849 return(-1);
8850 debug(F110,"tnc_resume_flow","end",0);
8851 return(0);
8852 }
8853
8854 int
8855 #ifdef CK_ANSIC
tnsetflow(int nflow)8856 tnsetflow(int nflow)
8857 #else
8858 tnsetflow(nflow) int nflow;
8859 #endif /* CK_ANSIC */
8860 /* tnsetflow */ {
8861
8862 int rc = -1;
8863
8864 debug(F111,"tnsetflow","begin",nflow);
8865 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8866 return(-1);
8867
8868 if (TELOPT_ME(TELOPT_COMPORT)) {
8869 switch(nflow) {
8870 case FLO_XONX:
8871 rc = tnc_set_oflow(
8872 TNC_CTL_OFLOW_XON_XOFF
8873 );
8874 if (rc >= 0)
8875 rc = tnc_set_iflow(
8876 TNC_CTL_IFLOW_XON_XOFF
8877 );
8878 break;
8879 case FLO_RTSC:
8880 rc = tnc_set_oflow(
8881 TNC_CTL_OFLOW_RTS_CTS
8882 );
8883 if (rc >= 0)
8884 rc = tnc_set_iflow(
8885 TNC_CTL_IFLOW_RTS_CTS
8886 );
8887 break;
8888 case FLO_KEEP:
8889 /* leave things exactly as they are */
8890 rc = 0;
8891 break;
8892 case FLO_NONE:
8893 case FLO_DIAL: /* dialing hack */
8894 case FLO_DIAX: /* cancel dialing hack */
8895 rc = tnc_set_oflow(
8896 TNC_CTL_OFLOW_NONE
8897 );
8898 if (rc >= 0)
8899 rc = tnc_set_iflow(
8900 TNC_CTL_IFLOW_NONE
8901 );
8902 break;
8903 case FLO_DTRC:
8904 case FLO_ETXA:
8905 case FLO_STRG:
8906 case FLO_DTRT:
8907 default:
8908 /* not supported */
8909 rc = -1;
8910 break;
8911 }
8912 }
8913 debug(F111,"tnsetflow","end",rc);
8914 return(rc >= 0 ? 0 : -1);
8915 }
8916
8917 int
8918 #ifdef CK_ANSIC
tnsettings(int par,int stop)8919 tnsettings(int par, int stop)
8920 #else
8921 tnsettings(par, stop) int par, stop;
8922 #endif /* CK_ANSIC */
8923 /* tnsettings */ {
8924 int rc = -1;
8925 int datasize = 0;
8926 extern int hwparity;
8927
8928 debug(F111,"tnsettings begin","par",par);
8929 debug(F111,"tnsettings begin","stop",stop);
8930 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8931 return(-1);
8932
8933 datasize = par ? TNC_DS_7 : TNC_DS_8;
8934 if (!par) par = hwparity;
8935
8936 if (TELOPT_ME(TELOPT_COMPORT)) {
8937 switch (par) {
8938 case 'e':
8939 rc = tnc_set_parity(TNC_PAR_EVEN);
8940 if (rc >= 0)
8941 rc = tnc_set_datasize(datasize);
8942 break;
8943 case 'o':
8944 rc = tnc_set_parity(TNC_PAR_ODD);
8945 if (rc >= 0)
8946 rc = tnc_set_datasize(datasize);
8947 break;
8948 case 'm':
8949 rc = tnc_set_parity(TNC_PAR_MARK);
8950 if (rc >= 0)
8951 rc = tnc_set_datasize(datasize);
8952 break;
8953 case 's':
8954 rc = tnc_set_parity(TNC_PAR_SPACE);
8955 if (rc >= 0)
8956 rc = tnc_set_datasize(datasize);
8957 break;
8958 case 0:
8959 case 'n':
8960 rc = tnc_set_parity(TNC_PAR_NONE);
8961 if (rc >= 0)
8962 rc = tnc_set_datasize(datasize);
8963 break;
8964 default:
8965 /* no change */
8966 rc = 0;
8967 }
8968 switch(stop) {
8969 case 2:
8970 if (rc >= 0)
8971 rc = tnc_set_stopsize(TNC_SB_2);
8972 break;
8973 case 1:
8974 if (rc >= 0)
8975 rc = tnc_set_stopsize(TNC_SB_1);
8976 break;
8977 default:
8978 /* no change */
8979 if (rc >= 0)
8980 rc = 0;
8981 }
8982 }
8983 debug(F111,"tnsettings","end",rc);
8984 return((rc >= 0) ? 0 : -1);
8985 }
8986
8987 /* T N G M D M -- Telnet Get modem signals */
8988 /*
8989 Looks for the modem signals CTS, DSR, and CTS, and returns those that are
8990 on in as its return value, in a bit mask as described for ttwmdm.
8991 Returns:
8992 -3 Not implemented
8993 -2 if the line does not have modem control
8994 -1 on error.
8995 >= 0 on success, with a bit mask containing the modem signals that are on.
8996 */
8997 int
8998 #ifdef CK_ANSIC
tngmdm(void)8999 tngmdm(void)
9000 #else
9001 tngmdm()
9002 #endif /* CK_ANSIC */
9003 /* tngmdm */ {
9004
9005 int rc = -1;
9006
9007 debug(F110,"tngmdm","begin",0);
9008 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
9009 return(-1);
9010
9011 if (TELOPT_ME(TELOPT_COMPORT)) {
9012 int modemstate = tnc_get_ms();
9013 int modem = 0;
9014 if (modemstate & TNC_MS_CTS_SIG)
9015 modem |= BM_CTS;
9016 if (modemstate & TNC_MS_DSR_SIG)
9017 modem |= BM_DSR;
9018 if (modemstate & TNC_MS_RI_SIG)
9019 modem |= BM_RNG;
9020 if (modemstate & TNC_MS_RLSD_SIG)
9021 modem |= BM_DCD;
9022 debug(F111,"tngmdm","end",modem);
9023 return(modem);
9024 } else {
9025 debug(F111,"tngmdm","end",-2);
9026 return(-2);
9027 }
9028 }
9029
9030 int
9031 #ifdef CK_ANSIC
tnsndb(long wait)9032 tnsndb(long wait)
9033 #else
9034 tnsndb(wait) long wait;
9035 #endif /* CK_ANSIC */
9036 /* tnsndb */ {
9037 int rc = -1;
9038
9039 debug(F111,"tnsndb","begin",wait);
9040 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
9041 return(-1);
9042
9043 if (TELOPT_ME(TELOPT_COMPORT)) {
9044 rc = tnc_set_break_state(1);
9045 if (rc >= 0) {
9046 msleep(wait);
9047 rc = tnc_set_break_state(0);
9048 }
9049 }
9050 debug(F111,"tnsndb","end",rc);
9051 return((rc >= 0) ? 0 : -1);
9052 }
9053 #endif /* TN_COMPORT */
9054 #endif /* TNCODE */
9055