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 /* based on @(#)state.c 8.1 (Berkeley) 6/4/93 */
35
36 #include <autoconf.h>
37
38 #include "telnetd.h"
39 #if defined(AUTHENTICATION)
40 #include <libtelnet/auth.h>
41 #endif
42 #if defined(ENCRYPTION)
43 #include <libtelnet/encrypt.h>
44 #endif
45
46 unsigned char doopt[] = { IAC, DO, '%', 'c', 0 };
47 unsigned char dont[] = { IAC, DONT, '%', 'c', 0 };
48 unsigned char will[] = { IAC, WILL, '%', 'c', 0 };
49 unsigned char wont[] = { IAC, WONT, '%', 'c', 0 };
50 int not42 = 1;
51
52 static int envvarok (char *);
53
54 /*
55 * Buffer for sub-options, and macros
56 * for suboptions buffer manipulations
57 */
58 unsigned char subbuffer[TELNET_BUFSIZE], *subpointer= subbuffer, *subend= subbuffer;
59
60 #define SB_CLEAR() subpointer = subbuffer
61 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
62 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
63 *subpointer++ = (c); \
64 }
65 #define SB_GET() ((*subpointer++)&0xff)
66 #define SB_EOF() (subpointer >= subend)
67 #define SB_LEN() (subend - subpointer)
68
69 #ifdef ENV_HACK
70 unsigned char *subsave;
71 #define SB_SAVE() subsave = subpointer;
72 #define SB_RESTORE() subpointer = subsave;
73 #endif
74
75
76 /*
77 * State for recv fsm
78 */
79 #define TS_DATA 0 /* base state */
80 #define TS_IAC 1 /* look for double IAC's */
81 #define TS_CR 2 /* CR-LF ->'s CR */
82 #define TS_SB 3 /* throw away begin's... */
83 #define TS_SE 4 /* ...end's (suboption negotiation) */
84 #define TS_WILL 5 /* will option negotiation */
85 #define TS_WONT 6 /* wont " */
86 #define TS_DO 7 /* do " */
87 #define TS_DONT 8 /* dont " */
88
sb_auth_complete()89 static void sb_auth_complete()
90 {
91 if (!auth_negotiated) {
92 static char *error =
93 "An environment option was sent before authentication negotiation completed.\r\nThis may create a security hazard. Connection dropped.\r\n";
94 netputs(error);
95 netflush();
96 exit(1);
97 }
98 }
99
100 void
telrcv()101 telrcv()
102 {
103 register int c;
104 static int state = TS_DATA;
105 #if defined(CRAY2) && defined(UNICOS5)
106 char *opfrontp = pfrontp;
107 #endif
108
109 while (ncc > 0) {
110 if ((&ptyobuf[BUFSIZ] - pfrontp) < 1)
111 break;
112 c = *netip++ & 0377, ncc--;
113 #ifdef ENCRYPTION
114 if (decrypt_input)
115 c = (*decrypt_input)(c);
116 #endif /* ENCRYPTION */
117 switch (state) {
118
119 case TS_CR:
120 state = TS_DATA;
121 /* Strip off \n or \0 after a \r */
122 if ((c == 0) || (c == '\n')) {
123 break;
124 }
125 /* FALL THROUGH */
126
127 case TS_DATA:
128 if (c == IAC) {
129 state = TS_IAC;
130 break;
131 }
132 /*
133 * We now map \r\n ==> \r for pragmatic reasons.
134 * Many client implementations send \r\n when
135 * the user hits the CarriageReturn key.
136 *
137 * We USED to map \r\n ==> \n, since \r\n says
138 * that we want to be in column 1 of the next
139 * printable line, and \n is the standard
140 * unix way of saying that (\r is only good
141 * if CRMOD is set, which it normally is).
142 */
143 if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
144 int nc = *netip;
145 #ifdef ENCRYPTION
146 if (decrypt_input)
147 nc = (*decrypt_input)(nc & 0xff);
148 #endif /* ENCRYPTION */
149 #ifdef LINEMODE
150 /*
151 * If we are operating in linemode,
152 * convert to local end-of-line.
153 */
154 if (linemode && (ncc > 0) && (('\n' == nc) ||
155 ((0 == nc) && tty_iscrnl())) ) {
156 netip++; ncc--;
157 c = '\n';
158 } else
159 #endif
160 {
161 #ifdef ENCRYPTION
162 if (decrypt_input)
163 (void)(*decrypt_input)(-1);
164 #endif /* ENCRYPTION */
165 state = TS_CR;
166 }
167 }
168 *pfrontp++ = c;
169 break;
170
171 case TS_IAC:
172 gotiac: switch (c) {
173
174 /*
175 * Send the process on the pty side an
176 * interrupt. Do this with a NULL or
177 * interrupt char; depending on the tty mode.
178 */
179 case IP:
180 DIAG(TD_OPTIONS,
181 printoption("td: recv IAC", c));
182 interrupt();
183 break;
184
185 case BREAK:
186 DIAG(TD_OPTIONS,
187 printoption("td: recv IAC", c));
188 sendbrk();
189 break;
190
191 /*
192 * Are You There?
193 */
194 case AYT:
195 DIAG(TD_OPTIONS,
196 printoption("td: recv IAC", c));
197 recv_ayt();
198 break;
199
200 /*
201 * Abort Output
202 */
203 case AO:
204 {
205 DIAG(TD_OPTIONS,
206 printoption("td: recv IAC", c));
207 ptyflush(); /* half-hearted */
208 init_termbuf();
209
210 if (slctab[SLC_AO].sptr &&
211 *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
212 *pfrontp++ =
213 (unsigned char)*slctab[SLC_AO].sptr;
214 }
215
216 netclear(); /* clear buffer back */
217 netprintf_urg("%c%c", IAC, DM);
218 DIAG(TD_OPTIONS,
219 printoption("td: send IAC", DM));
220 break;
221 }
222
223 /*
224 * Erase Character and
225 * Erase Line
226 */
227 case EC:
228 case EL:
229 {
230 cc_t ch;
231
232 DIAG(TD_OPTIONS,
233 printoption("td: recv IAC", c));
234 ptyflush(); /* half-hearted */
235 init_termbuf();
236 if (c == EC)
237 ch = *slctab[SLC_EC].sptr;
238 else
239 ch = *slctab[SLC_EL].sptr;
240 if (ch != (cc_t)(_POSIX_VDISABLE))
241 *pfrontp++ = (unsigned char)ch;
242 break;
243 }
244
245 /*
246 * Check for urgent data...
247 */
248 case DM:
249 DIAG(TD_OPTIONS,
250 printoption("td: recv IAC", c));
251 SYNCHing = stilloob(net);
252 settimer(gotDM);
253 break;
254
255
256 /*
257 * Begin option subnegotiation...
258 */
259 case SB:
260 state = TS_SB;
261 SB_CLEAR();
262 continue;
263
264 case WILL:
265 state = TS_WILL;
266 continue;
267
268 case WONT:
269 state = TS_WONT;
270 continue;
271
272 case DO:
273 state = TS_DO;
274 continue;
275
276 case DONT:
277 state = TS_DONT;
278 continue;
279 case EOR:
280 if (his_state_is_will(TELOPT_EOR))
281 doeof();
282 break;
283
284 /*
285 * Handle RFC 10xx Telnet linemode option additions
286 * to command stream (EOF, SUSP, ABORT).
287 */
288 case xEOF:
289 doeof();
290 break;
291
292 case SUSP:
293 sendsusp();
294 break;
295
296 case ABORT:
297 sendbrk();
298 break;
299
300 case IAC:
301 *pfrontp++ = c;
302 break;
303 }
304 state = TS_DATA;
305 break;
306
307 case TS_SB:
308 if (c == IAC) {
309 state = TS_SE;
310 } else {
311 SB_ACCUM(c);
312 }
313 break;
314
315 case TS_SE:
316 if (c != SE) {
317 if (c != IAC) {
318 /*
319 * bad form of suboption negotiation.
320 * handle it in such a way as to avoid
321 * damage to local state. Parse
322 * suboption buffer found so far,
323 * then treat remaining stream as
324 * another command sequence.
325 */
326
327 /* for DIAGNOSTICS */
328 SB_ACCUM(IAC);
329 SB_ACCUM(c);
330 subpointer -= 2;
331
332 SB_TERM();
333 suboption();
334 state = TS_IAC;
335 goto gotiac;
336 }
337 SB_ACCUM(c);
338 state = TS_SB;
339 } else {
340 /* for DIAGNOSTICS */
341 SB_ACCUM(IAC);
342 SB_ACCUM(SE);
343 subpointer -= 2;
344
345 SB_TERM();
346 suboption(); /* handle sub-option */
347 state = TS_DATA;
348 }
349 break;
350
351 case TS_WILL:
352 willoption(c);
353 state = TS_DATA;
354 continue;
355
356 case TS_WONT:
357 wontoption(c);
358 state = TS_DATA;
359 continue;
360
361 case TS_DO:
362 dooption(c);
363 state = TS_DATA;
364 continue;
365
366 case TS_DONT:
367 dontoption(c);
368 state = TS_DATA;
369 continue;
370
371 default:
372 syslog(LOG_ERR, "telnetd: panic state=%d", state);
373 printf("telnetd: panic state=%d\n", state);
374 exit(1);
375 }
376 }
377 #if defined(CRAY2) && defined(UNICOS5)
378 if (!linemode) {
379 char xptyobuf[BUFSIZ+NETSLOP];
380 char xbuf2[BUFSIZ];
381 register char *cp;
382 int n = pfrontp - opfrontp, oc;
383 memcpy(xptyobuf, opfrontp, n);
384 pfrontp = opfrontp;
385 pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
386 xbuf2, &oc, BUFSIZ);
387 for (cp = xbuf2; oc > 0; --oc) {
388 if (*cp == IAC)
389 netprintf("%c%c", *cp++, IAC);
390 else
391 netprintf("%c", *cp++);
392 }
393 }
394 #endif /* defined(CRAY2) && defined(UNICOS5) */
395 } /* end of telrcv */
396
397 /*
398 * The will/wont/do/dont state machines are based on Dave Borman's
399 * Telnet option processing state machine.
400 *
401 * These correspond to the following states:
402 * my_state = the last negotiated state
403 * want_state = what I want the state to go to
404 * want_resp = how many requests I have sent
405 * All state defaults are negative, and resp defaults to 0.
406 *
407 * When initiating a request to change state to new_state:
408 *
409 * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
410 * do nothing;
411 * } else {
412 * want_state = new_state;
413 * send new_state;
414 * want_resp++;
415 * }
416 *
417 * When receiving new_state:
418 *
419 * if (want_resp) {
420 * want_resp--;
421 * if (want_resp && (new_state == my_state))
422 * want_resp--;
423 * }
424 * if ((want_resp == 0) && (new_state != want_state)) {
425 * if (ok_to_switch_to new_state)
426 * want_state = new_state;
427 * else
428 * want_resp++;
429 * send want_state;
430 * }
431 * my_state = new_state;
432 *
433 * Note that new_state is implied in these functions by the function itself.
434 * will and do imply positive new_state, wont and dont imply negative.
435 *
436 * Finally, there is one catch. If we send a negative response to a
437 * positive request, my_state will be the positive while want_state will
438 * remain negative. my_state will revert to negative when the negative
439 * acknowlegment arrives from the peer. Thus, my_state generally tells
440 * us not only the last negotiated state, but also tells us what the peer
441 * wants to be doing as well. It is important to understand this difference
442 * as we may wish to be processing data streams based on our desired state
443 * (want_state) or based on what the peer thinks the state is (my_state).
444 *
445 * This all works fine because if the peer sends a positive request, the data
446 * that we receive prior to negative acknowlegment will probably be affected
447 * by the positive state, and we can process it as such (if we can; if we
448 * can't then it really doesn't matter). If it is that important, then the
449 * peer probably should be buffering until this option state negotiation
450 * is complete.
451 *
452 */
453 void
send_do(option,init)454 send_do(option, init)
455 int option, init;
456 {
457 if (init) {
458 if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
459 his_want_state_is_will(option))
460 return;
461 /*
462 * Special case for TELOPT_TM: We send a DO, but pretend
463 * that we sent a DONT, so that we can send more DOs if
464 * we want to.
465 */
466 if (option == TELOPT_TM)
467 set_his_want_state_wont(option);
468 else
469 set_his_want_state_will(option);
470 do_dont_resp[option]++;
471 }
472 netprintf((char *)doopt, option);
473
474 DIAG(TD_OPTIONS, printoption("td: send do", option));
475 }
476
477 #ifdef AUTHENTICATION
478 extern void auth_request();
479 #endif
480 #ifdef LINEMODE
481 static void doclientstat(void);
482 #endif
483 #ifdef ENCRYPTION
484 extern void encrypt_send_support();
485 #endif /* ENCRYPTION */
486
487 void
willoption(option)488 willoption(option)
489 int option;
490 {
491 int changeok = 0;
492 void (*func)() = 0;
493
494 /*
495 * process input from peer.
496 */
497
498 DIAG(TD_OPTIONS, printoption("td: recv will", option));
499
500 if (do_dont_resp[option]) {
501 do_dont_resp[option]--;
502 if (do_dont_resp[option] && his_state_is_will(option))
503 do_dont_resp[option]--;
504 }
505 if (do_dont_resp[option] == 0) {
506 if (his_want_state_is_wont(option)) {
507 switch (option) {
508
509 case TELOPT_BINARY:
510 init_termbuf();
511 tty_binaryin(1);
512 set_termbuf();
513 changeok++;
514 break;
515
516 case TELOPT_ECHO:
517 /*
518 * See comments below for more info.
519 */
520 not42 = 0; /* looks like a 4.2 system */
521 break;
522
523 case TELOPT_TM:
524 #if defined(LINEMODE) && defined(KLUDGELINEMODE)
525 /*
526 * This telnetd implementation does not really
527 * support timing marks, it just uses them to
528 * support the kludge linemode stuff. If we
529 * receive a will or wont TM in response to our
530 * do TM request that may have been sent to
531 * determine kludge linemode support, process
532 * it, otherwise TM should get a negative
533 * response back.
534 */
535 /*
536 * Handle the linemode kludge stuff.
537 * If we are not currently supporting any
538 * linemode at all, then we assume that this
539 * is the client telling us to use kludge
540 * linemode in response to our query. Set the
541 * linemode type that is to be supported, note
542 * that the client wishes to use linemode, and
543 * eat the will TM as though it never arrived.
544 */
545 if (lmodetype < KLUDGE_LINEMODE) {
546 lmodetype = KLUDGE_LINEMODE;
547 clientstat(TELOPT_LINEMODE, WILL, 0);
548 send_wont(TELOPT_SGA, 1);
549 } else if (lmodetype == NO_AUTOKLUDGE) {
550 lmodetype = KLUDGE_OK;
551 }
552 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
553 /*
554 * We never respond to a WILL TM, and
555 * we leave the state WONT.
556 */
557 return;
558
559 case TELOPT_LFLOW:
560 /*
561 * If we are going to support flow control
562 * option, then don't worry peer that we can't
563 * change the flow control characters.
564 */
565 slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
566 slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
567 slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
568 slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
569 case TELOPT_TTYPE:
570 case TELOPT_SGA:
571 case TELOPT_NAWS:
572 case TELOPT_TSPEED:
573 case TELOPT_XDISPLOC:
574 case TELOPT_NEW_ENVIRON:
575 case TELOPT_OLD_ENVIRON:
576 changeok++;
577 break;
578
579 #ifdef LINEMODE
580 case TELOPT_LINEMODE:
581 # ifdef KLUDGELINEMODE
582 /*
583 * Note client's desire to use linemode.
584 */
585 lmodetype = REAL_LINEMODE;
586 # endif /* KLUDGELINEMODE */
587 func = doclientstat;
588 changeok++;
589 break;
590 #endif /* LINEMODE */
591
592 #ifdef AUTHENTICATION
593 case TELOPT_AUTHENTICATION:
594 func = auth_request;
595 changeok++;
596 break;
597 #endif
598
599 #ifdef ENCRYPTION
600 case TELOPT_ENCRYPT:
601 func = encrypt_send_support;
602 changeok++;
603 break;
604 #endif /* ENCRYPTION */
605
606 default:
607 break;
608 }
609 if (changeok) {
610 set_his_want_state_will(option);
611 send_do(option, 0);
612 } else {
613 do_dont_resp[option]++;
614 send_dont(option, 0);
615 }
616 } else {
617 /*
618 * Option processing that should happen when
619 * we receive conformation of a change in
620 * state that we had requested.
621 */
622 switch (option) {
623 case TELOPT_ECHO:
624 not42 = 0; /* looks like a 4.2 system */
625 /*
626 * Egads, he responded "WILL ECHO". Turn
627 * it off right now!
628 */
629 send_dont(option, 1);
630 /*
631 * "WILL ECHO". Kludge upon kludge!
632 * A 4.2 client is now echoing user input at
633 * the tty. This is probably undesireable and
634 * it should be stopped. The client will
635 * respond WONT TM to the DO TM that we send to
636 * check for kludge linemode. When the WONT TM
637 * arrives, linemode will be turned off and a
638 * change propogated to the pty. This change
639 * will cause us to process the new pty state
640 * in localstat(), which will notice that
641 * linemode is off and send a WILL ECHO
642 * so that we are properly in character mode and
643 * all is well.
644 */
645 break;
646 #ifdef LINEMODE
647 case TELOPT_LINEMODE:
648 # ifdef KLUDGELINEMODE
649 /*
650 * Note client's desire to use linemode.
651 */
652 lmodetype = REAL_LINEMODE;
653 # endif /* KLUDGELINEMODE */
654 func = doclientstat;
655 break;
656 #endif /* LINEMODE */
657
658 #ifdef AUTHENTICATION
659 case TELOPT_AUTHENTICATION:
660 func = auth_request;
661 break;
662 #endif
663
664 #ifdef ENCRYPTION
665 case TELOPT_ENCRYPT:
666 func = encrypt_send_support;
667 break;
668 #endif /* ENCRYPTION */
669 case TELOPT_LFLOW:
670 func = flowstat;
671 break;
672 }
673 }
674 }
675 set_his_state_will(option);
676 if (func)
677 (*func)();
678 } /* end of willoption */
679
680 void
send_dont(option,init)681 send_dont(option, init)
682 int option, init;
683 {
684 if (init) {
685 if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) ||
686 his_want_state_is_wont(option))
687 return;
688 set_his_want_state_wont(option);
689 do_dont_resp[option]++;
690 }
691 netprintf((char *)dont, option);
692
693 DIAG(TD_OPTIONS, printoption("td: send dont", option));
694 }
695
696 void
wontoption(option)697 wontoption(option)
698 int option;
699 {
700 /*
701 * Process client input.
702 */
703
704 DIAG(TD_OPTIONS, printoption("td: recv wont", option));
705
706 if (do_dont_resp[option]) {
707 do_dont_resp[option]--;
708 if (do_dont_resp[option] && his_state_is_wont(option))
709 do_dont_resp[option]--;
710 }
711 if (do_dont_resp[option] == 0) {
712 if (his_want_state_is_will(option)) {
713 /* it is always ok to change to negative state */
714 switch (option) {
715 case TELOPT_ECHO:
716 not42 = 1; /* doesn't seem to be a 4.2 system */
717 break;
718
719 case TELOPT_BINARY:
720 init_termbuf();
721 tty_binaryin(0);
722 set_termbuf();
723 break;
724
725 #ifdef LINEMODE
726 case TELOPT_LINEMODE:
727 # ifdef KLUDGELINEMODE
728 /*
729 * If real linemode is supported, then client is
730 * asking to turn linemode off.
731 */
732 if (lmodetype != REAL_LINEMODE)
733 break;
734 lmodetype = KLUDGE_LINEMODE;
735 # endif /* KLUDGELINEMODE */
736 clientstat(TELOPT_LINEMODE, WONT, 0);
737 break;
738 #endif /* LINEMODE */
739
740 case TELOPT_TM:
741 /*
742 * If we get a WONT TM, and had sent a DO TM,
743 * don't respond with a DONT TM, just leave it
744 * as is. Short circut the state machine to
745 * achive this.
746 */
747 set_his_want_state_wont(TELOPT_TM);
748 return;
749
750 case TELOPT_LFLOW:
751 /*
752 * If we are not going to support flow control
753 * option, then let peer know that we can't
754 * change the flow control characters.
755 */
756 slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
757 slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
758 slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
759 slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
760 break;
761
762 #if defined(AUTHENTICATION)
763 case TELOPT_AUTHENTICATION:
764 auth_finished(0, AUTH_REJECT);
765 break;
766 #endif
767
768 /*
769 * For options that we might spin waiting for
770 * sub-negotiation, if the client turns off the
771 * option rather than responding to the request,
772 * we have to treat it here as if we got a response
773 * to the sub-negotiation, (by updating the timers)
774 * so that we'll break out of the loop.
775 */
776 case TELOPT_TTYPE:
777 settimer(ttypesubopt);
778 break;
779
780 case TELOPT_TSPEED:
781 settimer(tspeedsubopt);
782 break;
783
784 case TELOPT_XDISPLOC:
785 settimer(xdisplocsubopt);
786 break;
787
788 case TELOPT_OLD_ENVIRON:
789 settimer(oenvironsubopt);
790 break;
791
792 case TELOPT_NEW_ENVIRON:
793 settimer(environsubopt);
794 break;
795
796 default:
797 break;
798 }
799 set_his_want_state_wont(option);
800 if (his_state_is_will(option))
801 send_dont(option, 0);
802 } else {
803 switch (option) {
804 case TELOPT_TM:
805 #if defined(LINEMODE) && defined(KLUDGELINEMODE)
806 if (lmodetype < NO_AUTOKLUDGE) {
807 lmodetype = NO_LINEMODE;
808 clientstat(TELOPT_LINEMODE, WONT, 0);
809 send_will(TELOPT_SGA, 1);
810 send_will(TELOPT_ECHO, 1);
811 }
812 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
813 break;
814
815 #if defined(AUTHENTICATION)
816 case TELOPT_AUTHENTICATION:
817 auth_finished(0, AUTH_REJECT);
818 break;
819 #endif
820 default:
821 break;
822 }
823 }
824 }
825 set_his_state_wont(option);
826
827 } /* end of wontoption */
828
829 void
send_will(option,init)830 send_will(option, init)
831 int option, init;
832 {
833 if (init) {
834 if ((will_wont_resp[option] == 0 && my_state_is_will(option))||
835 my_want_state_is_will(option))
836 return;
837 set_my_want_state_will(option);
838 will_wont_resp[option]++;
839 }
840 netprintf((char *)will, option);
841
842 DIAG(TD_OPTIONS, printoption("td: send will", option));
843 }
844
845 #if !defined(LINEMODE) || !defined(KLUDGELINEMODE)
846 /*
847 * When we get a DONT SGA, we will try once to turn it
848 * back on. If the other side responds DONT SGA, we
849 * leave it at that. This is so that when we talk to
850 * clients that understand KLUDGELINEMODE but not LINEMODE,
851 * we'll keep them in char-at-a-time mode.
852 */
853 int turn_on_sga = 0;
854 #endif
855
856 void
dooption(option)857 dooption(option)
858 int option;
859 {
860 int changeok = 0;
861
862 /*
863 * Process client input.
864 */
865
866 DIAG(TD_OPTIONS, printoption("td: recv do", option));
867
868 if (will_wont_resp[option]) {
869 will_wont_resp[option]--;
870 if (will_wont_resp[option] && my_state_is_will(option))
871 will_wont_resp[option]--;
872 }
873 if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
874 switch (option) {
875 case TELOPT_ECHO:
876 #ifdef LINEMODE
877 # ifdef KLUDGELINEMODE
878 if (lmodetype == NO_LINEMODE)
879 # else
880 if (his_state_is_wont(TELOPT_LINEMODE))
881 # endif
882 #endif
883 {
884 init_termbuf();
885 tty_setecho(1);
886 set_termbuf();
887 }
888 changeok++;
889 break;
890
891 case TELOPT_BINARY:
892 init_termbuf();
893 tty_binaryout(1);
894 set_termbuf();
895 changeok++;
896 break;
897
898 case TELOPT_SGA:
899 #if defined(LINEMODE) && defined(KLUDGELINEMODE)
900 /*
901 * If kludge linemode is in use, then we must
902 * process an incoming do SGA for linemode
903 * purposes.
904 */
905 if (lmodetype == KLUDGE_LINEMODE) {
906 /*
907 * Receipt of "do SGA" in kludge
908 * linemode is the peer asking us to
909 * turn off linemode. Make note of
910 * the request.
911 */
912 clientstat(TELOPT_LINEMODE, WONT, 0);
913 /*
914 * If linemode did not get turned off
915 * then don't tell peer that we did.
916 * Breaking here forces a wont SGA to
917 * be returned.
918 */
919 if (linemode)
920 break;
921 }
922 #else
923 turn_on_sga = 0;
924 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
925 changeok++;
926 break;
927
928 case TELOPT_STATUS:
929 changeok++;
930 break;
931
932 case TELOPT_TM:
933 /*
934 * Special case for TM. We send a WILL, but
935 * pretend we sent a WONT.
936 */
937 send_will(option, 0);
938 set_my_want_state_wont(option);
939 set_my_state_wont(option);
940 return;
941
942 case TELOPT_LOGOUT:
943 /*
944 * When we get a LOGOUT option, respond
945 * with a WILL LOGOUT, make sure that
946 * it gets written out to the network,
947 * and then just go away...
948 */
949 set_my_want_state_will(TELOPT_LOGOUT);
950 send_will(TELOPT_LOGOUT, 0);
951 set_my_state_will(TELOPT_LOGOUT);
952 (void)netflush();
953 (void)signal(SIGCHLD, SIG_DFL);
954 cleanup(0);
955 /* NOT REACHED */
956 break;
957
958 #ifdef ENCRYPTION
959 case TELOPT_ENCRYPT:
960 changeok++;
961 break;
962 #endif /* ENCRYPTION */
963 case TELOPT_LINEMODE:
964 case TELOPT_TTYPE:
965 case TELOPT_NAWS:
966 case TELOPT_TSPEED:
967 case TELOPT_LFLOW:
968 case TELOPT_XDISPLOC:
969 #ifdef TELOPT_ENVIRON
970 case TELOPT_NEW_ENVIRON:
971 #endif
972 case TELOPT_OLD_ENVIRON:
973 default:
974 break;
975 }
976 if (changeok) {
977 set_my_want_state_will(option);
978 send_will(option, 0);
979 } else {
980 will_wont_resp[option]++;
981 send_wont(option, 0);
982 }
983 }
984 set_my_state_will(option);
985
986 } /* end of dooption */
987
988 void
send_wont(option,init)989 send_wont(option, init)
990 int option, init;
991 {
992 if (init) {
993 if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) ||
994 my_want_state_is_wont(option))
995 return;
996 set_my_want_state_wont(option);
997 will_wont_resp[option]++;
998 }
999 netprintf((char *)wont, option);
1000
1001 DIAG(TD_OPTIONS, printoption("td: send wont", option));
1002 }
1003
1004 void
dontoption(option)1005 dontoption(option)
1006 int option;
1007 {
1008 /*
1009 * Process client input.
1010 */
1011
1012
1013 DIAG(TD_OPTIONS, printoption("td: recv dont", option));
1014
1015 if (will_wont_resp[option]) {
1016 will_wont_resp[option]--;
1017 if (will_wont_resp[option] && my_state_is_wont(option))
1018 will_wont_resp[option]--;
1019 }
1020 if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
1021 switch (option) {
1022 case TELOPT_BINARY:
1023 init_termbuf();
1024 tty_binaryout(0);
1025 set_termbuf();
1026 break;
1027
1028 case TELOPT_ECHO: /* we should stop echoing */
1029 #ifdef LINEMODE
1030 # ifdef KLUDGELINEMODE
1031 if ((lmodetype != REAL_LINEMODE) &&
1032 (lmodetype != KLUDGE_LINEMODE))
1033 # else
1034 if (his_state_is_wont(TELOPT_LINEMODE))
1035 # endif
1036 #endif
1037 {
1038 init_termbuf();
1039 tty_setecho(0);
1040 set_termbuf();
1041 }
1042 break;
1043
1044 case TELOPT_SGA:
1045 #if defined(LINEMODE) && defined(KLUDGELINEMODE)
1046 /*
1047 * If kludge linemode is in use, then we
1048 * must process an incoming do SGA for
1049 * linemode purposes.
1050 */
1051 if ((lmodetype == KLUDGE_LINEMODE) ||
1052 (lmodetype == KLUDGE_OK)) {
1053 /*
1054 * The client is asking us to turn
1055 * linemode on.
1056 */
1057 lmodetype = KLUDGE_LINEMODE;
1058 clientstat(TELOPT_LINEMODE, WILL, 0);
1059 /*
1060 * If we did not turn line mode on,
1061 * then what do we say? Will SGA?
1062 * This violates design of telnet.
1063 * Gross. Very Gross.
1064 */
1065 }
1066 break;
1067 #else
1068 set_my_want_state_wont(option);
1069 if (my_state_is_will(option))
1070 send_wont(option, 0);
1071 set_my_state_wont(option);
1072 if (turn_on_sga ^= 1)
1073 send_will(option, 1);
1074 return;
1075 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
1076
1077 default:
1078 break;
1079 }
1080
1081 set_my_want_state_wont(option);
1082 if (my_state_is_will(option))
1083 send_wont(option, 0);
1084 }
1085 set_my_state_wont(option);
1086
1087 } /* end of dontoption */
1088
1089 #ifdef ENV_HACK
1090 int env_ovar = -1;
1091 int env_ovalue = -1;
1092 #else /* ENV_HACK */
1093 # define env_ovar OLD_ENV_VAR
1094 # define env_ovalue OLD_ENV_VALUE
1095 #endif /* ENV_HACK */
1096
1097 /*
1098 * suboption()
1099 *
1100 * Look at the sub-option buffer, and try to be helpful to the other
1101 * side.
1102 *
1103 * Currently we recognize:
1104 *
1105 * Terminal type is
1106 * Linemode
1107 * Window size
1108 * Terminal speed
1109 */
1110 void
suboption()1111 suboption()
1112 {
1113 register int subchar;
1114
1115 DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
1116
1117 subchar = SB_GET();
1118 switch (subchar) {
1119 case TELOPT_TSPEED: {
1120 register int xspeed, rspeed;
1121
1122 if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */
1123 break;
1124
1125 sb_auth_complete();
1126
1127 settimer(tspeedsubopt);
1128
1129 if (SB_EOF() || SB_GET() != TELQUAL_IS)
1130 return;
1131
1132 xspeed = atoi((char *)subpointer);
1133
1134 while (SB_GET() != ',' && !SB_EOF());
1135 if (SB_EOF())
1136 return;
1137
1138 rspeed = atoi((char *)subpointer);
1139 clientstat(TELOPT_TSPEED, xspeed, rspeed);
1140
1141 break;
1142
1143 } /* end of case TELOPT_TSPEED */
1144
1145 case TELOPT_TTYPE: { /* Yaaaay! */
1146 char *tt;
1147
1148 if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */
1149 break;
1150 sb_auth_complete();
1151 settimer(ttypesubopt);
1152
1153 if (SB_EOF() || SB_GET() != TELQUAL_IS) {
1154 return; /* ??? XXX but, this is the most robust */
1155 }
1156
1157 tt = terminaltype;
1158
1159 while ((tt < (terminaltype + sizeof(terminaltype) - 1)) && !SB_EOF()) {
1160 register int c;
1161
1162 c = SB_GET();
1163 if (isupper(c)) {
1164 c = tolower(c);
1165 }
1166 *tt++ = c; /* accumulate name */
1167 }
1168 *tt = 0;
1169 break;
1170 } /* end of case TELOPT_TTYPE */
1171
1172 case TELOPT_NAWS: {
1173 register int xwinsize, ywinsize;
1174
1175 if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */
1176 break;
1177
1178 if (SB_EOF())
1179 return;
1180 xwinsize = SB_GET() << 8;
1181 if (SB_EOF())
1182 return;
1183 xwinsize |= SB_GET();
1184 if (SB_EOF())
1185 return;
1186 ywinsize = SB_GET() << 8;
1187 if (SB_EOF())
1188 return;
1189 ywinsize |= SB_GET();
1190 clientstat(TELOPT_NAWS, xwinsize, ywinsize);
1191
1192 break;
1193
1194 } /* end of case TELOPT_NAWS */
1195
1196 #ifdef LINEMODE
1197 case TELOPT_LINEMODE: {
1198 register int request;
1199
1200 if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */
1201 break;
1202 /*
1203 * Process linemode suboptions.
1204 */
1205 if (SB_EOF())
1206 break; /* garbage was sent */
1207 request = SB_GET(); /* get will/wont */
1208
1209 if (SB_EOF())
1210 break; /* another garbage check */
1211
1212 if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */
1213 /*
1214 * Process suboption buffer of slc's
1215 */
1216 start_slc(1);
1217 do_opt_slc(subpointer, subend - subpointer);
1218 (void) end_slc(0);
1219 break;
1220 } else if (request == LM_MODE) {
1221 if (SB_EOF())
1222 return;
1223 useeditmode = SB_GET(); /* get mode flag */
1224 clientstat(LM_MODE, 0, 0);
1225 break;
1226 }
1227
1228 if (SB_EOF())
1229 break;
1230 switch (SB_GET()) { /* what suboption? */
1231 case LM_FORWARDMASK:
1232 /*
1233 * According to spec, only server can send request for
1234 * forwardmask, and client can only return a positive response.
1235 * So don't worry about it.
1236 */
1237
1238 default:
1239 break;
1240 }
1241 break;
1242 } /* end of case TELOPT_LINEMODE */
1243 #endif
1244 case TELOPT_STATUS: {
1245 int mode;
1246
1247 if (SB_EOF())
1248 break;
1249 mode = SB_GET();
1250 switch (mode) {
1251 case TELQUAL_SEND:
1252 if (my_state_is_will(TELOPT_STATUS))
1253 send_status();
1254 break;
1255
1256 case TELQUAL_IS:
1257 break;
1258
1259 default:
1260 break;
1261 }
1262 break;
1263 } /* end of case TELOPT_STATUS */
1264
1265 case TELOPT_XDISPLOC: {
1266 if (SB_EOF() || SB_GET() != TELQUAL_IS)
1267 return;
1268 sb_auth_complete();
1269 settimer(xdisplocsubopt);
1270 subpointer[SB_LEN()] = '\0';
1271 (void)setenv("DISPLAY", (char *)subpointer, 1);
1272 break;
1273 } /* end of case TELOPT_XDISPLOC */
1274
1275 #ifdef TELOPT_NEW_ENVIRON
1276 case TELOPT_NEW_ENVIRON:
1277 #endif
1278 case TELOPT_OLD_ENVIRON: {
1279 register int c;
1280 register char *cp, *varp, *valp;
1281
1282 if (SB_EOF())
1283 return;
1284 sb_auth_complete();
1285 c = SB_GET();
1286 if (c == TELQUAL_IS) {
1287 if (subchar == TELOPT_OLD_ENVIRON)
1288 settimer(oenvironsubopt);
1289 else
1290 settimer(environsubopt);
1291 } else if (c != TELQUAL_INFO) {
1292 return;
1293 }
1294
1295 #ifdef TELOPT_NEW_ENVIRON
1296 if (subchar == TELOPT_NEW_ENVIRON) {
1297 while (!SB_EOF()) {
1298 c = SB_GET();
1299 if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
1300 break;
1301 }
1302 } else
1303 #endif
1304 {
1305 #ifdef ENV_HACK
1306 /*
1307 * We only want to do this if we haven't already decided
1308 * whether or not the other side has its VALUE and VAR
1309 * reversed.
1310 */
1311 if (env_ovar < 0) {
1312 register int last = -1; /* invalid value */
1313 int empty = 0;
1314 int got_var = 0, got_value = 0, got_uservar = 0;
1315
1316 /*
1317 * The other side might have its VALUE and VAR values
1318 * reversed. To be interoperable, we need to determine
1319 * which way it is. If the first recognized character
1320 * is a VAR or VALUE, then that will tell us what
1321 * type of client it is. If the fist recognized
1322 * character is a USERVAR, then we continue scanning
1323 * the suboption looking for two consecutive
1324 * VAR or VALUE fields. We should not get two
1325 * consecutive VALUE fields, so finding two
1326 * consecutive VALUE or VAR fields will tell us
1327 * what the client is.
1328 */
1329 SB_SAVE();
1330 while (!SB_EOF()) {
1331 c = SB_GET();
1332 switch(c) {
1333 case OLD_ENV_VAR:
1334 if (last < 0 || last == OLD_ENV_VAR
1335 || (empty && (last == OLD_ENV_VALUE)))
1336 goto env_ovar_ok;
1337 got_var++;
1338 last = OLD_ENV_VAR;
1339 break;
1340 case OLD_ENV_VALUE:
1341 if (last < 0 || last == OLD_ENV_VALUE
1342 || (empty && (last == OLD_ENV_VAR)))
1343 goto env_ovar_wrong;
1344 got_value++;
1345 last = OLD_ENV_VALUE;
1346 break;
1347 case ENV_USERVAR:
1348 /* count strings of USERVAR as one */
1349 if (last != ENV_USERVAR)
1350 got_uservar++;
1351 if (empty) {
1352 if (last == OLD_ENV_VALUE)
1353 goto env_ovar_ok;
1354 if (last == OLD_ENV_VAR)
1355 goto env_ovar_wrong;
1356 }
1357 last = ENV_USERVAR;
1358 break;
1359 case ENV_ESC:
1360 if (!SB_EOF())
1361 c = SB_GET();
1362 /* FALL THROUGH */
1363 default:
1364 empty = 0;
1365 continue;
1366 }
1367 empty = 1;
1368 }
1369 if (empty) {
1370 if (last == OLD_ENV_VALUE)
1371 goto env_ovar_ok;
1372 if (last == OLD_ENV_VAR)
1373 goto env_ovar_wrong;
1374 }
1375 /*
1376 * Ok, the first thing was a USERVAR, and there
1377 * are not two consecutive VAR or VALUE commands,
1378 * and none of the VAR or VALUE commands are empty.
1379 * If the client has sent us a well-formed option,
1380 * then the number of VALUEs received should always
1381 * be less than or equal to the number of VARs and
1382 * USERVARs received.
1383 *
1384 * If we got exactly as many VALUEs as VARs and
1385 * USERVARs, the client has the same definitions.
1386 *
1387 * If we got exactly as many VARs as VALUEs and
1388 * USERVARS, the client has reversed definitions.
1389 */
1390 if (got_uservar + got_var == got_value) {
1391 env_ovar_ok:
1392 env_ovar = OLD_ENV_VAR;
1393 env_ovalue = OLD_ENV_VALUE;
1394 } else if (got_uservar + got_value == got_var) {
1395 env_ovar_wrong:
1396 env_ovar = OLD_ENV_VALUE;
1397 env_ovalue = OLD_ENV_VAR;
1398 DIAG(TD_OPTIONS,
1399 netputs("ENVIRON VALUE and VAR are reversed!\r\n"));
1400 }
1401 }
1402 SB_RESTORE();
1403 #endif
1404
1405 while (!SB_EOF()) {
1406 c = SB_GET();
1407 if ((c == env_ovar) || (c == ENV_USERVAR))
1408 break;
1409 }
1410 }
1411
1412 if (SB_EOF())
1413 return;
1414
1415 cp = varp = (char *)subpointer;
1416 valp = 0;
1417
1418 while (!SB_EOF()) {
1419 c = SB_GET();
1420 if (subchar == TELOPT_OLD_ENVIRON) {
1421 if (c == env_ovar)
1422 c = NEW_ENV_VAR;
1423 else if (c == env_ovalue)
1424 c = NEW_ENV_VALUE;
1425 }
1426 switch (c) {
1427
1428 case NEW_ENV_VALUE:
1429 *cp = '\0';
1430 cp = valp = (char *)subpointer;
1431 break;
1432
1433 case NEW_ENV_VAR:
1434 case ENV_USERVAR:
1435 *cp = '\0';
1436 if (envvarok(varp)) {
1437 if (valp)
1438 (void)setenv(varp, valp, 1);
1439 else
1440 unsetenv(varp);
1441 }
1442 cp = varp = (char *)subpointer;
1443 valp = 0;
1444 break;
1445
1446 case ENV_ESC:
1447 if (SB_EOF())
1448 break;
1449 c = SB_GET();
1450 /* FALL THROUGH */
1451 default:
1452 *cp++ = c;
1453 break;
1454 }
1455 }
1456 *cp = '\0';
1457 if (envvarok(varp)) {
1458 if (valp)
1459 (void)setenv(varp, valp, 1);
1460 else
1461 unsetenv(varp);
1462 }
1463 break;
1464 } /* end of case TELOPT_NEW_ENVIRON */
1465 #if defined(AUTHENTICATION)
1466 case TELOPT_AUTHENTICATION:
1467 if (SB_EOF())
1468 break;
1469 switch(SB_GET()) {
1470 case TELQUAL_SEND:
1471 case TELQUAL_REPLY:
1472 /*
1473 * These are sent by us and cannot be sent by
1474 * the client.
1475 */
1476 break;
1477 case TELQUAL_IS:
1478 if (!auth_negotiated)
1479 auth_is(subpointer, SB_LEN());
1480 break;
1481 case TELQUAL_NAME:
1482 if (!auth_negotiated)
1483 auth_name(subpointer, SB_LEN());
1484 break;
1485 }
1486 break;
1487 #endif
1488 #ifdef ENCRYPTION
1489 case TELOPT_ENCRYPT:
1490 if (SB_EOF())
1491 break;
1492 switch(SB_GET()) {
1493 case ENCRYPT_SUPPORT:
1494 encrypt_support(subpointer, SB_LEN());
1495 break;
1496 case ENCRYPT_IS:
1497 encrypt_is(subpointer, SB_LEN());
1498 break;
1499 case ENCRYPT_REPLY:
1500 encrypt_reply(subpointer, SB_LEN());
1501 break;
1502 case ENCRYPT_START:
1503 encrypt_start(subpointer, SB_LEN());
1504 break;
1505 case ENCRYPT_END:
1506 encrypt_end();
1507 break;
1508 case ENCRYPT_REQSTART:
1509 encrypt_request_start(subpointer, SB_LEN());
1510 break;
1511 case ENCRYPT_REQEND:
1512 /*
1513 * We can always send an REQEND so that we cannot
1514 * get stuck encrypting. We should only get this
1515 * if we have been able to get in the correct mode
1516 * anyhow.
1517 */
1518 encrypt_request_end();
1519 break;
1520 case ENCRYPT_ENC_KEYID:
1521 encrypt_enc_keyid(subpointer, SB_LEN());
1522 break;
1523 case ENCRYPT_DEC_KEYID:
1524 encrypt_dec_keyid(subpointer, SB_LEN());
1525 break;
1526 default:
1527 break;
1528 }
1529 break;
1530 #endif /* ENCRYPTION */
1531
1532 default:
1533 break;
1534 } /* end of switch */
1535
1536 } /* end of suboption */
1537
1538 #ifdef LINEMODE
1539 static void
doclientstat()1540 doclientstat()
1541 {
1542 clientstat(TELOPT_LINEMODE, WILL, 0);
1543 }
1544 #endif
1545
1546 #define ADD(c) *ncp++ = c;
1547 #define ADD_DATA(c) { *ncp++ = c; if (c == SE) *ncp++ = c; }
1548 void
send_status()1549 send_status()
1550 {
1551 unsigned char statusbuf[256];
1552 register unsigned char *ncp;
1553 register unsigned char i;
1554
1555 ncp = statusbuf;
1556
1557 netflush(); /* get rid of anything waiting to go out */
1558
1559 ADD(IAC);
1560 ADD(SB);
1561 ADD(TELOPT_STATUS);
1562 ADD(TELQUAL_IS);
1563
1564 /*
1565 * We check the want_state rather than the current state,
1566 * because if we received a DO/WILL for an option that we
1567 * don't support, and the other side didn't send a DONT/WONT
1568 * in response to our WONT/DONT, then the "state" will be
1569 * WILL/DO, and the "want_state" will be WONT/DONT. We
1570 * need to go by the latter.
1571 */
1572 for (i = 0; i < (unsigned char)NTELOPTS; i++) {
1573 if (my_want_state_is_will(i)) {
1574 ADD(WILL);
1575 ADD_DATA(i);
1576 if (i == IAC)
1577 ADD(IAC);
1578 }
1579 if (his_want_state_is_will(i)) {
1580 ADD(DO);
1581 ADD_DATA(i);
1582 if (i == IAC)
1583 ADD(IAC);
1584 }
1585 }
1586
1587 if (his_want_state_is_will(TELOPT_LFLOW)) {
1588 ADD(SB);
1589 ADD(TELOPT_LFLOW);
1590 if (flowmode) {
1591 ADD(LFLOW_ON);
1592 } else {
1593 ADD(LFLOW_OFF);
1594 }
1595 ADD(SE);
1596
1597 if (restartany >= 0) {
1598 ADD(SB)
1599 ADD(TELOPT_LFLOW);
1600 if (restartany) {
1601 ADD(LFLOW_RESTART_ANY);
1602 } else {
1603 ADD(LFLOW_RESTART_XON);
1604 }
1605 ADD(SE)
1606 ADD(SB);
1607 }
1608 }
1609
1610 #ifdef LINEMODE
1611 if (his_want_state_is_will(TELOPT_LINEMODE)) {
1612 unsigned char *cp, *cpe;
1613 int len;
1614
1615 ADD(SB);
1616 ADD(TELOPT_LINEMODE);
1617 ADD(LM_MODE);
1618 ADD_DATA(editmode);
1619 if (editmode == IAC)
1620 ADD(IAC);
1621 ADD(SE);
1622
1623 ADD(SB);
1624 ADD(TELOPT_LINEMODE);
1625 ADD(LM_SLC);
1626 start_slc(0);
1627 send_slc();
1628 len = end_slc(&cp);
1629 for (cpe = cp + len; cp < cpe; cp++)
1630 ADD_DATA(*cp);
1631 ADD(SE);
1632 }
1633 #endif /* LINEMODE */
1634
1635 ADD(IAC);
1636 ADD(SE);
1637
1638 netwrite(statusbuf, (unsigned) (ncp - statusbuf));
1639 netflush(); /* Send it on its way */
1640
1641 DIAG(TD_OPTIONS,
1642 {printsub('>', statusbuf, ncp - statusbuf); netflush();});
1643 }
1644
envvarok(varp)1645 static int envvarok(varp)
1646 char *varp;
1647 {
1648 if (!strchr(varp, '=') &&
1649 strcmp(varp, "TERMCAP") && /* to prevent a security hole */
1650 strcmp(varp, "TERMINFO") && /* with tgetent */
1651 strcmp(varp, "TERMPATH") &&
1652 strcmp(varp, "HOME") && /* to prevent the tegetent bug */
1653 strncmp(varp, "LD_", strlen("LD_")) && /* most systems */
1654 strncmp(varp, "_RLD_", strlen("_RLD_")) && /* irix */
1655 strncmp(varp, "KRB5", strlen("KRB5")) && /* v5 */
1656 /* The above is a catch-all for now. Here are some of the
1657 specific ones we must avoid passing, at least until we
1658 can prove it can be done safely. Keep this list around
1659 in case someone wants to remove the catch-all. */
1660 strcmp(varp, "KRB5_CONFIG") && /* v5 */
1661 strcmp(varp, "KRB5CCNAME") && /* v5 */
1662 strcmp(varp, "KRB5_KTNAME") && /* v5 */
1663 strcmp(varp, "KRBTKFILE") && /* v4 */
1664 strcmp(varp, "KRB_CONF") && /* cns v4 */
1665 strcmp(varp, "KRB_REALMS") && /* cns v4 */
1666 strcmp(varp, "LIBPATH") && /* AIX */
1667 strcmp(varp, "RESOLV_HOST_CONF") && /* linux */
1668 strcmp(varp, "NLSPATH") && /* locale stuff */
1669 strncmp(varp, "LC_", strlen("LC_")) && /* locale stuff */
1670 strcmp(varp, "IFS") &&
1671 (varp[0] != '-')) {
1672 return 1;
1673 } else {
1674 syslog(LOG_INFO, "Rejected the attempt to modify the environment variable \"%s\"", varp);
1675 return 0;
1676 }
1677
1678 }
1679