Annotation of src/usr.bin/telnet/telnet.c, Revision 1.19
1.19 ! otto 1: /* $OpenBSD: telnet.c,v 1.18 2003/11/08 19:17:29 jmc Exp $ */
1.2 niklas 2: /* $NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $ */
3:
1.1 deraadt 4: /*
5: * Copyright (c) 1988, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.16 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.4 art 33: #include "telnet_locl.h"
1.9 millert 34: #include <curses.h>
35: #include <term.h>
1.1 deraadt 36:
1.4 art 37: #define strip(x) (eight ? (x) : ((x) & 0x7f))
1.1 deraadt 38:
39: static unsigned char subbuffer[SUBBUFSIZE],
40: *subpointer, *subend; /* buffer for sub-options */
41: #define SB_CLEAR() subpointer = subbuffer;
42: #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
43: #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
44: *subpointer++ = (c); \
45: }
46:
47: #define SB_GET() ((*subpointer++)&0xff)
48: #define SB_PEEK() ((*subpointer)&0xff)
49: #define SB_EOF() (subpointer >= subend)
50: #define SB_LEN() (subend - subpointer)
51:
52: char options[256]; /* The combined options */
53: char do_dont_resp[256];
54: char will_wont_resp[256];
55:
56: int
1.4 art 57: eight = 3,
58: binary = 0,
1.1 deraadt 59: autologin = 0, /* Autologin anyone? */
60: skiprc = 0,
61: connected,
62: showoptions,
63: In3270, /* Are we in 3270 mode? */
64: ISend, /* trying to send network data in */
65: debug = 0,
66: crmod,
67: netdata, /* Print out network data flow */
68: crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
69: #if defined(TN3270)
70: noasynchtty = 0,/* User specified "-noasynch" on command line */
71: noasynchnet = 0,/* User specified "-noasynch" on command line */
72: askedSGA = 0, /* We have talked about suppress go ahead */
73: #endif /* defined(TN3270) */
74: telnetport,
1.15 hin 75: wantencryption = 0,
1.1 deraadt 76: SYNCHing, /* we are in TELNET SYNCH mode */
77: flushout, /* flush output */
78: autoflush = 0, /* flush output when interrupting? */
79: autosynch, /* send interrupt characters with SYNCH? */
80: localflow, /* we handle flow control locally */
81: restartany, /* if flow control enabled, restart on any character */
82: localchars, /* we recognize interrupt/quit */
83: donelclchars, /* the user has set "localchars" */
84: donebinarytoggle, /* the user has put us in binary */
85: dontlecho, /* do we suppress local echoing right now? */
86: globalmode,
87: clienteof = 0;
88:
89: char *prompt = 0;
90:
1.15 hin 91: int scheduler_lockout_tty = 0;
92:
1.1 deraadt 93: cc_t escape;
94: cc_t rlogin;
95: #ifdef KLUDGELINEMODE
96: cc_t echoc;
97: #endif
98:
99: /*
100: * Telnet receiver states for fsm
101: */
102: #define TS_DATA 0
103: #define TS_IAC 1
104: #define TS_WILL 2
105: #define TS_WONT 3
106: #define TS_DO 4
107: #define TS_DONT 5
108: #define TS_CR 6
109: #define TS_SB 7 /* sub-option collection */
110: #define TS_SE 8 /* looking for sub-option end */
111:
112: static int telrcv_state;
113: #ifdef OLD_ENVIRON
114: unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
115: #else
116: # define telopt_environ TELOPT_NEW_ENVIRON
117: #endif
118:
119: jmp_buf toplevel = { 0 };
120: jmp_buf peerdied;
121:
122: int flushline;
123: int linemode;
124:
125: #ifdef KLUDGELINEMODE
126: int kludgelinemode = 1;
127: #endif
128:
129: /*
130: * The following are some clocks used to decide how to interpret
131: * the relationship between various variables.
132: */
133:
134: Clocks clocks;
135:
136:
137: /*
138: * Initialize telnet environment.
139: */
140:
141: void
142: init_telnet()
143: {
144: env_init();
145:
146: SB_CLEAR();
1.4 art 147: memset((char *)options, 0, sizeof options);
1.1 deraadt 148:
149: connected = In3270 = ISend = localflow = donebinarytoggle = 0;
1.4 art 150: #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1 deraadt 151: auth_encrypt_connect(connected);
1.4 art 152: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1 deraadt 153: restartany = -1;
154:
155: SYNCHing = 0;
156:
157: /* Don't change NetTrace */
158:
159: escape = CONTROL(']');
160: rlogin = _POSIX_VDISABLE;
161: #ifdef KLUDGELINEMODE
162: echoc = CONTROL('E');
163: #endif
164:
165: flushline = 1;
166: telrcv_state = TS_DATA;
167: }
168:
169:
170: /*
171: * These routines are in charge of sending option negotiations
172: * to the other side.
173: *
174: * The basic idea is that we send the negotiation if either side
175: * is in disagreement as to what the current state should be.
176: */
177:
178: void
179: send_do(c, init)
1.13 mpech 180: int c, init;
1.1 deraadt 181: {
182: if (init) {
183: if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
184: my_want_state_is_do(c))
185: return;
186: set_my_want_state_do(c);
187: do_dont_resp[c]++;
188: }
189: NET2ADD(IAC, DO);
190: NETADD(c);
1.12 hin 191: printoption("SENT",DO, c);
1.1 deraadt 192: }
193:
194: void
195: send_dont(c, init)
1.13 mpech 196: int c, init;
1.1 deraadt 197: {
198: if (init) {
199: if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
200: my_want_state_is_dont(c))
201: return;
202: set_my_want_state_dont(c);
203: do_dont_resp[c]++;
204: }
205: NET2ADD(IAC, DONT);
206: NETADD(c);
207: printoption("SENT", DONT, c);
208: }
209:
210: void
211: send_will(c, init)
1.13 mpech 212: int c, init;
1.1 deraadt 213: {
214: if (init) {
215: if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
216: my_want_state_is_will(c))
217: return;
218: set_my_want_state_will(c);
219: will_wont_resp[c]++;
220: }
221: NET2ADD(IAC, WILL);
222: NETADD(c);
223: printoption("SENT", WILL, c);
224: }
225:
226: void
227: send_wont(c, init)
1.13 mpech 228: int c, init;
1.1 deraadt 229: {
230: if (init) {
231: if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
232: my_want_state_is_wont(c))
233: return;
234: set_my_want_state_wont(c);
235: will_wont_resp[c]++;
236: }
237: NET2ADD(IAC, WONT);
238: NETADD(c);
239: printoption("SENT", WONT, c);
240: }
241:
242:
243: void
244: willoption(option)
245: int option;
246: {
247: int new_state_ok = 0;
248:
249: if (do_dont_resp[option]) {
250: --do_dont_resp[option];
251: if (do_dont_resp[option] && my_state_is_do(option))
252: --do_dont_resp[option];
253: }
254:
255: if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
256:
257: switch (option) {
258:
259: case TELOPT_ECHO:
260: # if defined(TN3270)
261: /*
262: * The following is a pain in the rear-end.
263: * Various IBM servers (some versions of Wiscnet,
264: * possibly Fibronics/Spartacus, and who knows who
265: * else) will NOT allow us to send "DO SGA" too early
266: * in the setup proceedings. On the other hand,
267: * 4.2 servers (telnetd) won't set SGA correctly.
268: * So, we are stuck. Empirically (but, based on
269: * a VERY small sample), the IBM servers don't send
270: * out anything about ECHO, so we postpone our sending
271: * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
272: * DO send).
273: */
274: {
275: if (askedSGA == 0) {
276: askedSGA = 1;
277: if (my_want_state_is_dont(TELOPT_SGA))
278: send_do(TELOPT_SGA, 1);
279: }
280: }
281: /* Fall through */
282: case TELOPT_EOR:
283: #endif /* defined(TN3270) */
284: case TELOPT_BINARY:
285: case TELOPT_SGA:
286: settimer(modenegotiated);
287: /* FALL THROUGH */
288: case TELOPT_STATUS:
289: #if defined(AUTHENTICATION)
290: case TELOPT_AUTHENTICATION:
291: #endif
1.4 art 292: #if defined(ENCRYPTION)
293: case TELOPT_ENCRYPT:
294: #endif
1.1 deraadt 295: new_state_ok = 1;
296: break;
297:
298: case TELOPT_TM:
299: if (flushout)
300: flushout = 0;
301: /*
302: * Special case for TM. If we get back a WILL,
303: * pretend we got back a WONT.
304: */
305: set_my_want_state_dont(option);
306: set_my_state_dont(option);
307: return; /* Never reply to TM will's/wont's */
308:
309: case TELOPT_LINEMODE:
310: default:
311: break;
312: }
313:
314: if (new_state_ok) {
315: set_my_want_state_do(option);
316: send_do(option, 0);
317: setconnmode(0); /* possibly set new tty mode */
318: } else {
319: do_dont_resp[option]++;
320: send_dont(option, 0);
321: }
322: }
323: set_my_state_do(option);
1.4 art 324: #if defined(ENCRYPTION)
325: if (option == TELOPT_ENCRYPT)
326: encrypt_send_support();
327: #endif
328:
1.1 deraadt 329: }
330:
331: void
332: wontoption(option)
333: int option;
334: {
335: if (do_dont_resp[option]) {
336: --do_dont_resp[option];
337: if (do_dont_resp[option] && my_state_is_dont(option))
338: --do_dont_resp[option];
339: }
340:
341: if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
342:
343: switch (option) {
344:
345: #ifdef KLUDGELINEMODE
346: case TELOPT_SGA:
347: if (!kludgelinemode)
348: break;
349: /* FALL THROUGH */
350: #endif
351: case TELOPT_ECHO:
352: settimer(modenegotiated);
353: break;
354:
355: case TELOPT_TM:
356: if (flushout)
357: flushout = 0;
358: set_my_want_state_dont(option);
359: set_my_state_dont(option);
360: return; /* Never reply to TM will's/wont's */
361:
1.4 art 362: #ifdef ENCRYPTION
363: case TELOPT_ENCRYPT:
364: encrypt_not();
365: break;
366: #endif
1.1 deraadt 367: default:
368: break;
369: }
370: set_my_want_state_dont(option);
371: if (my_state_is_do(option))
372: send_dont(option, 0);
373: setconnmode(0); /* Set new tty mode */
374: } else if (option == TELOPT_TM) {
375: /*
376: * Special case for TM.
377: */
378: if (flushout)
379: flushout = 0;
380: set_my_want_state_dont(option);
381: }
382: set_my_state_dont(option);
383: }
384:
385: static void
386: dooption(option)
387: int option;
388: {
389: int new_state_ok = 0;
390:
391: if (will_wont_resp[option]) {
392: --will_wont_resp[option];
393: if (will_wont_resp[option] && my_state_is_will(option))
394: --will_wont_resp[option];
395: }
396:
397: if (will_wont_resp[option] == 0) {
398: if (my_want_state_is_wont(option)) {
399:
400: switch (option) {
401:
402: case TELOPT_TM:
403: /*
404: * Special case for TM. We send a WILL, but pretend
405: * we sent WONT.
406: */
407: send_will(option, 0);
408: set_my_want_state_wont(TELOPT_TM);
409: set_my_state_wont(TELOPT_TM);
410: return;
411:
412: # if defined(TN3270)
413: case TELOPT_EOR: /* end of record */
414: # endif /* defined(TN3270) */
415: case TELOPT_BINARY: /* binary mode */
416: case TELOPT_NAWS: /* window size */
417: case TELOPT_TSPEED: /* terminal speed */
418: case TELOPT_LFLOW: /* local flow control */
419: case TELOPT_TTYPE: /* terminal type option */
420: case TELOPT_SGA: /* no big deal */
1.4 art 421: #if defined(ENCRYPTION)
422: case TELOPT_ENCRYPT: /* encryption variable option */
423: #endif
1.1 deraadt 424: new_state_ok = 1;
425: break;
426:
427: case TELOPT_NEW_ENVIRON: /* New environment variable option */
428: #ifdef OLD_ENVIRON
429: if (my_state_is_will(TELOPT_OLD_ENVIRON))
430: send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
431: goto env_common;
432: case TELOPT_OLD_ENVIRON: /* Old environment variable option */
433: if (my_state_is_will(TELOPT_NEW_ENVIRON))
434: break; /* Don't enable if new one is in use! */
435: env_common:
436: telopt_environ = option;
437: #endif
438: new_state_ok = 1;
439: break;
440:
441: #if defined(AUTHENTICATION)
442: case TELOPT_AUTHENTICATION:
443: if (autologin)
444: new_state_ok = 1;
445: break;
446: #endif
447:
448: case TELOPT_XDISPLOC: /* X Display location */
1.19 ! otto 449: if (env_getvalue((unsigned char *)"DISPLAY", 0))
1.1 deraadt 450: new_state_ok = 1;
451: break;
452:
453: case TELOPT_LINEMODE:
454: #ifdef KLUDGELINEMODE
455: kludgelinemode = 0;
456: send_do(TELOPT_SGA, 1);
457: #endif
458: set_my_want_state_will(TELOPT_LINEMODE);
459: send_will(option, 0);
460: set_my_state_will(TELOPT_LINEMODE);
461: slc_init();
462: return;
463:
464: case TELOPT_ECHO: /* We're never going to echo... */
465: default:
466: break;
467: }
468:
469: if (new_state_ok) {
470: set_my_want_state_will(option);
471: send_will(option, 0);
472: setconnmode(0); /* Set new tty mode */
473: } else {
474: will_wont_resp[option]++;
475: send_wont(option, 0);
476: }
477: } else {
478: /*
479: * Handle options that need more things done after the
480: * other side has acknowledged the option.
481: */
482: switch (option) {
483: case TELOPT_LINEMODE:
484: #ifdef KLUDGELINEMODE
485: kludgelinemode = 0;
486: send_do(TELOPT_SGA, 1);
487: #endif
488: set_my_state_will(option);
489: slc_init();
490: send_do(TELOPT_SGA, 0);
491: return;
492: }
493: }
494: }
495: set_my_state_will(option);
496: }
497:
498: static void
499: dontoption(option)
500: int option;
501: {
502:
503: if (will_wont_resp[option]) {
504: --will_wont_resp[option];
505: if (will_wont_resp[option] && my_state_is_wont(option))
506: --will_wont_resp[option];
507: }
508:
509: if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
510: switch (option) {
511: case TELOPT_LINEMODE:
512: linemode = 0; /* put us back to the default state */
513: break;
514: #ifdef OLD_ENVIRON
515: case TELOPT_NEW_ENVIRON:
516: /*
517: * The new environ option wasn't recognized, try
518: * the old one.
519: */
520: send_will(TELOPT_OLD_ENVIRON, 1);
521: telopt_environ = TELOPT_OLD_ENVIRON;
522: break;
523: #endif
524: }
525: /* we always accept a DONT */
526: set_my_want_state_wont(option);
527: if (my_state_is_will(option))
528: send_wont(option, 0);
529: setconnmode(0); /* Set new tty mode */
530: }
531: set_my_state_wont(option);
532: }
533:
534: /*
1.11 provos 535: * This routine will turn a pipe separated list of names in the buffer
1.9 millert 536: * into an array of pointers to NUL terminated names. We toss out any
537: * bad, duplicate, or verbose names (names with spaces).
1.1 deraadt 538: */
539:
1.14 millert 540: int is_unique(char *, char **, char **);
1.5 art 541:
1.1 deraadt 542: static char *name_unknown = "UNKNOWN";
543: static char *unknown[] = { 0, 0 };
544:
545: char **
546: mklist(buf, name)
547: char *buf, *name;
548: {
1.13 mpech 549: int n;
550: char c, *cp, **argvp, *cp2, **argv, **avt;
1.1 deraadt 551:
552: if (name) {
1.2 niklas 553: if ((int)strlen(name) > 40) {
1.1 deraadt 554: name = 0;
555: unknown[0] = name_unknown;
556: } else {
557: unknown[0] = name;
558: upcase(name);
559: }
560: } else
561: unknown[0] = name_unknown;
562: /*
563: * Count up the number of names.
564: */
1.9 millert 565: for (n = 1, cp = buf; *cp; cp++) {
1.1 deraadt 566: if (*cp == '|')
567: n++;
568: }
569: /*
570: * Allocate an array to put the name pointers into
571: */
572: argv = (char **)malloc((n+3)*sizeof(char *));
573: if (argv == 0)
574: return(unknown);
575:
576: /*
577: * Fill up the array of pointers to names.
578: */
579: *argv = 0;
580: argvp = argv+1;
581: n = 0;
582: for (cp = cp2 = buf; (c = *cp); cp++) {
583: if (c == '|' || c == ':') {
584: *cp++ = '\0';
585: /*
586: * Skip entries that have spaces or are over 40
587: * characters long. If this is our environment
588: * name, then put it up front. Otherwise, as
589: * long as this is not a duplicate name (case
590: * insensitive) add it to the list.
591: */
592: if (n || (cp - cp2 > 41))
593: ;
594: else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
595: *argv = cp2;
596: else if (is_unique(cp2, argv+1, argvp))
597: *argvp++ = cp2;
598: if (c == ':')
599: break;
600: /*
601: * Skip multiple delimiters. Reset cp2 to
602: * the beginning of the next name. Reset n,
603: * the flag for names with spaces.
604: */
605: while ((c = *cp) == '|')
606: cp++;
607: cp2 = cp;
608: n = 0;
609: }
610: /*
611: * Skip entries with spaces or non-ascii values.
612: * Convert lower case letters to upper case.
613: */
1.4 art 614: #define ISASCII(c) (!((c)&0x80))
615: if ((c == ' ') || !ISASCII(c))
1.1 deraadt 616: n = 1;
617: else if (islower(c))
618: *cp = toupper(c);
619: }
1.2 niklas 620:
1.1 deraadt 621: /*
622: * Check for an old V6 2 character name. If the second
623: * name points to the beginning of the buffer, and is
624: * only 2 characters long, move it to the end of the array.
625: */
626: if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
627: --argvp;
628: for (avt = &argv[1]; avt < argvp; avt++)
629: *avt = *(avt+1);
630: *argvp++ = buf;
631: }
632:
633: /*
634: * Duplicate last name, for TTYPE option, and null
635: * terminate the array. If we didn't find a match on
636: * our terminal name, put that name at the beginning.
637: */
638: cp = *(argvp-1);
639: *argvp++ = cp;
640: *argvp = 0;
641:
642: if (*argv == 0) {
643: if (name)
644: *argv = name;
645: else {
646: --argvp;
647: for (avt = argv; avt < argvp; avt++)
648: *avt = *(avt+1);
649: }
650: }
651: if (*argv)
652: return(argv);
653: else
654: return(unknown);
655: }
656:
657: int
658: is_unique(name, as, ae)
1.13 mpech 659: char *name, **as, **ae;
1.1 deraadt 660: {
1.13 mpech 661: char **ap;
662: int n;
1.1 deraadt 663:
664: n = strlen(name) + 1;
665: for (ap = as; ap < ae; ap++)
666: if (strncasecmp(*ap, name, n) == 0)
667: return(0);
668: return (1);
669: }
670:
671: int resettermname = 1;
672:
673: char *
674: gettermname()
675: {
676: char *tname;
677: static char **tnamep = 0;
678: static char **next;
1.10 millert 679: int errret;
1.1 deraadt 680:
681: if (resettermname) {
682: resettermname = 0;
683: if (tnamep && tnamep != unknown)
684: free(tnamep);
1.19 ! otto 685: if ((tname = (char *)env_getvalue((unsigned char *)"TERM", 0)) &&
1.10 millert 686: (setupterm(tname, 1, &errret) == OK)) {
1.9 millert 687: tnamep = mklist(ttytype, tname);
1.1 deraadt 688: } else {
1.2 niklas 689: if (tname && ((int)strlen(tname) <= 40)) {
1.1 deraadt 690: unknown[0] = tname;
691: upcase(tname);
692: } else
693: unknown[0] = name_unknown;
694: tnamep = unknown;
695: }
696: next = tnamep;
697: }
698: if (*next == 0)
699: next = tnamep;
700: return(*next++);
701: }
702: /*
703: * suboption()
704: *
705: * Look at the sub-option buffer, and try to be helpful to the other
706: * side.
707: *
708: * Currently we recognize:
709: *
710: * Terminal type, send request.
711: * Terminal speed (send request).
712: * Local flow control (is request).
713: * Linemode
714: */
715:
716: static void
717: suboption()
718: {
719: unsigned char subchar;
720:
721: printsub('<', subbuffer, SB_LEN()+2);
722: switch (subchar = SB_GET()) {
723: case TELOPT_TTYPE:
724: if (my_want_state_is_wont(TELOPT_TTYPE))
725: return;
726: if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
727: return;
728: } else {
729: char *name;
730: unsigned char temp[50];
731: int len;
732:
733: #if defined(TN3270)
734: if (tn3270_ttype()) {
735: return;
736: }
737: #endif /* defined(TN3270) */
738: name = gettermname();
739: len = strlen(name) + 4 + 2;
740: if (len < NETROOM()) {
1.4 art 741: snprintf((char *)temp, sizeof(temp),
742: "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
743: TELQUAL_IS, name, IAC, SE);
1.1 deraadt 744: ring_supply_data(&netoring, temp, len);
745: printsub('>', &temp[2], len-2);
746: } else {
747: ExitString("No room in buffer for terminal type.\n", 1);
748: /*NOTREACHED*/
749: }
750: }
751: break;
752: case TELOPT_TSPEED:
753: if (my_want_state_is_wont(TELOPT_TSPEED))
754: return;
755: if (SB_EOF())
756: return;
757: if (SB_GET() == TELQUAL_SEND) {
758: long ospeed, ispeed;
759: unsigned char temp[50];
760: int len;
761:
762: TerminalSpeeds(&ispeed, &ospeed);
763:
1.4 art 764: snprintf((char *)temp, sizeof(temp),
1.5 art 765: "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
1.4 art 766: TELQUAL_IS, ospeed, ispeed, IAC, SE);
1.1 deraadt 767: len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
768:
769: if (len < NETROOM()) {
770: ring_supply_data(&netoring, temp, len);
771: printsub('>', temp+2, len - 2);
772: }
773: /*@*/ else printf("lm_will: not enough room in buffer\n");
774: }
775: break;
776: case TELOPT_LFLOW:
777: if (my_want_state_is_wont(TELOPT_LFLOW))
778: return;
779: if (SB_EOF())
780: return;
781: switch(SB_GET()) {
782: case LFLOW_RESTART_ANY:
783: restartany = 1;
784: break;
785: case LFLOW_RESTART_XON:
786: restartany = 0;
787: break;
788: case LFLOW_ON:
789: localflow = 1;
790: break;
791: case LFLOW_OFF:
792: localflow = 0;
793: break;
794: default:
795: return;
796: }
797: setcommandmode();
798: setconnmode(0);
799: break;
800:
801: case TELOPT_LINEMODE:
802: if (my_want_state_is_wont(TELOPT_LINEMODE))
803: return;
804: if (SB_EOF())
805: return;
806: switch (SB_GET()) {
807: case WILL:
808: lm_will(subpointer, SB_LEN());
809: break;
810: case WONT:
811: lm_wont(subpointer, SB_LEN());
812: break;
813: case DO:
814: lm_do(subpointer, SB_LEN());
815: break;
816: case DONT:
817: lm_dont(subpointer, SB_LEN());
818: break;
819: case LM_SLC:
820: slc(subpointer, SB_LEN());
821: break;
822: case LM_MODE:
823: lm_mode(subpointer, SB_LEN(), 0);
824: break;
825: default:
826: break;
827: }
828: break;
829:
830: #ifdef OLD_ENVIRON
831: case TELOPT_OLD_ENVIRON:
832: #endif
833: case TELOPT_NEW_ENVIRON:
834: if (SB_EOF())
835: return;
836: switch(SB_PEEK()) {
837: case TELQUAL_IS:
838: case TELQUAL_INFO:
839: if (my_want_state_is_dont(subchar))
840: return;
841: break;
842: case TELQUAL_SEND:
843: if (my_want_state_is_wont(subchar)) {
844: return;
845: }
846: break;
847: default:
848: return;
849: }
850: env_opt(subpointer, SB_LEN());
851: break;
852:
853: case TELOPT_XDISPLOC:
854: if (my_want_state_is_wont(TELOPT_XDISPLOC))
855: return;
856: if (SB_EOF())
857: return;
858: if (SB_GET() == TELQUAL_SEND) {
859: unsigned char temp[50], *dp;
860: int len;
861:
1.19 ! otto 862: if ((dp = env_getvalue((unsigned char *)"DISPLAY", 0)) == NULL) {
1.1 deraadt 863: /*
864: * Something happened, we no longer have a DISPLAY
865: * variable. So, turn off the option.
866: */
867: send_wont(TELOPT_XDISPLOC, 1);
868: break;
869: }
1.4 art 870: snprintf((char *)temp, sizeof(temp),
871: "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
1.1 deraadt 872: TELQUAL_IS, dp, IAC, SE);
873: len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
874:
875: if (len < NETROOM()) {
876: ring_supply_data(&netoring, temp, len);
877: printsub('>', temp+2, len - 2);
878: }
879: /*@*/ else printf("lm_will: not enough room in buffer\n");
880: }
881: break;
882:
883: #if defined(AUTHENTICATION)
884: case TELOPT_AUTHENTICATION: {
885: if (!autologin)
886: break;
887: if (SB_EOF())
888: return;
889: switch(SB_GET()) {
890: case TELQUAL_IS:
891: if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
892: return;
893: auth_is(subpointer, SB_LEN());
894: break;
895: case TELQUAL_SEND:
896: if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
897: return;
898: auth_send(subpointer, SB_LEN());
899: break;
900: case TELQUAL_REPLY:
901: if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
902: return;
903: auth_reply(subpointer, SB_LEN());
904: break;
905: case TELQUAL_NAME:
906: if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
907: return;
908: auth_name(subpointer, SB_LEN());
909: break;
910: }
911: }
912: break;
913: #endif
1.4 art 914: #if defined(ENCRYPTION)
915: case TELOPT_ENCRYPT:
916: if (SB_EOF())
917: return;
918: switch(SB_GET()) {
919: case ENCRYPT_START:
920: if (my_want_state_is_dont(TELOPT_ENCRYPT))
921: return;
922: encrypt_start(subpointer, SB_LEN());
923: break;
924: case ENCRYPT_END:
925: if (my_want_state_is_dont(TELOPT_ENCRYPT))
926: return;
927: encrypt_end();
928: break;
929: case ENCRYPT_SUPPORT:
930: if (my_want_state_is_wont(TELOPT_ENCRYPT))
931: return;
932: encrypt_support(subpointer, SB_LEN());
933: break;
934: case ENCRYPT_REQSTART:
935: if (my_want_state_is_wont(TELOPT_ENCRYPT))
936: return;
937: encrypt_request_start(subpointer, SB_LEN());
938: break;
939: case ENCRYPT_REQEND:
940: if (my_want_state_is_wont(TELOPT_ENCRYPT))
941: return;
942: /*
943: * We can always send an REQEND so that we cannot
944: * get stuck encrypting. We should only get this
945: * if we have been able to get in the correct mode
946: * anyhow.
947: */
948: encrypt_request_end();
949: break;
950: case ENCRYPT_IS:
951: if (my_want_state_is_dont(TELOPT_ENCRYPT))
952: return;
953: encrypt_is(subpointer, SB_LEN());
954: break;
955: case ENCRYPT_REPLY:
956: if (my_want_state_is_wont(TELOPT_ENCRYPT))
957: return;
958: encrypt_reply(subpointer, SB_LEN());
959: break;
960: case ENCRYPT_ENC_KEYID:
961: if (my_want_state_is_dont(TELOPT_ENCRYPT))
962: return;
963: encrypt_enc_keyid(subpointer, SB_LEN());
964: break;
965: case ENCRYPT_DEC_KEYID:
966: if (my_want_state_is_wont(TELOPT_ENCRYPT))
967: return;
968: encrypt_dec_keyid(subpointer, SB_LEN());
969: break;
970: default:
971: break;
972: }
973: break;
974: #endif
1.1 deraadt 975: default:
976: break;
977: }
978: }
979:
980: static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
981:
982: void
983: lm_will(cmd, len)
984: unsigned char *cmd;
985: int len;
986: {
987: if (len < 1) {
988: /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
989: return;
990: }
991: switch(cmd[0]) {
992: case LM_FORWARDMASK: /* We shouldn't ever get this... */
993: default:
994: str_lm[3] = DONT;
995: str_lm[4] = cmd[0];
996: if (NETROOM() > sizeof(str_lm)) {
997: ring_supply_data(&netoring, str_lm, sizeof(str_lm));
998: printsub('>', &str_lm[2], sizeof(str_lm)-2);
999: }
1000: /*@*/ else printf("lm_will: not enough room in buffer\n");
1001: break;
1002: }
1003: }
1004:
1005: void
1006: lm_wont(cmd, len)
1007: unsigned char *cmd;
1008: int len;
1009: {
1010: if (len < 1) {
1011: /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
1012: return;
1013: }
1014: switch(cmd[0]) {
1015: case LM_FORWARDMASK: /* We shouldn't ever get this... */
1016: default:
1017: /* We are always DONT, so don't respond */
1018: return;
1019: }
1020: }
1021:
1022: void
1023: lm_do(cmd, len)
1024: unsigned char *cmd;
1025: int len;
1026: {
1027: if (len < 1) {
1028: /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
1029: return;
1030: }
1031: switch(cmd[0]) {
1032: case LM_FORWARDMASK:
1033: default:
1034: str_lm[3] = WONT;
1035: str_lm[4] = cmd[0];
1036: if (NETROOM() > sizeof(str_lm)) {
1037: ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1038: printsub('>', &str_lm[2], sizeof(str_lm)-2);
1039: }
1040: /*@*/ else printf("lm_do: not enough room in buffer\n");
1041: break;
1042: }
1043: }
1044:
1045: void
1046: lm_dont(cmd, len)
1047: unsigned char *cmd;
1048: int len;
1049: {
1050: if (len < 1) {
1051: /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
1052: return;
1053: }
1054: switch(cmd[0]) {
1055: case LM_FORWARDMASK:
1056: default:
1057: /* we are always WONT, so don't respond */
1058: break;
1059: }
1060: }
1061:
1062: static unsigned char str_lm_mode[] = {
1063: IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1064: };
1065:
1066: void
1067: lm_mode(cmd, len, init)
1068: unsigned char *cmd;
1069: int len, init;
1070: {
1071: if (len != 1)
1072: return;
1073: if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
1074: return;
1075: if (*cmd&MODE_ACK)
1076: return;
1077: linemode = *cmd&(MODE_MASK&~MODE_ACK);
1078: str_lm_mode[4] = linemode;
1079: if (!init)
1080: str_lm_mode[4] |= MODE_ACK;
1081: if (NETROOM() > sizeof(str_lm_mode)) {
1082: ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
1083: printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
1084: }
1085: /*@*/ else printf("lm_mode: not enough room in buffer\n");
1086: setconnmode(0); /* set changed mode */
1087: }
1088:
1089:
1090:
1091: /*
1092: * slc()
1093: * Handle special character suboption of LINEMODE.
1094: */
1095:
1096: struct spc {
1097: cc_t val;
1098: cc_t *valp;
1099: char flags; /* Current flags & level */
1100: char mylevel; /* Maximum level & flags */
1101: } spc_data[NSLC+1];
1102:
1103: #define SLC_IMPORT 0
1104: #define SLC_EXPORT 1
1105: #define SLC_RVALUE 2
1106: static int slc_mode = SLC_EXPORT;
1107:
1108: void
1109: slc_init()
1110: {
1.13 mpech 1111: struct spc *spcp;
1.1 deraadt 1112:
1113: localchars = 1;
1114: for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
1115: spcp->val = 0;
1116: spcp->valp = 0;
1117: spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1118: }
1119:
1120: #define initfunc(func, flags) { \
1121: spcp = &spc_data[func]; \
1.4 art 1122: if ((spcp->valp = tcval(func))) { \
1.1 deraadt 1123: spcp->val = *spcp->valp; \
1124: spcp->mylevel = SLC_VARIABLE|flags; \
1125: } else { \
1126: spcp->val = 0; \
1127: spcp->mylevel = SLC_DEFAULT; \
1128: } \
1129: }
1130:
1131: initfunc(SLC_SYNCH, 0);
1132: /* No BRK */
1133: initfunc(SLC_AO, 0);
1134: initfunc(SLC_AYT, 0);
1135: /* No EOR */
1136: initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
1137: initfunc(SLC_EOF, 0);
1138: #ifndef SYSV_TERMIO
1139: initfunc(SLC_SUSP, SLC_FLUSHIN);
1140: #endif
1141: initfunc(SLC_EC, 0);
1142: initfunc(SLC_EL, 0);
1143: #ifndef SYSV_TERMIO
1144: initfunc(SLC_EW, 0);
1145: initfunc(SLC_RP, 0);
1146: initfunc(SLC_LNEXT, 0);
1147: #endif
1148: initfunc(SLC_XON, 0);
1149: initfunc(SLC_XOFF, 0);
1150: #ifdef SYSV_TERMIO
1151: spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
1152: spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
1153: #endif
1154: initfunc(SLC_FORW1, 0);
1155: #ifdef USE_TERMIO
1156: initfunc(SLC_FORW2, 0);
1157: /* No FORW2 */
1158: #endif
1159:
1160: initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
1161: #undef initfunc
1162:
1163: if (slc_mode == SLC_EXPORT)
1164: slc_export();
1165: else
1166: slc_import(1);
1167:
1168: }
1169:
1170: void
1171: slcstate()
1172: {
1173: printf("Special characters are %s values\n",
1174: slc_mode == SLC_IMPORT ? "remote default" :
1175: slc_mode == SLC_EXPORT ? "local" :
1176: "remote");
1177: }
1178:
1179: void
1180: slc_mode_export()
1181: {
1182: slc_mode = SLC_EXPORT;
1183: if (my_state_is_will(TELOPT_LINEMODE))
1184: slc_export();
1185: }
1186:
1187: void
1188: slc_mode_import(def)
1189: int def;
1190: {
1191: slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1192: if (my_state_is_will(TELOPT_LINEMODE))
1193: slc_import(def);
1194: }
1195:
1196: unsigned char slc_import_val[] = {
1197: IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1198: };
1199: unsigned char slc_import_def[] = {
1200: IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1201: };
1202:
1203: void
1204: slc_import(def)
1205: int def;
1206: {
1207: if (NETROOM() > sizeof(slc_import_val)) {
1208: if (def) {
1209: ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1210: printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1211: } else {
1212: ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1213: printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1214: }
1215: }
1216: /*@*/ else printf("slc_import: not enough room\n");
1217: }
1218:
1219: void
1220: slc_export()
1221: {
1.13 mpech 1222: struct spc *spcp;
1.1 deraadt 1223:
1224: TerminalDefaultChars();
1225:
1226: slc_start_reply();
1227: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1228: if (spcp->mylevel != SLC_NOSUPPORT) {
1229: if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1230: spcp->flags = SLC_NOSUPPORT;
1231: else
1232: spcp->flags = spcp->mylevel;
1233: if (spcp->valp)
1234: spcp->val = *spcp->valp;
1235: slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1236: }
1237: }
1238: slc_end_reply();
1239: (void)slc_update();
1240: setconnmode(1); /* Make sure the character values are set */
1241: }
1242:
1243: void
1244: slc(cp, len)
1.13 mpech 1245: unsigned char *cp;
1.1 deraadt 1246: int len;
1247: {
1.13 mpech 1248: struct spc *spcp;
1249: int func,level;
1.1 deraadt 1250:
1251: slc_start_reply();
1252:
1253: for (; len >= 3; len -=3, cp +=3) {
1254:
1255: func = cp[SLC_FUNC];
1256:
1257: if (func == 0) {
1258: /*
1259: * Client side: always ignore 0 function.
1260: */
1261: continue;
1262: }
1263: if (func > NSLC) {
1264: if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1265: slc_add_reply(func, SLC_NOSUPPORT, 0);
1266: continue;
1267: }
1268:
1269: spcp = &spc_data[func];
1270:
1271: level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1272:
1273: if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1274: ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1275: continue;
1276: }
1277:
1278: if (level == (SLC_DEFAULT|SLC_ACK)) {
1279: /*
1280: * This is an error condition, the SLC_ACK
1281: * bit should never be set for the SLC_DEFAULT
1282: * level. Our best guess to recover is to
1283: * ignore the SLC_ACK bit.
1284: */
1285: cp[SLC_FLAGS] &= ~SLC_ACK;
1286: }
1287:
1288: if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1289: spcp->val = (cc_t)cp[SLC_VALUE];
1290: spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
1291: continue;
1292: }
1293:
1294: level &= ~SLC_ACK;
1295:
1296: if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1297: spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1298: spcp->val = (cc_t)cp[SLC_VALUE];
1299: }
1300: if (level == SLC_DEFAULT) {
1301: if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1302: spcp->flags = spcp->mylevel;
1303: else
1304: spcp->flags = SLC_NOSUPPORT;
1305: }
1306: slc_add_reply(func, spcp->flags, spcp->val);
1307: }
1308: slc_end_reply();
1309: if (slc_update())
1310: setconnmode(1); /* set the new character values */
1311: }
1312:
1313: void
1314: slc_check()
1315: {
1.13 mpech 1316: struct spc *spcp;
1.1 deraadt 1317:
1318: slc_start_reply();
1319: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1320: if (spcp->valp && spcp->val != *spcp->valp) {
1321: spcp->val = *spcp->valp;
1322: if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1323: spcp->flags = SLC_NOSUPPORT;
1324: else
1325: spcp->flags = spcp->mylevel;
1326: slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1327: }
1328: }
1329: slc_end_reply();
1330: setconnmode(1);
1331: }
1332:
1333:
1.19 ! otto 1334: static unsigned char slc_reply[2 * SUBBUFSIZE];
! 1335: static unsigned char *slc_replyp;
! 1336:
! 1337: unsigned char
! 1338: slc_add(unsigned char ch)
! 1339: {
! 1340: if (slc_replyp == slc_reply + sizeof(slc_reply))
! 1341: return ch;
! 1342: return *slc_replyp++ = ch;
! 1343: }
1.1 deraadt 1344:
1345: void
1346: slc_start_reply()
1347: {
1348: slc_replyp = slc_reply;
1.19 ! otto 1349: slc_add(IAC);
! 1350: slc_add(SB);
! 1351: slc_add(TELOPT_LINEMODE);
! 1352: slc_add(LM_SLC);
1.1 deraadt 1353: }
1354:
1355: void
1356: slc_add_reply(func, flags, value)
1357: unsigned char func;
1358: unsigned char flags;
1359: cc_t value;
1360: {
1.19 ! otto 1361: if (slc_replyp + 6 >= slc_reply + sizeof(slc_reply)) {
! 1362: printf("slc_add_reply: not enough room\n");
! 1363: return;
! 1364: }
! 1365: if (slc_add(func) == IAC)
! 1366: slc_add(IAC);
! 1367: if (slc_add(flags) == IAC)
! 1368: slc_add(IAC);
! 1369: if (slc_add((unsigned char)value) == IAC)
! 1370: slc_add(IAC);
1.1 deraadt 1371: }
1372:
1373: void
1374: slc_end_reply()
1375: {
1.13 mpech 1376: int len;
1.1 deraadt 1377:
1.19 ! otto 1378: if (slc_replyp + 2 >= slc_reply + sizeof(slc_reply)) {
! 1379: printf("slc_end_reply: not enough room\n");
! 1380: return;
! 1381: }
! 1382:
! 1383: slc_add(IAC);
! 1384: slc_add(SE);
1.1 deraadt 1385: len = slc_replyp - slc_reply;
1386: if (len <= 6)
1387: return;
1388: if (NETROOM() > len) {
1389: ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1390: printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1391: }
1392: /*@*/else printf("slc_end_reply: not enough room\n");
1393: }
1394:
1395: int
1396: slc_update()
1397: {
1.13 mpech 1398: struct spc *spcp;
1.1 deraadt 1399: int need_update = 0;
1400:
1401: for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1402: if (!(spcp->flags&SLC_ACK))
1403: continue;
1404: spcp->flags &= ~SLC_ACK;
1405: if (spcp->valp && (*spcp->valp != spcp->val)) {
1406: *spcp->valp = spcp->val;
1407: need_update = 1;
1408: }
1409: }
1410: return(need_update);
1411: }
1412:
1413: #ifdef OLD_ENVIRON
1414: # ifdef ENV_HACK
1415: /*
1416: * Earlier version of telnet/telnetd from the BSD code had
1417: * the definitions of VALUE and VAR reversed. To ensure
1418: * maximum interoperability, we assume that the server is
1419: * an older BSD server, until proven otherwise. The newer
1420: * BSD servers should be able to handle either definition,
1421: * so it is better to use the wrong values if we don't
1422: * know what type of server it is.
1423: */
1424: int env_auto = 1;
1425: int old_env_var = OLD_ENV_VAR;
1426: int old_env_value = OLD_ENV_VALUE;
1427: # else
1428: # define old_env_var OLD_ENV_VAR
1429: # define old_env_value OLD_ENV_VALUE
1430: # endif
1431: #endif
1432:
1433: void
1434: env_opt(buf, len)
1.13 mpech 1435: unsigned char *buf;
1436: int len;
1.1 deraadt 1437: {
1.13 mpech 1438: unsigned char *ep = 0, *epc = 0;
1439: int i;
1.1 deraadt 1440:
1441: switch(buf[0]&0xff) {
1442: case TELQUAL_SEND:
1443: env_opt_start();
1444: if (len == 1) {
1445: env_opt_add(NULL);
1446: } else for (i = 1; i < len; i++) {
1447: switch (buf[i]&0xff) {
1448: #ifdef OLD_ENVIRON
1449: case OLD_ENV_VAR:
1450: # ifdef ENV_HACK
1451: if (telopt_environ == TELOPT_OLD_ENVIRON
1452: && env_auto) {
1453: /* Server has the same definitions */
1454: old_env_var = OLD_ENV_VAR;
1455: old_env_value = OLD_ENV_VALUE;
1456: }
1457: /* FALL THROUGH */
1458: # endif
1459: case OLD_ENV_VALUE:
1460: /*
1461: * Although OLD_ENV_VALUE is not legal, we will
1462: * still recognize it, just in case it is an
1463: * old server that has VAR & VALUE mixed up...
1464: */
1465: /* FALL THROUGH */
1466: #else
1467: case NEW_ENV_VAR:
1468: #endif
1469: case ENV_USERVAR:
1470: if (ep) {
1471: *epc = 0;
1472: env_opt_add(ep);
1473: }
1474: ep = epc = &buf[i+1];
1475: break;
1476: case ENV_ESC:
1477: i++;
1478: /*FALL THROUGH*/
1479: default:
1480: if (epc)
1481: *epc++ = buf[i];
1482: break;
1483: }
1484: }
1485: if (ep) {
1486: *epc = 0;
1487: env_opt_add(ep);
1488: }
1489: env_opt_end(1);
1490: break;
1491:
1492: case TELQUAL_IS:
1493: case TELQUAL_INFO:
1494: /* Ignore for now. We shouldn't get it anyway. */
1495: break;
1496:
1497: default:
1498: break;
1499: }
1500: }
1501:
1.19 ! otto 1502: #define OPT_REPLY_SIZE (2 * SUBBUFSIZE)
! 1503: static unsigned char *opt_reply;
! 1504: static unsigned char *opt_replyp;
! 1505: static unsigned char *opt_replyend;
1.1 deraadt 1506:
1507: void
1.19 ! otto 1508: opt_add(unsigned char ch)
! 1509: {
! 1510: if (opt_replyp == opt_replyend)
! 1511: return;
! 1512: *opt_replyp++ = ch;
! 1513: }
! 1514: void
1.1 deraadt 1515: env_opt_start()
1516: {
1.8 itojun 1517: unsigned char *p;
1518:
1519: if (opt_reply) {
1520: p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
1521: if (p == NULL)
1522: free(opt_reply);
1523: } else
1524: p = (unsigned char *)malloc(OPT_REPLY_SIZE);
1525: opt_reply = p;
1.1 deraadt 1526: if (opt_reply == NULL) {
1527: /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
1528: opt_reply = opt_replyp = opt_replyend = NULL;
1529: return;
1530: }
1531: opt_replyp = opt_reply;
1532: opt_replyend = opt_reply + OPT_REPLY_SIZE;
1.19 ! otto 1533: opt_add(IAC);
! 1534: opt_add(SB);
! 1535: opt_add(telopt_environ);
! 1536: opt_add(TELQUAL_IS);
1.1 deraadt 1537: }
1538:
1539: void
1540: env_opt_start_info()
1541: {
1542: env_opt_start();
1543: if (opt_replyp)
1544: opt_replyp[-1] = TELQUAL_INFO;
1545: }
1546:
1547: void
1548: env_opt_add(ep)
1.13 mpech 1549: unsigned char *ep;
1.1 deraadt 1550: {
1.13 mpech 1551: unsigned char *vp, c;
1.1 deraadt 1552:
1553: if (opt_reply == NULL) /*XXX*/
1554: return; /*XXX*/
1555:
1556: if (ep == NULL || *ep == '\0') {
1557: /* Send user defined variables first. */
1558: env_default(1, 0);
1.4 art 1559: while ((ep = env_default(0, 0)))
1.1 deraadt 1560: env_opt_add(ep);
1561:
1562: /* Now add the list of well know variables. */
1563: env_default(1, 1);
1.4 art 1564: while ((ep = env_default(0, 1)))
1.1 deraadt 1565: env_opt_add(ep);
1566: return;
1567: }
1.19 ! otto 1568: vp = env_getvalue(ep, 1);
! 1569: if (opt_replyp + 2 * (vp ? strlen((char *)vp) : 0) +
! 1570: 2 * strlen((char *)ep) + 6 > opt_replyend)
1.1 deraadt 1571: {
1.19 ! otto 1572: size_t len;
1.8 itojun 1573: unsigned char *p;
1.19 ! otto 1574:
1.1 deraadt 1575: len = opt_replyend - opt_reply;
1.19 ! otto 1576: len += OPT_REPLY_SIZE + 2 * strlen(ep);
! 1577: if (vp)
! 1578: len += 2 * strlen(vp);
1.8 itojun 1579: p = (unsigned char *)realloc(opt_reply, len);
1.19 ! otto 1580: if (p == NULL) {
1.8 itojun 1581: free(opt_reply);
1.1 deraadt 1582: /*@*/ printf("env_opt_add: realloc() failed!!!\n");
1583: opt_reply = opt_replyp = opt_replyend = NULL;
1584: return;
1585: }
1.19 ! otto 1586: opt_replyp = p + (opt_replyp - opt_reply);
! 1587: opt_replyend = p + len;
! 1588: opt_reply = p;
1.1 deraadt 1589: }
1.4 art 1590: if (opt_welldefined((char *)ep))
1.1 deraadt 1591: #ifdef OLD_ENVIRON
1592: if (telopt_environ == TELOPT_OLD_ENVIRON)
1.19 ! otto 1593: opt_add(old_env_var);
1.1 deraadt 1594: else
1595: #endif
1.19 ! otto 1596: opt_add(NEW_ENV_VAR);
1.1 deraadt 1597: else
1.19 ! otto 1598: opt_add(ENV_USERVAR);
! 1599:
1.1 deraadt 1600: for (;;) {
1.4 art 1601: while ((c = *ep++)) {
1.1 deraadt 1602: switch(c&0xff) {
1603: case IAC:
1.19 ! otto 1604: opt_add(IAC);
1.1 deraadt 1605: break;
1606: case NEW_ENV_VAR:
1607: case NEW_ENV_VALUE:
1608: case ENV_ESC:
1609: case ENV_USERVAR:
1.19 ! otto 1610: opt_add(ENV_ESC);
1.1 deraadt 1611: break;
1612: }
1.19 ! otto 1613: opt_add(c);
1.1 deraadt 1614: }
1.4 art 1615: if ((ep = vp)) {
1.1 deraadt 1616: #ifdef OLD_ENVIRON
1617: if (telopt_environ == TELOPT_OLD_ENVIRON)
1.19 ! otto 1618: opt_add(old_env_value);
1.1 deraadt 1619: else
1620: #endif
1.19 ! otto 1621: opt_add(NEW_ENV_VALUE);
1.1 deraadt 1622: vp = NULL;
1623: } else
1624: break;
1625: }
1626: }
1627:
1628: int
1629: opt_welldefined(ep)
1630: char *ep;
1631: {
1632: if ((strcmp(ep, "USER") == 0) ||
1633: (strcmp(ep, "DISPLAY") == 0) ||
1634: (strcmp(ep, "PRINTER") == 0) ||
1635: (strcmp(ep, "SYSTEMTYPE") == 0) ||
1636: (strcmp(ep, "JOB") == 0) ||
1637: (strcmp(ep, "ACCT") == 0))
1638: return(1);
1639: return(0);
1640: }
1641: void
1642: env_opt_end(emptyok)
1.13 mpech 1643: int emptyok;
1.1 deraadt 1644: {
1.13 mpech 1645: int len;
1.1 deraadt 1646:
1647: len = opt_replyp - opt_reply + 2;
1648: if (emptyok || len > 6) {
1.19 ! otto 1649: opt_add(IAC);
! 1650: opt_add(SE);
1.1 deraadt 1651: if (NETROOM() > len) {
1652: ring_supply_data(&netoring, opt_reply, len);
1653: printsub('>', &opt_reply[2], len - 2);
1654: }
1655: /*@*/ else printf("slc_end_reply: not enough room\n");
1656: }
1657: if (opt_reply) {
1658: free(opt_reply);
1659: opt_reply = opt_replyp = opt_replyend = NULL;
1660: }
1661: }
1662:
1663:
1664:
1665: int
1666: telrcv()
1667: {
1.13 mpech 1668: int c;
1669: int scc;
1670: unsigned char *sbp;
1.1 deraadt 1671: int count;
1672: int returnValue = 0;
1673:
1674: scc = 0;
1675: count = 0;
1676: while (TTYROOM() > 2) {
1677: if (scc == 0) {
1678: if (count) {
1679: ring_consumed(&netiring, count);
1680: returnValue = 1;
1681: count = 0;
1682: }
1683: sbp = netiring.consume;
1684: scc = ring_full_consecutive(&netiring);
1685: if (scc == 0) {
1686: /* No more data coming in */
1687: break;
1688: }
1689: }
1690:
1691: c = *sbp++ & 0xff, scc--; count++;
1.4 art 1692: #if defined(ENCRYPTION)
1693: if (decrypt_input)
1694: c = (*decrypt_input)(c);
1695: #endif
1.1 deraadt 1696:
1697: switch (telrcv_state) {
1698:
1699: case TS_CR:
1700: telrcv_state = TS_DATA;
1701: if (c == '\0') {
1702: break; /* Ignore \0 after CR */
1703: }
1704: else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1705: TTYADD(c);
1706: break;
1707: }
1708: /* Else, fall through */
1709:
1710: case TS_DATA:
1711: if (c == IAC) {
1712: telrcv_state = TS_IAC;
1713: break;
1714: }
1715: # if defined(TN3270)
1716: if (In3270) {
1717: *Ifrontp++ = c;
1718: while (scc > 0) {
1719: c = *sbp++ & 0377, scc--; count++;
1720: if (c == IAC) {
1721: telrcv_state = TS_IAC;
1722: break;
1723: }
1724: *Ifrontp++ = c;
1725: }
1726: } else
1727: # endif /* defined(TN3270) */
1728: /*
1729: * The 'crmod' hack (see following) is needed
1.4 art 1730: * since we can't set CRMOD on output only.
1.1 deraadt 1731: * Machines like MULTICS like to send \r without
1732: * \n; since we must turn off CRMOD to get proper
1733: * input, the mapping is done here (sigh).
1734: */
1735: if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1736: if (scc > 0) {
1737: c = *sbp&0xff;
1.4 art 1738: #if defined(ENCRYPTION)
1739: if (decrypt_input)
1740: c = (*decrypt_input)(c);
1741: #endif
1.1 deraadt 1742: if (c == 0) {
1743: sbp++, scc--; count++;
1744: /* a "true" CR */
1745: TTYADD('\r');
1746: } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1747: (c == '\n')) {
1748: sbp++, scc--; count++;
1749: TTYADD('\n');
1750: } else {
1.4 art 1751: #if defined(ENCRYPTION)
1752: if (decrypt_input)
1753: (*decrypt_input)(-1);
1754: #endif
1.1 deraadt 1755: TTYADD('\r');
1756: if (crmod) {
1757: TTYADD('\n');
1758: }
1759: }
1760: } else {
1761: telrcv_state = TS_CR;
1762: TTYADD('\r');
1763: if (crmod) {
1764: TTYADD('\n');
1765: }
1766: }
1767: } else {
1768: TTYADD(c);
1769: }
1770: continue;
1771:
1772: case TS_IAC:
1773: process_iac:
1774: switch (c) {
1.2 niklas 1775:
1.1 deraadt 1776: case WILL:
1777: telrcv_state = TS_WILL;
1778: continue;
1779:
1780: case WONT:
1781: telrcv_state = TS_WONT;
1782: continue;
1783:
1784: case DO:
1785: telrcv_state = TS_DO;
1786: continue;
1787:
1788: case DONT:
1789: telrcv_state = TS_DONT;
1790: continue;
1791:
1792: case DM:
1793: /*
1794: * We may have missed an urgent notification,
1795: * so make sure we flush whatever is in the
1796: * buffer currently.
1797: */
1798: printoption("RCVD", IAC, DM);
1799: SYNCHing = 1;
1800: (void) ttyflush(1);
1801: SYNCHing = stilloob();
1802: settimer(gotDM);
1803: break;
1804:
1805: case SB:
1806: SB_CLEAR();
1807: telrcv_state = TS_SB;
1808: continue;
1809:
1810: # if defined(TN3270)
1811: case EOR:
1812: if (In3270) {
1813: if (Ibackp == Ifrontp) {
1814: Ibackp = Ifrontp = Ibuf;
1815: ISend = 0; /* should have been! */
1816: } else {
1817: Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1818: ISend = 1;
1819: }
1820: }
1821: printoption("RCVD", IAC, EOR);
1822: break;
1823: # endif /* defined(TN3270) */
1824:
1825: case IAC:
1826: # if !defined(TN3270)
1827: TTYADD(IAC);
1828: # else /* !defined(TN3270) */
1829: if (In3270) {
1830: *Ifrontp++ = IAC;
1831: } else {
1832: TTYADD(IAC);
1833: }
1834: # endif /* !defined(TN3270) */
1835: break;
1836:
1837: case NOP:
1838: case GA:
1839: default:
1840: printoption("RCVD", IAC, c);
1841: break;
1842: }
1843: telrcv_state = TS_DATA;
1844: continue;
1845:
1846: case TS_WILL:
1847: printoption("RCVD", WILL, c);
1848: willoption(c);
1849: SetIn3270();
1850: telrcv_state = TS_DATA;
1851: continue;
1852:
1853: case TS_WONT:
1854: printoption("RCVD", WONT, c);
1855: wontoption(c);
1856: SetIn3270();
1857: telrcv_state = TS_DATA;
1858: continue;
1859:
1860: case TS_DO:
1861: printoption("RCVD", DO, c);
1862: dooption(c);
1863: SetIn3270();
1864: if (c == TELOPT_NAWS) {
1865: sendnaws();
1866: } else if (c == TELOPT_LFLOW) {
1867: localflow = 1;
1868: setcommandmode();
1869: setconnmode(0);
1870: }
1871: telrcv_state = TS_DATA;
1872: continue;
1873:
1874: case TS_DONT:
1875: printoption("RCVD", DONT, c);
1876: dontoption(c);
1877: flushline = 1;
1878: setconnmode(0); /* set new tty mode (maybe) */
1879: SetIn3270();
1880: telrcv_state = TS_DATA;
1881: continue;
1882:
1883: case TS_SB:
1884: if (c == IAC) {
1885: telrcv_state = TS_SE;
1886: } else {
1887: SB_ACCUM(c);
1888: }
1889: continue;
1890:
1891: case TS_SE:
1892: if (c != SE) {
1893: if (c != IAC) {
1894: /*
1895: * This is an error. We only expect to get
1896: * "IAC IAC" or "IAC SE". Several things may
1.18 jmc 1897: * have happened. An IAC was not doubled, the
1.1 deraadt 1898: * IAC SE was left off, or another option got
1899: * inserted into the suboption are all possibilities.
1900: * If we assume that the IAC was not doubled,
1901: * and really the IAC SE was left off, we could
1902: * get into an infinate loop here. So, instead,
1903: * we terminate the suboption, and process the
1904: * partial suboption if we can.
1905: */
1906: SB_ACCUM(IAC);
1907: SB_ACCUM(c);
1908: subpointer -= 2;
1909: SB_TERM();
1910:
1911: printoption("In SUBOPTION processing, RCVD", IAC, c);
1912: suboption(); /* handle sub-option */
1913: SetIn3270();
1914: telrcv_state = TS_IAC;
1915: goto process_iac;
1916: }
1917: SB_ACCUM(c);
1918: telrcv_state = TS_SB;
1919: } else {
1920: SB_ACCUM(IAC);
1921: SB_ACCUM(SE);
1922: subpointer -= 2;
1923: SB_TERM();
1924: suboption(); /* handle sub-option */
1925: SetIn3270();
1926: telrcv_state = TS_DATA;
1927: }
1928: }
1929: }
1930: if (count)
1931: ring_consumed(&netiring, count);
1932: return returnValue||count;
1933: }
1934:
1935: static int bol = 1, local = 0;
1936:
1937: int
1938: rlogin_susp()
1939: {
1940: if (local) {
1941: local = 0;
1942: bol = 1;
1943: command(0, "z\n", 2);
1944: return(1);
1945: }
1946: return(0);
1947: }
1948:
1949: static int
1950: telsnd()
1951: {
1952: int tcc;
1953: int count;
1954: int returnValue = 0;
1955: unsigned char *tbp;
1956:
1957: tcc = 0;
1958: count = 0;
1959: while (NETROOM() > 2) {
1.13 mpech 1960: int sc;
1961: int c;
1.1 deraadt 1962:
1963: if (tcc == 0) {
1964: if (count) {
1965: ring_consumed(&ttyiring, count);
1966: returnValue = 1;
1967: count = 0;
1968: }
1969: tbp = ttyiring.consume;
1970: tcc = ring_full_consecutive(&ttyiring);
1971: if (tcc == 0) {
1972: break;
1973: }
1974: }
1975: c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
1976: if (rlogin != _POSIX_VDISABLE) {
1977: if (bol) {
1978: bol = 0;
1979: if (sc == rlogin) {
1980: local = 1;
1981: continue;
1982: }
1983: } else if (local) {
1984: local = 0;
1985: if (sc == '.' || c == termEofChar) {
1986: bol = 1;
1987: command(0, "close\n", 6);
1988: continue;
1989: }
1990: if (sc == termSuspChar) {
1991: bol = 1;
1992: command(0, "z\n", 2);
1993: continue;
1994: }
1995: if (sc == escape) {
1996: command(0, (char *)tbp, tcc);
1997: bol = 1;
1998: count += tcc;
1999: tcc = 0;
2000: flushline = 1;
2001: break;
2002: }
2003: if (sc != rlogin) {
2004: ++tcc;
2005: --tbp;
2006: --count;
2007: c = sc = rlogin;
2008: }
2009: }
2010: if ((sc == '\n') || (sc == '\r'))
2011: bol = 1;
1.7 aaron 2012: } else if (escape != _POSIX_VDISABLE && sc == escape) {
1.1 deraadt 2013: /*
2014: * Double escape is a pass through of a single escape character.
2015: */
2016: if (tcc && strip(*tbp) == escape) {
2017: tbp++;
2018: tcc--;
2019: count++;
2020: bol = 0;
2021: } else {
2022: command(0, (char *)tbp, tcc);
2023: bol = 1;
2024: count += tcc;
2025: tcc = 0;
2026: flushline = 1;
2027: break;
2028: }
2029: } else
2030: bol = 0;
2031: #ifdef KLUDGELINEMODE
2032: if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
2033: if (tcc > 0 && strip(*tbp) == echoc) {
2034: tcc--; tbp++; count++;
2035: } else {
2036: dontlecho = !dontlecho;
2037: settimer(echotoggle);
2038: setconnmode(0);
2039: flushline = 1;
2040: break;
2041: }
2042: }
2043: #endif
1.3 deraadt 2044: if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
1.1 deraadt 2045: if (TerminalSpecialChars(sc) == 0) {
2046: bol = 1;
2047: break;
2048: }
2049: }
2050: if (my_want_state_is_wont(TELOPT_BINARY)) {
2051: switch (c) {
2052: case '\n':
2053: /*
2054: * If we are in CRMOD mode (\r ==> \n)
2055: * on our local machine, then probably
2056: * a newline (unix) is CRLF (TELNET).
2057: */
2058: if (MODE_LOCAL_CHARS(globalmode)) {
2059: NETADD('\r');
2060: }
2061: NETADD('\n');
2062: bol = flushline = 1;
2063: break;
2064: case '\r':
2065: if (!crlf) {
2066: NET2ADD('\r', '\0');
2067: } else {
2068: NET2ADD('\r', '\n');
2069: }
2070: bol = flushline = 1;
2071: break;
2072: case IAC:
2073: NET2ADD(IAC, IAC);
2074: break;
2075: default:
2076: NETADD(c);
2077: break;
2078: }
2079: } else if (c == IAC) {
2080: NET2ADD(IAC, IAC);
2081: } else {
2082: NETADD(c);
2083: }
2084: }
2085: if (count)
2086: ring_consumed(&ttyiring, count);
2087: return returnValue||count; /* Non-zero if we did anything */
2088: }
2089:
2090: /*
2091: * Scheduler()
2092: *
2093: * Try to do something.
2094: *
2095: * If we do something useful, return 1; else return 0.
2096: *
2097: */
2098:
2099:
2100: int
2101: Scheduler(block)
2102: int block; /* should we block in the select ? */
2103: {
2104: /* One wants to be a bit careful about setting returnValue
2105: * to one, since a one implies we did some useful work,
2106: * and therefore probably won't be called to block next
2107: * time (TN3270 mode only).
2108: */
2109: int returnValue;
2110: int netin, netout, netex, ttyin, ttyout;
2111:
2112: /* Decide which rings should be processed */
2113:
2114: netout = ring_full_count(&netoring) &&
2115: (flushline ||
2116: (my_want_state_is_wont(TELOPT_LINEMODE)
2117: #ifdef KLUDGELINEMODE
2118: && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
2119: #endif
2120: ) ||
2121: my_want_state_is_will(TELOPT_BINARY));
2122: ttyout = ring_full_count(&ttyoring);
2123:
2124: #if defined(TN3270)
2125: ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
2126: #else /* defined(TN3270) */
2127: ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
2128: #endif /* defined(TN3270) */
2129:
2130: #if defined(TN3270)
2131: netin = ring_empty_count(&netiring);
2132: # else /* !defined(TN3270) */
2133: netin = !ISend && ring_empty_count(&netiring);
2134: # endif /* !defined(TN3270) */
2135:
2136: netex = !SYNCHing;
2137:
2138: /* If we have seen a signal recently, reset things */
1.15 hin 2139:
2140: if (scheduler_lockout_tty) {
2141: ttyin = ttyout = 0;
2142: }
2143:
1.1 deraadt 2144: # if defined(TN3270) && defined(unix)
2145: if (HaveInput) {
2146: HaveInput = 0;
2147: (void) signal(SIGIO, inputAvailable);
2148: }
2149: #endif /* defined(TN3270) && defined(unix) */
2150:
2151: /* Call to system code to process rings */
2152:
2153: returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
2154:
2155: /* Now, look at the input rings, looking for work to do. */
2156:
2157: if (ring_full_count(&ttyiring)) {
2158: # if defined(TN3270)
2159: if (In3270) {
2160: int c;
2161:
2162: c = DataFromTerminal(ttyiring.consume,
2163: ring_full_consecutive(&ttyiring));
2164: if (c) {
2165: returnValue = 1;
1.2 niklas 2166: ring_consumed(&ttyiring, c);
1.1 deraadt 2167: }
2168: } else {
2169: # endif /* defined(TN3270) */
2170: returnValue |= telsnd();
2171: # if defined(TN3270)
2172: }
2173: # endif /* defined(TN3270) */
2174: }
2175:
2176: if (ring_full_count(&netiring)) {
2177: # if !defined(TN3270)
2178: returnValue |= telrcv();
2179: # else /* !defined(TN3270) */
2180: returnValue = Push3270();
2181: # endif /* !defined(TN3270) */
2182: }
2183: return returnValue;
2184: }
2185:
2186: /*
2187: * Select from tty and network...
2188: */
2189: void
2190: telnet(user)
2191: char *user;
2192: {
1.15 hin 2193: int printed_encrypt = 0;
2194:
1.1 deraadt 2195: sys_telnet_init();
2196:
1.4 art 2197: #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1 deraadt 2198: {
2199: static char local_host[256] = { 0 };
2200:
2201: if (!local_host[0]) {
2202: gethostname(local_host, sizeof(local_host));
2203: local_host[sizeof(local_host)-1] = 0;
2204: }
2205: auth_encrypt_init(local_host, hostname, "TELNET", 0);
2206: auth_encrypt_user(user);
2207: }
1.4 art 2208: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1 deraadt 2209: # if !defined(TN3270)
2210: if (telnetport) {
2211: #if defined(AUTHENTICATION)
2212: if (autologin)
2213: send_will(TELOPT_AUTHENTICATION, 1);
2214: #endif
1.4 art 2215: #if defined(ENCRYPTION)
2216: send_do(TELOPT_ENCRYPT, 1);
2217: send_will(TELOPT_ENCRYPT, 1);
2218: #endif
1.1 deraadt 2219: send_do(TELOPT_SGA, 1);
2220: send_will(TELOPT_TTYPE, 1);
2221: send_will(TELOPT_NAWS, 1);
2222: send_will(TELOPT_TSPEED, 1);
2223: send_will(TELOPT_LFLOW, 1);
2224: send_will(TELOPT_LINEMODE, 1);
2225: send_will(TELOPT_NEW_ENVIRON, 1);
2226: send_do(TELOPT_STATUS, 1);
1.19 ! otto 2227: if (env_getvalue((unsigned char *)"DISPLAY", 0))
1.1 deraadt 2228: send_will(TELOPT_XDISPLOC, 1);
1.4 art 2229: if (binary)
2230: tel_enter_binary(binary);
1.1 deraadt 2231: }
2232: # endif /* !defined(TN3270) */
2233:
1.15 hin 2234: #ifdef ENCRYPTION
2235: /*
2236: * Note: we assume a tie to the authentication option here. This
2237: * is necessary so that authentication fails, we don't spin
2238: * forever.
2239: */
2240: if (wantencryption) {
2241: extern int auth_has_failed;
2242: time_t timeout = time(0) + 60;
2243:
2244: send_do(TELOPT_ENCRYPT, 1);
2245: send_will(TELOPT_ENCRYPT, 1);
2246: while (1) {
2247: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
2248: if (wantencryption == -1) {
2249: break;
2250: } else {
2251: printf("\nServer refused to negotiate authentication,");
2252: printf(" which is required for encryption.\n");
2253: Exit(1);
2254: }
2255: }
2256: if (auth_has_failed) {
1.17 jmc 2257: printf("\nAuthentication negotiation has failed,");
1.15 hin 2258: printf(" which is required for encryption.\n");
2259: Exit(1);
2260: }
2261: if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
2262: my_want_state_is_wont(TELOPT_ENCRYPT)) {
2263: printf("\nServer refused to negotiate encryption.\n");
2264: Exit(1);
2265: }
2266: if (encrypt_is_encrypting())
2267: break;
2268: if (time(0) > timeout) {
2269: printf("\nEncryption could not be enabled.\n");
2270: Exit(1);
2271: }
2272: if (printed_encrypt == 0) {
2273: printed_encrypt = 1;
2274: printf("Waiting for encryption to be negotiated...\n");
2275: /*
2276: * Turn on MODE_TRAPSIG and then turn off localchars
2277: * so that ^C will cause telnet to exit.
2278: */
2279: TerminalNewMode(getconnmode()|MODE_TRAPSIG);
2280: intr_waiting = 1;
2281: }
2282: if (intr_happened) {
2283: printf("\nUser interrupt.\n");
2284: Exit(1);
2285: }
2286: telnet_spin();
2287: }
2288: if (printed_encrypt) {
2289: printf("Encryption negotiated.\n");
2290: intr_waiting = 0;
2291: setconnmode(0);
2292: }
2293: }
2294: #endif
2295:
1.1 deraadt 2296: # if !defined(TN3270)
2297: for (;;) {
2298: int schedValue;
2299:
2300: while ((schedValue = Scheduler(0)) != 0) {
2301: if (schedValue == -1) {
2302: setcommandmode();
2303: return;
2304: }
2305: }
2306:
2307: if (Scheduler(1) == -1) {
2308: setcommandmode();
2309: return;
2310: }
2311: }
2312: # else /* !defined(TN3270) */
2313: for (;;) {
2314: int schedValue;
2315:
2316: while (!In3270 && !shell_active) {
2317: if (Scheduler(1) == -1) {
2318: setcommandmode();
2319: return;
2320: }
2321: }
2322:
2323: while ((schedValue = Scheduler(0)) != 0) {
2324: if (schedValue == -1) {
2325: setcommandmode();
2326: return;
2327: }
2328: }
2329: /* If there is data waiting to go out to terminal, don't
2330: * schedule any more data for the terminal.
2331: */
2332: if (ring_full_count(&ttyoring)) {
2333: schedValue = 1;
2334: } else {
2335: if (shell_active) {
2336: if (shell_continue() == 0) {
2337: ConnectScreen();
2338: }
2339: } else if (In3270) {
2340: schedValue = DoTerminalOutput();
2341: }
2342: }
2343: if (schedValue && (shell_active == 0)) {
2344: if (Scheduler(1) == -1) {
2345: setcommandmode();
2346: return;
2347: }
2348: }
2349: }
2350: # endif /* !defined(TN3270) */
2351: }
2352:
2353: #if 0 /* XXX - this not being in is a bug */
2354: /*
2355: * nextitem()
2356: *
2357: * Return the address of the next "item" in the TELNET data
2358: * stream. This will be the address of the next character if
2359: * the current address is a user data character, or it will
2360: * be the address of the character following the TELNET command
2361: * if the current address is a TELNET IAC ("I Am a Command")
2362: * character.
2363: */
2364:
2365: static char *
2366: nextitem(current)
2367: char *current;
2368: {
2369: if ((*current&0xff) != IAC) {
2370: return current+1;
2371: }
2372: switch (*(current+1)&0xff) {
2373: case DO:
2374: case DONT:
2375: case WILL:
2376: case WONT:
2377: return current+3;
2378: case SB: /* loop forever looking for the SE */
2379: {
1.13 mpech 2380: char *look = current+2;
1.1 deraadt 2381:
2382: for (;;) {
2383: if ((*look++&0xff) == IAC) {
2384: if ((*look++&0xff) == SE) {
2385: return look;
2386: }
2387: }
2388: }
2389: }
2390: default:
2391: return current+2;
2392: }
2393: }
2394: #endif /* 0 */
2395:
2396: /*
2397: * netclear()
2398: *
2399: * We are about to do a TELNET SYNCH operation. Clear
2400: * the path to the network.
2401: *
2402: * Things are a bit tricky since we may have sent the first
2403: * byte or so of a previous TELNET command into the network.
2404: * So, we have to scan the network buffer from the beginning
2405: * until we are up to where we want to be.
2406: *
2407: * A side effect of what we do, just to keep things
2408: * simple, is to clear the urgent data pointer. The principal
2409: * caller should be setting the urgent data pointer AFTER calling
2410: * us in any case.
2411: */
2412:
2413: static void
2414: netclear()
2415: {
2416: #if 0 /* XXX */
1.13 mpech 2417: char *thisitem, *next;
1.1 deraadt 2418: char *good;
2419: #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2420: ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2421:
2422: thisitem = netobuf;
2423:
2424: while ((next = nextitem(thisitem)) <= netobuf.send) {
2425: thisitem = next;
2426: }
2427:
2428: /* Now, thisitem is first before/at boundary. */
2429:
2430: good = netobuf; /* where the good bytes go */
2431:
2432: while (netoring.add > thisitem) {
2433: if (wewant(thisitem)) {
2434: int length;
2435:
2436: next = thisitem;
2437: do {
2438: next = nextitem(next);
2439: } while (wewant(next) && (nfrontp > next));
2440: length = next-thisitem;
1.2 niklas 2441: memmove(good, thisitem, length);
1.1 deraadt 2442: good += length;
2443: thisitem = next;
2444: } else {
2445: thisitem = nextitem(thisitem);
2446: }
2447: }
2448:
2449: #endif /* 0 */
2450: }
2451:
2452: /*
2453: * These routines add various telnet commands to the data stream.
2454: */
2455:
2456: static void
2457: doflush()
2458: {
2459: NET2ADD(IAC, DO);
2460: NETADD(TELOPT_TM);
2461: flushline = 1;
2462: flushout = 1;
2463: (void) ttyflush(1); /* Flush/drop output */
2464: /* do printoption AFTER flush, otherwise the output gets tossed... */
2465: printoption("SENT", DO, TELOPT_TM);
2466: }
2467:
2468: void
2469: xmitAO()
2470: {
2471: NET2ADD(IAC, AO);
2472: printoption("SENT", IAC, AO);
2473: if (autoflush) {
2474: doflush();
2475: }
2476: }
2477:
2478:
2479: void
2480: xmitEL()
2481: {
2482: NET2ADD(IAC, EL);
2483: printoption("SENT", IAC, EL);
2484: }
2485:
2486: void
2487: xmitEC()
2488: {
2489: NET2ADD(IAC, EC);
2490: printoption("SENT", IAC, EC);
2491: }
2492:
2493:
2494: int
2495: dosynch()
2496: {
2497: netclear(); /* clear the path to the network */
2498: NETADD(IAC);
2499: setneturg();
2500: NETADD(DM);
2501: printoption("SENT", IAC, DM);
2502: return 1;
2503: }
2504:
2505: int want_status_response = 0;
2506:
2507: int
2508: get_status()
2509: {
2510: unsigned char tmp[16];
1.13 mpech 2511: unsigned char *cp;
1.1 deraadt 2512:
2513: if (my_want_state_is_dont(TELOPT_STATUS)) {
2514: printf("Remote side does not support STATUS option\n");
2515: return 0;
2516: }
2517: cp = tmp;
2518:
2519: *cp++ = IAC;
2520: *cp++ = SB;
2521: *cp++ = TELOPT_STATUS;
2522: *cp++ = TELQUAL_SEND;
2523: *cp++ = IAC;
2524: *cp++ = SE;
2525: if (NETROOM() >= cp - tmp) {
2526: ring_supply_data(&netoring, tmp, cp-tmp);
2527: printsub('>', tmp+2, cp - tmp - 2);
2528: }
2529: ++want_status_response;
2530: return 1;
2531: }
2532:
2533: void
2534: intp()
2535: {
2536: NET2ADD(IAC, IP);
2537: printoption("SENT", IAC, IP);
2538: flushline = 1;
2539: if (autoflush) {
2540: doflush();
2541: }
2542: if (autosynch) {
2543: dosynch();
2544: }
2545: }
2546:
2547: void
2548: sendbrk()
2549: {
2550: NET2ADD(IAC, BREAK);
2551: printoption("SENT", IAC, BREAK);
2552: flushline = 1;
2553: if (autoflush) {
2554: doflush();
2555: }
2556: if (autosynch) {
2557: dosynch();
2558: }
2559: }
2560:
2561: void
2562: sendabort()
2563: {
2564: NET2ADD(IAC, ABORT);
2565: printoption("SENT", IAC, ABORT);
2566: flushline = 1;
2567: if (autoflush) {
2568: doflush();
2569: }
2570: if (autosynch) {
2571: dosynch();
2572: }
2573: }
2574:
2575: void
2576: sendsusp()
2577: {
2578: NET2ADD(IAC, SUSP);
2579: printoption("SENT", IAC, SUSP);
2580: flushline = 1;
2581: if (autoflush) {
2582: doflush();
2583: }
2584: if (autosynch) {
2585: dosynch();
2586: }
2587: }
2588:
2589: void
2590: sendeof()
2591: {
2592: NET2ADD(IAC, xEOF);
2593: printoption("SENT", IAC, xEOF);
2594: }
2595:
2596: void
2597: sendayt()
2598: {
2599: NET2ADD(IAC, AYT);
2600: printoption("SENT", IAC, AYT);
2601: }
2602:
2603: /*
2604: * Send a window size update to the remote system.
2605: */
2606:
2607: void
2608: sendnaws()
2609: {
2610: long rows, cols;
2611: unsigned char tmp[16];
1.13 mpech 2612: unsigned char *cp;
1.1 deraadt 2613:
2614: if (my_state_is_wont(TELOPT_NAWS))
2615: return;
2616:
2617: #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2618: if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2619:
2620: if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
2621: return;
2622: }
2623:
2624: cp = tmp;
2625:
2626: *cp++ = IAC;
2627: *cp++ = SB;
2628: *cp++ = TELOPT_NAWS;
2629: PUTSHORT(cp, cols);
2630: PUTSHORT(cp, rows);
2631: *cp++ = IAC;
2632: *cp++ = SE;
2633: if (NETROOM() >= cp - tmp) {
2634: ring_supply_data(&netoring, tmp, cp-tmp);
2635: printsub('>', tmp+2, cp - tmp - 2);
2636: }
2637: }
2638:
2639: void
2640: tel_enter_binary(rw)
2641: int rw;
2642: {
2643: if (rw&1)
2644: send_do(TELOPT_BINARY, 1);
2645: if (rw&2)
2646: send_will(TELOPT_BINARY, 1);
2647: }
2648:
2649: void
2650: tel_leave_binary(rw)
2651: int rw;
2652: {
2653: if (rw&1)
2654: send_dont(TELOPT_BINARY, 1);
2655: if (rw&2)
2656: send_wont(TELOPT_BINARY, 1);
2657: }