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