1/*
2 * Copyright (c) 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "telnetd.h"
35
36RCSID("$Id$");
37
38unsigned char	doopt[] = { IAC, DO, '%', 'c', 0 };
39unsigned char	dont[] = { IAC, DONT, '%', 'c', 0 };
40unsigned char	will[] = { IAC, WILL, '%', 'c', 0 };
41unsigned char	wont[] = { IAC, WONT, '%', 'c', 0 };
42int	not42 = 1;
43
44/*
45 * Buffer for sub-options, and macros
46 * for suboptions buffer manipulations
47 */
48unsigned char subbuffer[1024*64], *subpointer= subbuffer, *subend= subbuffer;
49
50#define	SB_CLEAR()	subpointer = subbuffer
51#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
52#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
53    *subpointer++ = (c); \
54			     }
55#define	SB_GET()	((*subpointer++)&0xff)
56#define	SB_EOF()	(subpointer >= subend)
57#define	SB_LEN()	(subend - subpointer)
58
59#ifdef	ENV_HACK
60unsigned char *subsave;
61#define SB_SAVE()	subsave = subpointer;
62#define	SB_RESTORE()	subpointer = subsave;
63#endif
64
65
66/*
67 * State for recv fsm
68 */
69#define	TS_DATA		0	/* base state */
70#define	TS_IAC		1	/* look for double IAC's */
71#define	TS_CR		2	/* CR-LF ->'s CR */
72#define	TS_SB		3	/* throw away begin's... */
73#define	TS_SE		4	/* ...end's (suboption negotiation) */
74#define	TS_WILL		5	/* will option negotiation */
75#define	TS_WONT		6	/* wont -''- */
76#define	TS_DO		7	/* do -''- */
77#define	TS_DONT		8	/* dont -''- */
78
79void
80telrcv(void)
81{
82    int c;
83    static int state = TS_DATA;
84
85    while (ncc > 0) {
86	if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
87	    break;
88	c = *netip++ & 0377, ncc--;
89#ifdef ENCRYPTION
90	if (decrypt_input)
91	    c = (*decrypt_input)(c);
92#endif
93	switch (state) {
94
95	case TS_CR:
96	    state = TS_DATA;
97	    /* Strip off \n or \0 after a \r */
98	    if ((c == 0) || (c == '\n')) {
99		break;
100	    }
101	    /* FALL THROUGH */
102
103	case TS_DATA:
104	    if (c == IAC) {
105		state = TS_IAC;
106		break;
107	    }
108	    /*
109	     * We now map \r\n ==> \r for pragmatic reasons.
110	     * Many client implementations send \r\n when
111	     * the user hits the CarriageReturn key.
112	     *
113	     * We USED to map \r\n ==> \n, since \r\n says
114	     * that we want to be in column 1 of the next
115	     * printable line, and \n is the standard
116	     * unix way of saying that (\r is only good
117	     * if CRMOD is set, which it normally is).
118	     */
119	    if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
120		int nc = *netip;
121#ifdef ENCRYPTION
122		if (decrypt_input)
123		    nc = (*decrypt_input)(nc & 0xff);
124#endif
125		{
126#ifdef ENCRYPTION
127		    if (decrypt_input)
128			(void)(*decrypt_input)(-1);
129#endif
130		    state = TS_CR;
131		}
132	    }
133	    *pfrontp++ = c;
134	    break;
135
136	case TS_IAC:
137	gotiac:			switch (c) {
138
139	    /*
140	     * Send the process on the pty side an
141	     * interrupt.  Do this with a NULL or
142	     * interrupt char; depending on the tty mode.
143	     */
144	case IP:
145	    DIAG(TD_OPTIONS,
146		 printoption("td: recv IAC", c));
147	    interrupt();
148	    break;
149
150	case BREAK:
151	    DIAG(TD_OPTIONS,
152		 printoption("td: recv IAC", c));
153	    sendbrk();
154	    break;
155
156	    /*
157	     * Are You There?
158	     */
159	case AYT:
160	    DIAG(TD_OPTIONS,
161		 printoption("td: recv IAC", c));
162	    recv_ayt();
163	    break;
164
165	    /*
166	     * Abort Output
167	     */
168	case AO:
169	    {
170		DIAG(TD_OPTIONS,
171		     printoption("td: recv IAC", c));
172		ptyflush();	/* half-hearted */
173		init_termbuf();
174
175		if (slctab[SLC_AO].sptr &&
176		    *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
177		    *pfrontp++ =
178			(unsigned char)*slctab[SLC_AO].sptr;
179		}
180
181		netclear();	/* clear buffer back */
182		output_data ("%c%c", IAC, DM);
183		neturg = nfrontp-1; /* off by one XXX */
184		DIAG(TD_OPTIONS,
185		     printoption("td: send IAC", DM));
186		break;
187	    }
188
189	/*
190	 * Erase Character and
191	 * Erase Line
192	 */
193	case EC:
194	case EL:
195	    {
196		cc_t ch;
197
198		DIAG(TD_OPTIONS,
199		     printoption("td: recv IAC", c));
200		ptyflush();	/* half-hearted */
201		init_termbuf();
202		if (c == EC)
203		    ch = *slctab[SLC_EC].sptr;
204		else
205		    ch = *slctab[SLC_EL].sptr;
206		if (ch != (cc_t)(_POSIX_VDISABLE))
207		    *pfrontp++ = (unsigned char)ch;
208		break;
209	    }
210
211	/*
212	 * Check for urgent data...
213	 */
214	case DM:
215	    DIAG(TD_OPTIONS,
216		 printoption("td: recv IAC", c));
217	    SYNCHing = stilloob(net);
218	    settimer(gotDM);
219	    break;
220
221
222	    /*
223	     * Begin option subnegotiation...
224	     */
225	case SB:
226	    state = TS_SB;
227	    SB_CLEAR();
228	    continue;
229
230	case WILL:
231	    state = TS_WILL;
232	    continue;
233
234	case WONT:
235	    state = TS_WONT;
236	    continue;
237
238	case DO:
239	    state = TS_DO;
240	    continue;
241
242	case DONT:
243	    state = TS_DONT;
244	    continue;
245	case EOR:
246	    if (his_state_is_will(TELOPT_EOR))
247		doeof();
248	    break;
249
250	    /*
251	     * Handle RFC 10xx Telnet linemode option additions
252	     * to command stream (EOF, SUSP, ABORT).
253	     */
254	case xEOF:
255	    doeof();
256	    break;
257
258	case SUSP:
259	    sendsusp();
260	    break;
261
262	case ABORT:
263	    sendbrk();
264	    break;
265
266	case IAC:
267	    *pfrontp++ = c;
268	    break;
269	}
270	state = TS_DATA;
271	break;
272
273	case TS_SB:
274	    if (c == IAC) {
275		state = TS_SE;
276	    } else {
277		SB_ACCUM(c);
278	    }
279	    break;
280
281	case TS_SE:
282	    if (c != SE) {
283		if (c != IAC) {
284		    /*
285		     * bad form of suboption negotiation.
286		     * handle it in such a way as to avoid
287		     * damage to local state.  Parse
288		     * suboption buffer found so far,
289		     * then treat remaining stream as
290		     * another command sequence.
291		     */
292
293		    /* for DIAGNOSTICS */
294		    SB_ACCUM(IAC);
295		    SB_ACCUM(c);
296		    subpointer -= 2;
297
298		    SB_TERM();
299		    suboption();
300		    state = TS_IAC;
301		    goto gotiac;
302		}
303		SB_ACCUM(c);
304		state = TS_SB;
305	    } else {
306		/* for DIAGNOSTICS */
307		SB_ACCUM(IAC);
308		SB_ACCUM(SE);
309		subpointer -= 2;
310
311		SB_TERM();
312		suboption();	/* handle sub-option */
313		state = TS_DATA;
314	    }
315	    break;
316
317	case TS_WILL:
318	    willoption(c);
319	    state = TS_DATA;
320	    continue;
321
322	case TS_WONT:
323	    wontoption(c);
324	    if (c==TELOPT_ENCRYPT && his_do_dont_is_changing(TELOPT_ENCRYPT) )
325                dontoption(c);
326	    state = TS_DATA;
327	    continue;
328
329	case TS_DO:
330	    dooption(c);
331	    state = TS_DATA;
332	    continue;
333
334	case TS_DONT:
335	    dontoption(c);
336	    state = TS_DATA;
337	    continue;
338
339	default:
340	    syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
341	    printf("telnetd: panic state=%d\n", state);
342	    exit(1);
343	}
344    }
345}  /* end of telrcv */
346
347/*
348 * The will/wont/do/dont state machines are based on Dave Borman's
349 * Telnet option processing state machine.
350 *
351 * These correspond to the following states:
352 *	my_state = the last negotiated state
353 *	want_state = what I want the state to go to
354 *	want_resp = how many requests I have sent
355 * All state defaults are negative, and resp defaults to 0.
356 *
357 * When initiating a request to change state to new_state:
358 *
359 * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
360 *	do nothing;
361 * } else {
362 *	want_state = new_state;
363 *	send new_state;
364 *	want_resp++;
365 * }
366 *
367 * When receiving new_state:
368 *
369 * if (want_resp) {
370 *	want_resp--;
371 *	if (want_resp && (new_state == my_state))
372 *		want_resp--;
373 * }
374 * if ((want_resp == 0) && (new_state != want_state)) {
375 *	if (ok_to_switch_to new_state)
376 *		want_state = new_state;
377 *	else
378 *		want_resp++;
379 *	send want_state;
380 * }
381 * my_state = new_state;
382 *
383 * Note that new_state is implied in these functions by the function itself.
384 * will and do imply positive new_state, wont and dont imply negative.
385 *
386 * Finally, there is one catch.  If we send a negative response to a
387 * positive request, my_state will be the positive while want_state will
388 * remain negative.  my_state will revert to negative when the negative
389 * acknowlegment arrives from the peer.  Thus, my_state generally tells
390 * us not only the last negotiated state, but also tells us what the peer
391 * wants to be doing as well.  It is important to understand this difference
392 * as we may wish to be processing data streams based on our desired state
393 * (want_state) or based on what the peer thinks the state is (my_state).
394 *
395 * This all works fine because if the peer sends a positive request, the data
396 * that we receive prior to negative acknowlegment will probably be affected
397 * by the positive state, and we can process it as such (if we can; if we
398 * can't then it really doesn't matter).  If it is that important, then the
399 * peer probably should be buffering until this option state negotiation
400 * is complete.
401 *
402 */
403void
404send_do(int option, int init)
405{
406    if (init) {
407	if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
408	    his_want_state_is_will(option))
409	    return;
410	/*
411	 * Special case for TELOPT_TM:  We send a DO, but pretend
412	 * that we sent a DONT, so that we can send more DOs if
413	 * we want to.
414	 */
415	if (option == TELOPT_TM)
416	    set_his_want_state_wont(option);
417	else
418	    set_his_want_state_will(option);
419	do_dont_resp[option]++;
420    }
421    output_data((const char *)doopt, option);
422
423    DIAG(TD_OPTIONS, printoption("td: send do", option));
424}
425
426#ifdef	AUTHENTICATION
427extern void auth_request(void);
428#endif
429#ifdef	ENCRYPTION
430extern void encrypt_send_support(void);
431#endif
432
433void
434willoption(int option)
435{
436    int changeok = 0;
437    void (*func)(void) = NULL;
438
439    /*
440     * process input from peer.
441     */
442
443    DIAG(TD_OPTIONS, printoption("td: recv will", option));
444
445    if (do_dont_resp[option]) {
446	do_dont_resp[option]--;
447	if (do_dont_resp[option] && his_state_is_will(option))
448	    do_dont_resp[option]--;
449    }
450    if (do_dont_resp[option] == 0) {
451	if (his_want_state_is_wont(option)) {
452	    switch (option) {
453
454	    case TELOPT_BINARY:
455		init_termbuf();
456		tty_binaryin(1);
457		set_termbuf();
458		changeok++;
459		break;
460
461	    case TELOPT_ECHO:
462		/*
463		 * See comments below for more info.
464		 */
465		not42 = 0;	/* looks like a 4.2 system */
466		break;
467
468	    case TELOPT_TM:
469		/*
470		 * We never respond to a WILL TM, and
471		 * we leave the state WONT.
472		 */
473		return;
474
475	    case TELOPT_LFLOW:
476		/*
477		 * If we are going to support flow control
478		 * option, then don't worry peer that we can't
479		 * change the flow control characters.
480		 */
481		slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
482		slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
483		slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
484		slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
485	    case TELOPT_TTYPE:
486	    case TELOPT_SGA:
487	    case TELOPT_NAWS:
488	    case TELOPT_TSPEED:
489	    case TELOPT_XDISPLOC:
490	    case TELOPT_NEW_ENVIRON:
491	    case TELOPT_OLD_ENVIRON:
492		changeok++;
493		break;
494
495
496#ifdef	AUTHENTICATION
497	    case TELOPT_AUTHENTICATION:
498		func = auth_request;
499		changeok++;
500		break;
501#endif
502
503#ifdef	ENCRYPTION
504	    case TELOPT_ENCRYPT:
505		func = encrypt_send_support;
506		changeok++;
507		break;
508#endif
509
510	    default:
511		break;
512	    }
513	    if (changeok) {
514		set_his_want_state_will(option);
515		send_do(option, 0);
516	    } else {
517		do_dont_resp[option]++;
518		send_dont(option, 0);
519	    }
520	} else {
521	    /*
522	     * Option processing that should happen when
523	     * we receive conformation of a change in
524	     * state that we had requested.
525	     */
526	    switch (option) {
527	    case TELOPT_ECHO:
528		not42 = 0;	/* looks like a 4.2 system */
529		/*
530		 * Egads, he responded "WILL ECHO".  Turn
531		 * it off right now!
532		 */
533		send_dont(option, 1);
534		/*
535		 * "WILL ECHO".  Kludge upon kludge!
536		 * A 4.2 client is now echoing user input at
537		 * the tty.  This is probably undesireable and
538		 * it should be stopped.  The client will
539		 * respond WONT TM to the DO TM that we send to
540		 * check for kludge linemode.  When the WONT TM
541		 * arrives, linemode will be turned off and a
542		 * change propogated to the pty.  This change
543		 * will cause us to process the new pty state
544		 * in localstat(), which will notice that
545		 * linemode is off and send a WILL ECHO
546		 * so that we are properly in character mode and
547		 * all is well.
548		 */
549		break;
550
551#ifdef	AUTHENTICATION
552	    case TELOPT_AUTHENTICATION:
553		func = auth_request;
554		break;
555#endif
556
557#ifdef	ENCRYPTION
558	    case TELOPT_ENCRYPT:
559		func = encrypt_send_support;
560		break;
561#endif
562
563	    case TELOPT_LFLOW:
564		func = flowstat;
565		break;
566	    }
567	}
568    }
569    set_his_state_will(option);
570    if (func)
571	(*func)();
572}  /* end of willoption */
573
574void
575send_dont(int option, int init)
576{
577    if (init) {
578	if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
579	    his_want_state_is_wont(option))
580	    return;
581	set_his_want_state_wont(option);
582	do_dont_resp[option]++;
583    }
584    output_data((const char *)dont, option);
585
586    DIAG(TD_OPTIONS, printoption("td: send dont", option));
587}
588
589void
590wontoption(int option)
591{
592    /*
593     * Process client input.
594	 */
595
596    DIAG(TD_OPTIONS, printoption("td: recv wont", option));
597
598    if (do_dont_resp[option]) {
599	do_dont_resp[option]--;
600	if (do_dont_resp[option] && his_state_is_wont(option))
601	    do_dont_resp[option]--;
602    }
603    if (do_dont_resp[option] == 0) {
604	if (his_want_state_is_will(option)) {
605	    /* it is always ok to change to negative state */
606	    switch (option) {
607	    case TELOPT_ECHO:
608		not42 = 1; /* doesn't seem to be a 4.2 system */
609		break;
610
611	    case TELOPT_BINARY:
612		init_termbuf();
613		tty_binaryin(0);
614		set_termbuf();
615		break;
616
617	    case TELOPT_TM:
618		/*
619		 * If we get a WONT TM, and had sent a DO TM,
620		 * don't respond with a DONT TM, just leave it
621		 * as is.  Short circut the state machine to
622		 * achive this.
623		 */
624		set_his_want_state_wont(TELOPT_TM);
625		return;
626
627	    case TELOPT_LFLOW:
628		/*
629		 * If we are not going to support flow control
630		 * option, then let peer know that we can't
631		 * change the flow control characters.
632		 */
633		slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
634		slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
635		slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
636		slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
637		break;
638
639#ifdef AUTHENTICATION
640	    case TELOPT_AUTHENTICATION:
641		auth_finished(0, AUTH_REJECT);
642		break;
643#endif
644
645		/*
646		 * For options that we might spin waiting for
647		 * sub-negotiation, if the client turns off the
648		 * option rather than responding to the request,
649		 * we have to treat it here as if we got a response
650		 * to the sub-negotiation, (by updating the timers)
651		 * so that we'll break out of the loop.
652		 */
653	    case TELOPT_TTYPE:
654		settimer(ttypesubopt);
655		break;
656
657	    case TELOPT_TSPEED:
658		settimer(tspeedsubopt);
659		break;
660
661	    case TELOPT_XDISPLOC:
662		settimer(xdisplocsubopt);
663		break;
664
665	    case TELOPT_OLD_ENVIRON:
666		settimer(oenvironsubopt);
667		break;
668
669	    case TELOPT_NEW_ENVIRON:
670		settimer(environsubopt);
671		break;
672
673	    default:
674		break;
675	    }
676	    set_his_want_state_wont(option);
677	    if (his_state_is_will(option))
678		send_dont(option, 0);
679	} else {
680	    switch (option) {
681	    case TELOPT_TM:
682		break;
683
684#ifdef AUTHENTICATION
685	    case TELOPT_AUTHENTICATION:
686		auth_finished(0, AUTH_REJECT);
687		break;
688#endif
689	    default:
690		break;
691	    }
692	}
693    }
694    set_his_state_wont(option);
695
696}  /* end of wontoption */
697
698void
699send_will(int option, int init)
700{
701    if (init) {
702	if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
703	    my_want_state_is_will(option))
704	    return;
705	set_my_want_state_will(option);
706	will_wont_resp[option]++;
707    }
708    output_data ((const char *)will, option);
709
710    DIAG(TD_OPTIONS, printoption("td: send will", option));
711}
712
713/*
714 * When we get a DONT SGA, we will try once to turn it
715 * back on.  If the other side responds DONT SGA, we
716 * leave it at that.  This is so that when we talk to
717 * clients that understand KLUDGELINEMODE but not LINEMODE,
718 * we'll keep them in char-at-a-time mode.
719 */
720int turn_on_sga = 0;
721
722void
723dooption(int option)
724{
725    int changeok = 0;
726
727    /*
728     * Process client input.
729     */
730
731    DIAG(TD_OPTIONS, printoption("td: recv do", option));
732
733    if (will_wont_resp[option]) {
734	will_wont_resp[option]--;
735	if (will_wont_resp[option] && my_state_is_will(option))
736	    will_wont_resp[option]--;
737    }
738    if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
739	switch (option) {
740	case TELOPT_ECHO:
741	    {
742		init_termbuf();
743		tty_setecho(1);
744		set_termbuf();
745	    }
746	changeok++;
747	break;
748
749	case TELOPT_BINARY:
750	    init_termbuf();
751	    tty_binaryout(1);
752	    set_termbuf();
753	    changeok++;
754	    break;
755
756	case TELOPT_SGA:
757	    turn_on_sga = 0;
758	    changeok++;
759	    break;
760
761	case TELOPT_STATUS:
762	    changeok++;
763	    break;
764
765	case TELOPT_TM:
766	    /*
767	     * Special case for TM.  We send a WILL, but
768	     * pretend we sent a WONT.
769	     */
770	    send_will(option, 0);
771	    set_my_want_state_wont(option);
772	    set_my_state_wont(option);
773	    return;
774
775	case TELOPT_LOGOUT:
776	    /*
777	     * When we get a LOGOUT option, respond
778	     * with a WILL LOGOUT, make sure that
779	     * it gets written out to the network,
780	     * and then just go away...
781	     */
782	    set_my_want_state_will(TELOPT_LOGOUT);
783	    send_will(TELOPT_LOGOUT, 0);
784	    set_my_state_will(TELOPT_LOGOUT);
785	    netflush();
786	    cleanup(0);
787	    /* NOT REACHED */
788	    break;
789
790#ifdef ENCRYPTION
791	case TELOPT_ENCRYPT:
792	    changeok++;
793	    break;
794#endif
795	case TELOPT_LINEMODE:
796	case TELOPT_TTYPE:
797	case TELOPT_NAWS:
798	case TELOPT_TSPEED:
799	case TELOPT_LFLOW:
800	case TELOPT_XDISPLOC:
801#ifdef	TELOPT_ENVIRON
802	case TELOPT_NEW_ENVIRON:
803#endif
804	case TELOPT_OLD_ENVIRON:
805	default:
806	    break;
807	}
808	if (changeok) {
809	    set_my_want_state_will(option);
810	    send_will(option, 0);
811	} else {
812	    will_wont_resp[option]++;
813	    send_wont(option, 0);
814	}
815    }
816    set_my_state_will(option);
817
818}  /* end of dooption */
819
820void
821send_wont(int option, int init)
822{
823    if (init) {
824	if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
825	    my_want_state_is_wont(option))
826	    return;
827	set_my_want_state_wont(option);
828	will_wont_resp[option]++;
829    }
830    output_data ((const char *)wont, option);
831
832    DIAG(TD_OPTIONS, printoption("td: send wont", option));
833}
834
835void
836dontoption(int option)
837{
838    /*
839     * Process client input.
840	 */
841
842
843    DIAG(TD_OPTIONS, printoption("td: recv dont", option));
844
845    if (will_wont_resp[option]) {
846	will_wont_resp[option]--;
847	if (will_wont_resp[option] && my_state_is_wont(option))
848	    will_wont_resp[option]--;
849    }
850    if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
851	switch (option) {
852	case TELOPT_BINARY:
853	    init_termbuf();
854	    tty_binaryout(0);
855	    set_termbuf();
856	    break;
857
858	case TELOPT_ECHO:	/* we should stop echoing */
859	    {
860		init_termbuf();
861		tty_setecho(0);
862		set_termbuf();
863	    }
864	break;
865
866	case TELOPT_SGA:
867	    set_my_want_state_wont(option);
868	    if (my_state_is_will(option))
869		send_wont(option, 0);
870	    set_my_state_wont(option);
871	    if (turn_on_sga ^= 1)
872		send_will(option, 1);
873	    return;
874
875	default:
876	    break;
877	}
878
879	set_my_want_state_wont(option);
880	if (my_state_is_will(option))
881	    send_wont(option, 0);
882    }
883    set_my_state_wont(option);
884
885}  /* end of dontoption */
886
887#ifdef	ENV_HACK
888int env_ovar = -1;
889int env_ovalue = -1;
890#else	/* ENV_HACK */
891# define env_ovar OLD_ENV_VAR
892# define env_ovalue OLD_ENV_VALUE
893#endif	/* ENV_HACK */
894
895/*
896 * suboption()
897 *
898 *	Look at the sub-option buffer, and try to be helpful to the other
899 * side.
900 *
901 *	Currently we recognize:
902 *
903 *	Terminal type is
904 *	Linemode
905 *	Window size
906 *	Terminal speed
907 */
908void
909suboption(void)
910{
911    int subchar;
912
913    DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
914
915    subchar = SB_GET();
916    switch (subchar) {
917    case TELOPT_TSPEED: {
918	int xspeed, rspeed;
919
920	if (his_state_is_wont(TELOPT_TSPEED))	/* Ignore if option disabled */
921	    break;
922
923	settimer(tspeedsubopt);
924
925	if (SB_EOF() || SB_GET() != TELQUAL_IS)
926	    return;
927
928	xspeed = atoi((char *)subpointer);
929
930	while (SB_GET() != ',' && !SB_EOF());
931	if (SB_EOF())
932	    return;
933
934	rspeed = atoi((char *)subpointer);
935	clientstat(TELOPT_TSPEED, xspeed, rspeed);
936
937	break;
938
939    }  /* end of case TELOPT_TSPEED */
940
941    case TELOPT_TTYPE: {		/* Yaaaay! */
942	char *p;
943
944	if (his_state_is_wont(TELOPT_TTYPE))	/* Ignore if option disabled */
945	    break;
946	settimer(ttypesubopt);
947
948	if (SB_EOF() || SB_GET() != TELQUAL_IS) {
949	    return;		/* ??? XXX but, this is the most robust */
950	}
951
952	p = terminaltype;
953
954	while ((p < (terminaltype + sizeof terminaltype-1)) &&
955	       !SB_EOF()) {
956	    int c;
957
958	    c = SB_GET();
959	    if (isupper(c)) {
960		c = tolower(c);
961	    }
962	    *p++ = c;    /* accumulate name */
963	}
964	*p = 0;
965	break;
966    }  /* end of case TELOPT_TTYPE */
967
968    case TELOPT_NAWS: {
969	int xwinsize, ywinsize;
970
971	if (his_state_is_wont(TELOPT_NAWS))	/* Ignore if option disabled */
972	    break;
973
974	if (SB_EOF())
975	    return;
976	xwinsize = SB_GET() << 8;
977	if (SB_EOF())
978	    return;
979	xwinsize |= SB_GET();
980	if (SB_EOF())
981	    return;
982	ywinsize = SB_GET() << 8;
983	if (SB_EOF())
984	    return;
985	ywinsize |= SB_GET();
986	clientstat(TELOPT_NAWS, xwinsize, ywinsize);
987
988	break;
989
990    }  /* end of case TELOPT_NAWS */
991
992    case TELOPT_STATUS: {
993	int mode;
994
995	if (SB_EOF())
996	    break;
997	mode = SB_GET();
998	switch (mode) {
999	case TELQUAL_SEND:
1000	    if (my_state_is_will(TELOPT_STATUS))
1001		send_status();
1002	    break;
1003
1004	case TELQUAL_IS:
1005	    break;
1006
1007	default:
1008	    break;
1009	}
1010	break;
1011    }  /* end of case TELOPT_STATUS */
1012
1013    case TELOPT_XDISPLOC: {
1014	if (SB_EOF() || SB_GET() != TELQUAL_IS)
1015	    return;
1016	settimer(xdisplocsubopt);
1017	subpointer[SB_LEN()] = '\0';
1018	esetenv("DISPLAY", (char *)subpointer, 1);
1019	break;
1020    }  /* end of case TELOPT_XDISPLOC */
1021
1022#ifdef	TELOPT_NEW_ENVIRON
1023    case TELOPT_NEW_ENVIRON:
1024#endif
1025    case TELOPT_OLD_ENVIRON: {
1026	int c;
1027	char *cp, *varp, *valp;
1028
1029	if (SB_EOF())
1030	    return;
1031	c = SB_GET();
1032	if (c == TELQUAL_IS) {
1033	    if (subchar == TELOPT_OLD_ENVIRON)
1034		settimer(oenvironsubopt);
1035	    else
1036		settimer(environsubopt);
1037	} else if (c != TELQUAL_INFO) {
1038	    return;
1039	}
1040
1041#ifdef	TELOPT_NEW_ENVIRON
1042	if (subchar == TELOPT_NEW_ENVIRON) {
1043	    while (!SB_EOF()) {
1044		c = SB_GET();
1045		if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
1046		    break;
1047	    }
1048	} else
1049#endif
1050	    {
1051#ifdef	ENV_HACK
1052		/*
1053		 * We only want to do this if we haven't already decided
1054		 * whether or not the other side has its VALUE and VAR
1055		 * reversed.
1056		 */
1057		if (env_ovar < 0) {
1058		    int last = -1;		/* invalid value */
1059		    int empty = 0;
1060		    int got_var = 0, got_value = 0, got_uservar = 0;
1061
1062		    /*
1063		     * The other side might have its VALUE and VAR values
1064		     * reversed.  To be interoperable, we need to determine
1065		     * which way it is.  If the first recognized character
1066		     * is a VAR or VALUE, then that will tell us what
1067		     * type of client it is.  If the fist recognized
1068		     * character is a USERVAR, then we continue scanning
1069		     * the suboption looking for two consecutive
1070		     * VAR or VALUE fields.  We should not get two
1071		     * consecutive VALUE fields, so finding two
1072		     * consecutive VALUE or VAR fields will tell us
1073		     * what the client is.
1074		     */
1075		    SB_SAVE();
1076		    while (!SB_EOF()) {
1077			c = SB_GET();
1078			switch(c) {
1079			case OLD_ENV_VAR:
1080			    if (last < 0 || last == OLD_ENV_VAR
1081				|| (empty && (last == OLD_ENV_VALUE)))
1082				goto env_ovar_ok;
1083			    got_var++;
1084			    last = OLD_ENV_VAR;
1085			    break;
1086			case OLD_ENV_VALUE:
1087			    if (last < 0 || last == OLD_ENV_VALUE
1088				|| (empty && (last == OLD_ENV_VAR)))
1089				goto env_ovar_wrong;
1090			    got_value++;
1091			    last = OLD_ENV_VALUE;
1092			    break;
1093			case ENV_USERVAR:
1094			    /* count strings of USERVAR as one */
1095			    if (last != ENV_USERVAR)
1096				got_uservar++;
1097			    if (empty) {
1098				if (last == OLD_ENV_VALUE)
1099				    goto env_ovar_ok;
1100				if (last == OLD_ENV_VAR)
1101				    goto env_ovar_wrong;
1102			    }
1103			    last = ENV_USERVAR;
1104			    break;
1105			case ENV_ESC:
1106			    if (!SB_EOF())
1107				c = SB_GET();
1108			    /* FALL THROUGH */
1109			default:
1110			    empty = 0;
1111			    continue;
1112			}
1113			empty = 1;
1114		    }
1115		    if (empty) {
1116			if (last == OLD_ENV_VALUE)
1117			    goto env_ovar_ok;
1118			if (last == OLD_ENV_VAR)
1119			    goto env_ovar_wrong;
1120		    }
1121		    /*
1122		     * Ok, the first thing was a USERVAR, and there
1123		     * are not two consecutive VAR or VALUE commands,
1124		     * and none of the VAR or VALUE commands are empty.
1125		     * If the client has sent us a well-formed option,
1126		     * then the number of VALUEs received should always
1127		     * be less than or equal to the number of VARs and
1128		     * USERVARs received.
1129		     *
1130		     * If we got exactly as many VALUEs as VARs and
1131		     * USERVARs, the client has the same definitions.
1132		     *
1133		     * If we got exactly as many VARs as VALUEs and
1134		     * USERVARS, the client has reversed definitions.
1135		     */
1136		    if (got_uservar + got_var == got_value) {
1137		    env_ovar_ok:
1138			env_ovar = OLD_ENV_VAR;
1139			env_ovalue = OLD_ENV_VALUE;
1140		    } else if (got_uservar + got_value == got_var) {
1141		    env_ovar_wrong:
1142			env_ovar = OLD_ENV_VALUE;
1143			env_ovalue = OLD_ENV_VAR;
1144			DIAG(TD_OPTIONS, {
1145			    output_data("ENVIRON VALUE and VAR are reversed!\r\n");
1146			});
1147
1148		    }
1149		}
1150		SB_RESTORE();
1151#endif
1152
1153		while (!SB_EOF()) {
1154		    c = SB_GET();
1155		    if ((c == env_ovar) || (c == ENV_USERVAR))
1156			break;
1157		}
1158	    }
1159
1160	if (SB_EOF())
1161	    return;
1162
1163	cp = varp = (char *)subpointer;
1164	valp = 0;
1165
1166	while (!SB_EOF()) {
1167	    c = SB_GET();
1168	    if (subchar == TELOPT_OLD_ENVIRON) {
1169		if (c == env_ovar)
1170		    c = NEW_ENV_VAR;
1171		else if (c == env_ovalue)
1172		    c = NEW_ENV_VALUE;
1173	    }
1174	    switch (c) {
1175
1176	    case NEW_ENV_VALUE:
1177		*cp = '\0';
1178		cp = valp = (char *)subpointer;
1179		break;
1180
1181	    case NEW_ENV_VAR:
1182	    case ENV_USERVAR:
1183		*cp = '\0';
1184		if (valp)
1185		    esetenv(varp, valp, 1);
1186		else
1187		    unsetenv(varp);
1188		cp = varp = (char *)subpointer;
1189		valp = 0;
1190		break;
1191
1192	    case ENV_ESC:
1193		if (SB_EOF())
1194		    break;
1195		c = SB_GET();
1196		/* FALL THROUGH */
1197	    default:
1198		*cp++ = c;
1199		break;
1200	    }
1201	}
1202	*cp = '\0';
1203	if (valp)
1204	    esetenv(varp, valp, 1);
1205	else
1206	    unsetenv(varp);
1207	break;
1208    }  /* end of case TELOPT_NEW_ENVIRON */
1209#ifdef AUTHENTICATION
1210    case TELOPT_AUTHENTICATION:
1211	if (SB_EOF())
1212	    break;
1213	switch(SB_GET()) {
1214	case TELQUAL_SEND:
1215	case TELQUAL_REPLY:
1216	    /*
1217	     * These are sent by us and cannot be sent by
1218	     * the client.
1219	     */
1220	    break;
1221	case TELQUAL_IS:
1222	    auth_is(subpointer, SB_LEN());
1223	    break;
1224	case TELQUAL_NAME:
1225	    auth_name(subpointer, SB_LEN());
1226	    break;
1227	}
1228	break;
1229#endif
1230#ifdef ENCRYPTION
1231    case TELOPT_ENCRYPT:
1232	if (SB_EOF())
1233	    break;
1234	switch(SB_GET()) {
1235	case ENCRYPT_SUPPORT:
1236	    encrypt_support(subpointer, SB_LEN());
1237	    break;
1238	case ENCRYPT_IS:
1239	    encrypt_is(subpointer, SB_LEN());
1240	    break;
1241	case ENCRYPT_REPLY:
1242	    encrypt_reply(subpointer, SB_LEN());
1243	    break;
1244	case ENCRYPT_START:
1245	    encrypt_start(subpointer, SB_LEN());
1246	    break;
1247	case ENCRYPT_END:
1248	    if (require_encryption)
1249		fatal(net, "Output encryption is not possible to turn off");
1250	    encrypt_end();
1251	    break;
1252	case ENCRYPT_REQSTART:
1253	    encrypt_request_start(subpointer, SB_LEN());
1254	    break;
1255	case ENCRYPT_REQEND:
1256	    /*
1257	     * We can always send an REQEND so that we cannot
1258	     * get stuck encrypting.  We should only get this
1259	     * if we have been able to get in the correct mode
1260	     * anyhow.
1261	     */
1262	    if (require_encryption)
1263		fatal(net, "Input encryption is not possible to turn off");
1264	    encrypt_request_end();
1265	    break;
1266	case ENCRYPT_ENC_KEYID:
1267	    encrypt_enc_keyid(subpointer, SB_LEN());
1268	    break;
1269	case ENCRYPT_DEC_KEYID:
1270	    encrypt_dec_keyid(subpointer, SB_LEN());
1271	    break;
1272	default:
1273	    break;
1274	}
1275	break;
1276#endif
1277
1278    default:
1279	break;
1280    }  /* end of switch */
1281
1282}  /* end of suboption */
1283
1284void
1285doclientstat(void)
1286{
1287    clientstat(TELOPT_LINEMODE, WILL, 0);
1288}
1289
1290#undef ADD
1291#define	ADD(c)	 *ncp++ = c
1292#define	ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; }
1293
1294void
1295send_status(void)
1296{
1297    unsigned char statusbuf[256];
1298    unsigned char *ncp;
1299    unsigned char i;
1300
1301    ncp = statusbuf;
1302
1303    netflush();	/* get rid of anything waiting to go out */
1304
1305    ADD(IAC);
1306    ADD(SB);
1307    ADD(TELOPT_STATUS);
1308    ADD(TELQUAL_IS);
1309
1310    /*
1311     * We check the want_state rather than the current state,
1312     * because if we received a DO/WILL for an option that we
1313     * don't support, and the other side didn't send a DONT/WONT
1314     * in response to our WONT/DONT, then the "state" will be
1315     * WILL/DO, and the "want_state" will be WONT/DONT.  We
1316     * need to go by the latter.
1317     */
1318    for (i = 0; i < (unsigned char)NTELOPTS; i++) {
1319	if (my_want_state_is_will(i)) {
1320	    ADD(WILL);
1321	    ADD_DATA(i);
1322	}
1323	if (his_want_state_is_will(i)) {
1324	    ADD(DO);
1325	    ADD_DATA(i);
1326	}
1327    }
1328
1329    if (his_want_state_is_will(TELOPT_LFLOW)) {
1330	ADD(SB);
1331	ADD(TELOPT_LFLOW);
1332	if (flowmode) {
1333	    ADD(LFLOW_ON);
1334	} else {
1335	    ADD(LFLOW_OFF);
1336	}
1337	ADD(SE);
1338
1339	if (restartany >= 0) {
1340	    ADD(SB);
1341	    ADD(TELOPT_LFLOW);
1342	    if (restartany) {
1343		ADD(LFLOW_RESTART_ANY);
1344	    } else {
1345		ADD(LFLOW_RESTART_XON);
1346	    }
1347	    ADD(SE);
1348	}
1349    }
1350
1351
1352    ADD(IAC);
1353    ADD(SE);
1354
1355    writenet(statusbuf, ncp - statusbuf);
1356    netflush();	/* Send it on its way */
1357
1358    DIAG(TD_OPTIONS,
1359	 {printsub('>', statusbuf, ncp - statusbuf); netflush();});
1360}
1361