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