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 char copyright[] = 10 "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)telnetd.c 5.49 (Berkeley) 12/18/92"; 16 #endif /* not lint */ 17 18 #include "telnetd.h" 19 #include "pathnames.h" 20 21 #if defined(_SC_CRAY_SECURE_SYS) 22 #include <sys/sysv.h> 23 #include <sys/secdev.h> 24 int secflag; 25 char tty_dev[16]; 26 struct secdev dv; 27 struct sysv sysv; 28 struct socket_security ss; 29 #endif /* _SC_CRAY_SECURE_SYS */ 30 31 #if defined(AUTHENTICATION) 32 #include <libtelnet/auth.h> 33 int auth_level = 0; 34 #endif 35 #if defined(SecurID) 36 int require_SecurID = 0; 37 #endif 38 39 extern int utmp_len; 40 int registerd_host_only = 0; 41 42 #ifdef STREAMSPTY 43 # include <stropts.h> 44 # include <termio.h> 45 /* make sure we don't get the bsd version */ 46 # include "/usr/include/sys/tty.h" 47 # include <sys/ptyvar.h> 48 49 /* 50 * Because of the way ptyibuf is used with streams messages, we need 51 * ptyibuf+1 to be on a full-word boundary. The following wierdness 52 * is simply to make that happen. 53 */ 54 char ptyibufbuf[BUFSIZ+4]; 55 char *ptyibuf = ptyibufbuf+3; 56 char *ptyip = ptyibufbuf+3; 57 char ptyibuf2[BUFSIZ]; 58 unsigned char ctlbuf[BUFSIZ]; 59 struct strbuf strbufc, strbufd; 60 61 int readstream(); 62 63 #else /* ! STREAMPTY */ 64 65 /* 66 * I/O data buffers, 67 * pointers, and counters. 68 */ 69 char ptyibuf[BUFSIZ], *ptyip = ptyibuf; 70 char ptyibuf2[BUFSIZ]; 71 72 #endif /* ! STREAMPTY */ 73 74 int hostinfo = 1; /* do we print login banner? */ 75 76 #ifdef CRAY 77 extern int newmap; /* nonzero if \n maps to ^M^J */ 78 int lowpty = 0, highpty; /* low, high pty numbers */ 79 #endif /* CRAY */ 80 81 int debug = 0; 82 int keepalive = 1; 83 char *progname; 84 85 extern void usage P((void)); 86 87 main(argc, argv) 88 char *argv[]; 89 { 90 struct sockaddr_in from; 91 int on = 1, fromlen; 92 register int ch; 93 extern char *optarg; 94 extern int optind; 95 #if defined(IPPROTO_IP) && defined(IP_TOS) 96 int tos = -1; 97 #endif 98 99 pfrontp = pbackp = ptyobuf; 100 netip = netibuf; 101 nfrontp = nbackp = netobuf; 102 #if defined(ENCRYPTION) 103 nclearto = 0; 104 #endif 105 106 progname = *argv; 107 108 #ifdef CRAY 109 /* 110 * Get number of pty's before trying to process options, 111 * which may include changing pty range. 112 */ 113 highpty = getnpty(); 114 #endif /* CRAY */ 115 116 while ((ch = getopt(argc, argv, "d:a:e:klhnr:u:UI:D:B:sS:a:X:")) != EOF) { 117 switch(ch) { 118 119 #ifdef AUTHENTICATION 120 case 'a': 121 /* 122 * Check for required authentication level 123 */ 124 if (strcmp(optarg, "debug") == 0) { 125 extern int auth_debug_mode; 126 auth_debug_mode = 1; 127 } else if (strcasecmp(optarg, "none") == 0) { 128 auth_level = 0; 129 } else if (strcasecmp(optarg, "other") == 0) { 130 auth_level = AUTH_OTHER; 131 } else if (strcasecmp(optarg, "user") == 0) { 132 auth_level = AUTH_USER; 133 } else if (strcasecmp(optarg, "valid") == 0) { 134 auth_level = AUTH_VALID; 135 } else if (strcasecmp(optarg, "off") == 0) { 136 /* 137 * This hack turns off authentication 138 */ 139 auth_level = -1; 140 } else { 141 fprintf(stderr, 142 "telnetd: unknown authorization level for -a\n"); 143 } 144 break; 145 #endif /* AUTHENTICATION */ 146 147 #ifdef BFTPDAEMON 148 case 'B': 149 bftpd++; 150 break; 151 #endif /* BFTPDAEMON */ 152 153 case 'd': 154 if (strcmp(optarg, "ebug") == 0) { 155 debug++; 156 break; 157 } 158 usage(); 159 /* NOTREACHED */ 160 break; 161 162 #ifdef DIAGNOSTICS 163 case 'D': 164 /* 165 * Check for desired diagnostics capabilities. 166 */ 167 if (!strcmp(optarg, "report")) { 168 diagnostic |= TD_REPORT|TD_OPTIONS; 169 } else if (!strcmp(optarg, "exercise")) { 170 diagnostic |= TD_EXERCISE; 171 } else if (!strcmp(optarg, "netdata")) { 172 diagnostic |= TD_NETDATA; 173 } else if (!strcmp(optarg, "ptydata")) { 174 diagnostic |= TD_PTYDATA; 175 } else if (!strcmp(optarg, "options")) { 176 diagnostic |= TD_OPTIONS; 177 } else { 178 usage(); 179 /* NOT REACHED */ 180 } 181 break; 182 #endif /* DIAGNOSTICS */ 183 184 #ifdef ENCRYPTION 185 case 'e': 186 if (strcmp(optarg, "debug") == 0) { 187 extern int encrypt_debug_mode; 188 encrypt_debug_mode = 1; 189 break; 190 } 191 usage(); 192 /* NOTREACHED */ 193 break; 194 #endif /* ENCRYPTION */ 195 196 case 'h': 197 hostinfo = 0; 198 break; 199 200 #if defined(CRAY) && defined(NEWINIT) 201 case 'I': 202 { 203 extern char *gen_id; 204 gen_id = optarg; 205 break; 206 } 207 #endif /* defined(CRAY) && defined(NEWINIT) */ 208 209 #ifdef LINEMODE 210 case 'l': 211 alwayslinemode = 1; 212 break; 213 #endif /* LINEMODE */ 214 215 case 'k': 216 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 217 lmodetype = NO_AUTOKLUDGE; 218 #else 219 /* ignore -k option if built without kludge linemode */ 220 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 221 break; 222 223 case 'n': 224 keepalive = 0; 225 break; 226 227 #ifdef CRAY 228 case 'r': 229 { 230 char *strchr(); 231 char *c; 232 233 /* 234 * Allow the specification of alterations 235 * to the pty search range. It is legal to 236 * specify only one, and not change the 237 * other from its default. 238 */ 239 c = strchr(optarg, '-'); 240 if (c) { 241 *c++ = '\0'; 242 highpty = atoi(c); 243 } 244 if (*optarg != '\0') 245 lowpty = atoi(optarg); 246 if ((lowpty > highpty) || (lowpty < 0) || 247 (highpty > 32767)) { 248 usage(); 249 /* NOT REACHED */ 250 } 251 break; 252 } 253 #endif /* CRAY */ 254 255 #ifdef SecurID 256 case 's': 257 /* SecurID required */ 258 require_SecurID = 1; 259 break; 260 #endif /* SecurID */ 261 case 'S': 262 #ifdef HAS_GETTOS 263 if ((tos = parsetos(optarg, "tcp")) < 0) 264 fprintf(stderr, "%s%s%s\n", 265 "telnetd: Bad TOS argument '", optarg, 266 "'; will try to use default TOS"); 267 #else 268 fprintf(stderr, "%s%s\n", "TOS option unavailable; ", 269 "-S flag not supported\n"); 270 #endif 271 break; 272 273 case 'u': 274 utmp_len = atoi(optarg); 275 break; 276 277 case 'U': 278 registerd_host_only = 1; 279 break; 280 281 #ifdef AUTHENTICATION 282 case 'X': 283 /* 284 * Check for invalid authentication types 285 */ 286 auth_disable_name(optarg); 287 break; 288 #endif /* AUTHENTICATION */ 289 290 default: 291 fprintf(stderr, "telnetd: %s: unknown option\n", ch); 292 /* FALLTHROUGH */ 293 case '?': 294 usage(); 295 /* NOTREACHED */ 296 } 297 } 298 299 argc -= optind; 300 argv += optind; 301 302 if (debug) { 303 int s, ns, foo; 304 struct servent *sp; 305 static struct sockaddr_in sin = { AF_INET }; 306 307 if (argc > 1) { 308 usage(); 309 /* NOT REACHED */ 310 } else if (argc == 1) { 311 if (sp = getservbyname(*argv, "tcp")) { 312 sin.sin_port = sp->s_port; 313 } else { 314 sin.sin_port = atoi(*argv); 315 if ((int)sin.sin_port <= 0) { 316 fprintf(stderr, "telnetd: %s: bad port #\n", *argv); 317 usage(); 318 /* NOT REACHED */ 319 } 320 sin.sin_port = htons((u_short)sin.sin_port); 321 } 322 } else { 323 sp = getservbyname("telnet", "tcp"); 324 if (sp == 0) { 325 fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); 326 exit(1); 327 } 328 sin.sin_port = sp->s_port; 329 } 330 331 s = socket(AF_INET, SOCK_STREAM, 0); 332 if (s < 0) { 333 perror("telnetd: socket");; 334 exit(1); 335 } 336 (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 337 (char *)&on, sizeof(on)); 338 if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { 339 perror("bind"); 340 exit(1); 341 } 342 if (listen(s, 1) < 0) { 343 perror("listen"); 344 exit(1); 345 } 346 foo = sizeof sin; 347 ns = accept(s, (struct sockaddr *)&sin, &foo); 348 if (ns < 0) { 349 perror("accept"); 350 exit(1); 351 } 352 (void) dup2(ns, 0); 353 (void) close(ns); 354 (void) close(s); 355 #ifdef convex 356 } else if (argc == 1) { 357 ; /* VOID*/ /* Just ignore the host/port name */ 358 #endif 359 } else if (argc > 0) { 360 usage(); 361 /* NOT REACHED */ 362 } 363 364 #if defined(_SC_CRAY_SECURE_SYS) 365 secflag = sysconf(_SC_CRAY_SECURE_SYS); 366 367 /* 368 * Get socket's security label 369 */ 370 if (secflag) { 371 int sz = sizeof(ss); 372 373 bzero((char *)&dv, sizeof(dv)); 374 375 if (getsysv(&sysv, sizeof(struct sysv)) != 0) { 376 perror("getsysv"); 377 exit(1); 378 } 379 380 /* 381 * Get socket security label and set device values 382 * {security label to be set on ttyp device} 383 */ 384 if (getsockopt(0, SOL_SOCKET, SO_SECURITY, 385 (char *)&ss, &sz) >= 0) { 386 387 dv.dv_actlvl = ss.ss_slevel; 388 dv.dv_actcmp = ss.ss_compart; 389 dv.dv_minlvl = ss.ss_minlvl; 390 dv.dv_maxlvl = ss.ss_maxlvl; 391 dv.dv_valcmp = ss.ss_maxcmp; 392 } 393 } 394 #endif /* _SC_CRAY_SECURE_SYS */ 395 396 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 397 fromlen = sizeof (from); 398 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 399 fprintf(stderr, "%s: ", progname); 400 perror("getpeername"); 401 _exit(1); 402 } 403 if (keepalive && 404 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, 405 (char *)&on, sizeof (on)) < 0) { 406 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 407 } 408 409 #if defined(IPPROTO_IP) && defined(IP_TOS) 410 { 411 # if defined(HAS_GETTOS) 412 struct tosent *tp; 413 if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 414 tos = tp->t_tos; 415 # endif 416 if (tos < 0) 417 tos = 020; /* Low Delay bit */ 418 if (tos 419 && (setsockopt(0, IPPROTO_IP, IP_TOS, 420 (char *)&tos, sizeof(tos)) < 0) 421 && (errno != ENOPROTOOPT) ) 422 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 423 } 424 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 425 net = 0; 426 doit(&from); 427 /* NOTREACHED */ 428 } /* end of main */ 429 430 void 431 usage() 432 { 433 fprintf(stderr, "Usage: telnetd"); 434 #ifdef AUTHENTICATION 435 fprintf(stderr, " [-a (debug|other|user|valid|off)]\n\t"); 436 #endif 437 #ifdef BFTPDAEMON 438 fprintf(stderr, " [-B]"); 439 #endif 440 fprintf(stderr, " [-debug]"); 441 #ifdef DIAGNOSTICS 442 fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); 443 #endif 444 #ifdef AUTHENTICATION 445 fprintf(stderr, " [-edebug]"); 446 #endif 447 fprintf(stderr, " [-h]"); 448 #if defined(CRAY) && defined(NEWINIT) 449 fprintf(stderr, " [-Iinitid]"); 450 #endif 451 #ifdef LINEMODE 452 fprintf(stderr, " [-l]"); 453 #endif 454 fprintf(stderr, " [-n]"); 455 #ifdef CRAY 456 fprintf(stderr, " [-r[lowpty]-[highpty]]"); 457 #endif 458 #ifdef SecurID 459 fprintf(stderr, " [-s]"); 460 #endif 461 #ifdef AUTHENTICATION 462 fprintf(stderr, " [-X auth-type]"); 463 #endif 464 fprintf(stderr, " [-u utmp_hostname_length] [-U]"); 465 fprintf(stderr, " [port]\n"); 466 exit(1); 467 } 468 469 /* 470 * getterminaltype 471 * 472 * Ask the other end to send along its terminal type and speed. 473 * Output is the variable terminaltype filled in. 474 */ 475 static char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE }; 476 477 int 478 getterminaltype(name) 479 char *name; 480 { 481 int retval = -1; 482 void _gettermname(); 483 484 settimer(baseline); 485 #if defined(AUTHENTICATION) 486 /* 487 * Handle the Authentication option before we do anything else. 488 */ 489 send_do(TELOPT_AUTHENTICATION, 1); 490 while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) 491 ttloop(); 492 if (his_state_is_will(TELOPT_AUTHENTICATION)) { 493 retval = auth_wait(name); 494 } 495 #endif 496 497 #if defined(ENCRYPTION) 498 send_will(TELOPT_ENCRYPT, 1); 499 #endif 500 send_do(TELOPT_TTYPE, 1); 501 send_do(TELOPT_TSPEED, 1); 502 send_do(TELOPT_XDISPLOC, 1); 503 send_do(TELOPT_ENVIRON, 1); 504 while ( 505 #if defined(ENCRYPTION) 506 his_do_dont_is_changing(TELOPT_ENCRYPT) || 507 #endif 508 his_will_wont_is_changing(TELOPT_TTYPE) || 509 his_will_wont_is_changing(TELOPT_TSPEED) || 510 his_will_wont_is_changing(TELOPT_XDISPLOC) || 511 his_will_wont_is_changing(TELOPT_ENVIRON)) { 512 ttloop(); 513 } 514 #if defined(ENCRYPTION) 515 /* 516 * Wait for the negotiation of what type of encryption we can 517 * send with. If autoencrypt is not set, this will just return. 518 */ 519 if (his_state_is_will(TELOPT_ENCRYPT)) { 520 encrypt_wait(); 521 } 522 #endif 523 if (his_state_is_will(TELOPT_TSPEED)) { 524 static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; 525 526 bcopy(sbbuf, nfrontp, sizeof sbbuf); 527 nfrontp += sizeof sbbuf; 528 } 529 if (his_state_is_will(TELOPT_XDISPLOC)) { 530 static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; 531 532 bcopy(sbbuf, nfrontp, sizeof sbbuf); 533 nfrontp += sizeof sbbuf; 534 } 535 if (his_state_is_will(TELOPT_ENVIRON)) { 536 static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE }; 537 538 bcopy(sbbuf, nfrontp, sizeof sbbuf); 539 nfrontp += sizeof sbbuf; 540 } 541 if (his_state_is_will(TELOPT_TTYPE)) { 542 543 bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf); 544 nfrontp += sizeof ttytype_sbbuf; 545 } 546 if (his_state_is_will(TELOPT_TSPEED)) { 547 while (sequenceIs(tspeedsubopt, baseline)) 548 ttloop(); 549 } 550 if (his_state_is_will(TELOPT_XDISPLOC)) { 551 while (sequenceIs(xdisplocsubopt, baseline)) 552 ttloop(); 553 } 554 if (his_state_is_will(TELOPT_ENVIRON)) { 555 while (sequenceIs(environsubopt, baseline)) 556 ttloop(); 557 } 558 if (his_state_is_will(TELOPT_TTYPE)) { 559 char first[256], last[256]; 560 561 while (sequenceIs(ttypesubopt, baseline)) 562 ttloop(); 563 564 /* 565 * If the other side has already disabled the option, then 566 * we have to just go with what we (might) have already gotten. 567 */ 568 if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { 569 (void) strncpy(first, terminaltype, sizeof(first)); 570 for(;;) { 571 /* 572 * Save the unknown name, and request the next name. 573 */ 574 (void) strncpy(last, terminaltype, sizeof(last)); 575 _gettermname(); 576 if (terminaltypeok(terminaltype)) 577 break; 578 if ((strncmp(last, terminaltype, sizeof(last)) == 0) || 579 his_state_is_wont(TELOPT_TTYPE)) { 580 /* 581 * We've hit the end. If this is the same as 582 * the first name, just go with it. 583 */ 584 if (strncmp(first, terminaltype, sizeof(first)) == 0) 585 break; 586 /* 587 * Get the terminal name one more time, so that 588 * RFC1091 compliant telnets will cycle back to 589 * the start of the list. 590 */ 591 _gettermname(); 592 if (strncmp(first, terminaltype, sizeof(first)) != 0) 593 (void) strncpy(terminaltype, first, sizeof(first)); 594 break; 595 } 596 } 597 } 598 } 599 return(retval); 600 } /* end of getterminaltype */ 601 602 void 603 _gettermname() 604 { 605 /* 606 * If the client turned off the option, 607 * we can't send another request, so we 608 * just return. 609 */ 610 if (his_state_is_wont(TELOPT_TTYPE)) 611 return; 612 settimer(baseline); 613 bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf); 614 nfrontp += sizeof ttytype_sbbuf; 615 while (sequenceIs(ttypesubopt, baseline)) 616 ttloop(); 617 } 618 619 int 620 terminaltypeok(s) 621 char *s; 622 { 623 char buf[1024]; 624 625 if (terminaltype == NULL) 626 return(1); 627 628 /* 629 * tgetent() will return 1 if the type is known, and 630 * 0 if it is not known. If it returns -1, it couldn't 631 * open the database. But if we can't open the database, 632 * it won't help to say we failed, because we won't be 633 * able to verify anything else. So, we treat -1 like 1. 634 */ 635 if (tgetent(buf, s) == 0) 636 return(0); 637 return(1); 638 } 639 640 #ifndef MAXHOSTNAMELEN 641 #define MAXHOSTNAMELEN 64 642 #endif /* MAXHOSTNAMELEN */ 643 644 char *hostname; 645 char host_name[MAXHOSTNAMELEN]; 646 char remote_host_name[MAXHOSTNAMELEN]; 647 648 #ifndef convex 649 extern void telnet P((int, int)); 650 #else 651 extern void telnet P((int, int, char *)); 652 #endif 653 654 /* 655 * Get a pty, scan input lines. 656 */ 657 doit(who) 658 struct sockaddr_in *who; 659 { 660 char *host, *inet_ntoa(); 661 int t; 662 struct hostent *hp; 663 int level; 664 char user_name[256]; 665 666 /* 667 * Find an available pty to use. 668 */ 669 #ifndef convex 670 pty = getpty(); 671 if (pty < 0) 672 fatal(net, "All network ports in use"); 673 #else 674 for (;;) { 675 char *lp; 676 extern char *line, *getpty(); 677 678 if ((lp = getpty()) == NULL) 679 fatal(net, "Out of ptys"); 680 681 if ((pty = open(lp, 2)) >= 0) { 682 strcpy(line,lp); 683 line[5] = 't'; 684 break; 685 } 686 } 687 #endif 688 689 #if defined(_SC_CRAY_SECURE_SYS) 690 /* 691 * set ttyp line security label 692 */ 693 if (secflag) { 694 extern char *myline; 695 if (setdevs(myline, &dv) < 0) 696 fatal(net, "cannot set pty security"); 697 } 698 #endif /* _SC_CRAY_SECURE_SYS */ 699 700 /* get name of connected client */ 701 hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), 702 who->sin_family); 703 704 if (hp && 705 (strlen(hp->h_name) <= ((utmp_len < 0) ? -utmp_len : utmp_len))) { 706 host = hp->h_name; 707 } else if (registerd_host_only) { 708 fatal(net, "Couldn't resolve your address into a host name.\r\n\ 709 Please contact your net administrator"); 710 } else { 711 host = inet_ntoa(who->sin_addr); 712 } 713 /* 714 * We must make a copy because Kerberos is probably going 715 * to also do a gethost* and overwrite the static data... 716 */ 717 strncpy(remote_host_name, host, sizeof(remote_host_name)-1); 718 remote_host_name[sizeof(remote_host_name)-1] = 0; 719 host = remote_host_name; 720 721 (void) gethostname(host_name, sizeof (host_name)); 722 hostname = host_name; 723 724 #if defined(AUTHENTICATION) || defined(ENCRYPTION) 725 auth_encrypt_init(hostname, host, "TELNETD", 1); 726 #endif 727 728 init_env(); 729 /* 730 * get terminal type. 731 */ 732 *user_name = 0; 733 level = getterminaltype(user_name); 734 setenv("TERM", terminaltype ? terminaltype : "network", 1); 735 736 /* 737 * Start up the login process on the slave side of the terminal 738 */ 739 #ifndef convex 740 startslave(host, level, user_name); 741 742 telnet(net, pty); /* begin server processing */ 743 #else 744 telnet(net, pty, host); 745 #endif 746 /*NOTREACHED*/ 747 } /* end of doit */ 748 749 #if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) 750 int 751 Xterm_output(ibufp, obuf, icountp, ocount) 752 char **ibufp, *obuf; 753 int *icountp, ocount; 754 { 755 int ret; 756 ret = term_output(*ibufp, obuf, *icountp, ocount); 757 *ibufp += *icountp; 758 *icountp = 0; 759 return(ret); 760 } 761 #define term_output Xterm_output 762 #endif /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */ 763 764 /* 765 * Main loop. Select from pty and network, and 766 * hand data to telnet receiver finite state machine. 767 */ 768 void 769 #ifndef convex 770 telnet(f, p) 771 #else 772 telnet(f, p, host) 773 #endif 774 int f, p; 775 #ifdef convex 776 char *host; 777 #endif 778 { 779 int on = 1; 780 #define TABBUFSIZ 512 781 char defent[TABBUFSIZ]; 782 char defstrs[TABBUFSIZ]; 783 #undef TABBUFSIZ 784 char *HE; 785 char *HN; 786 char *IM; 787 void netflush(); 788 789 /* 790 * Initialize the slc mapping table. 791 */ 792 get_slc_defaults(); 793 794 /* 795 * Do some tests where it is desireable to wait for a response. 796 * Rather than doing them slowly, one at a time, do them all 797 * at once. 798 */ 799 if (my_state_is_wont(TELOPT_SGA)) 800 send_will(TELOPT_SGA, 1); 801 /* 802 * Is the client side a 4.2 (NOT 4.3) system? We need to know this 803 * because 4.2 clients are unable to deal with TCP urgent data. 804 * 805 * To find out, we send out a "DO ECHO". If the remote system 806 * answers "WILL ECHO" it is probably a 4.2 client, and we note 807 * that fact ("WILL ECHO" ==> that the client will echo what 808 * WE, the server, sends it; it does NOT mean that the client will 809 * echo the terminal input). 810 */ 811 send_do(TELOPT_ECHO, 1); 812 813 #ifdef LINEMODE 814 if (his_state_is_wont(TELOPT_LINEMODE)) { 815 /* Query the peer for linemode support by trying to negotiate 816 * the linemode option. 817 */ 818 linemode = 0; 819 editmode = 0; 820 send_do(TELOPT_LINEMODE, 1); /* send do linemode */ 821 } 822 #endif /* LINEMODE */ 823 824 /* 825 * Send along a couple of other options that we wish to negotiate. 826 */ 827 send_do(TELOPT_NAWS, 1); 828 send_will(TELOPT_STATUS, 1); 829 flowmode = 1; /* default flow control state */ 830 send_do(TELOPT_LFLOW, 1); 831 832 /* 833 * Spin, waiting for a response from the DO ECHO. However, 834 * some REALLY DUMB telnets out there might not respond 835 * to the DO ECHO. So, we spin looking for NAWS, (most dumb 836 * telnets so far seem to respond with WONT for a DO that 837 * they don't understand...) because by the time we get the 838 * response, it will already have processed the DO ECHO. 839 * Kludge upon kludge. 840 */ 841 while (his_will_wont_is_changing(TELOPT_NAWS)) 842 ttloop(); 843 844 /* 845 * But... 846 * The client might have sent a WILL NAWS as part of its 847 * startup code; if so, we'll be here before we get the 848 * response to the DO ECHO. We'll make the assumption 849 * that any implementation that understands about NAWS 850 * is a modern enough implementation that it will respond 851 * to our DO ECHO request; hence we'll do another spin 852 * waiting for the ECHO option to settle down, which is 853 * what we wanted to do in the first place... 854 */ 855 if (his_want_state_is_will(TELOPT_ECHO) && 856 his_state_is_will(TELOPT_NAWS)) { 857 while (his_will_wont_is_changing(TELOPT_ECHO)) 858 ttloop(); 859 } 860 /* 861 * On the off chance that the telnet client is broken and does not 862 * respond to the DO ECHO we sent, (after all, we did send the 863 * DO NAWS negotiation after the DO ECHO, and we won't get here 864 * until a response to the DO NAWS comes back) simulate the 865 * receipt of a will echo. This will also send a WONT ECHO 866 * to the client, since we assume that the client failed to 867 * respond because it believes that it is already in DO ECHO 868 * mode, which we do not want. 869 */ 870 if (his_want_state_is_will(TELOPT_ECHO)) { 871 DIAG(TD_OPTIONS, 872 {sprintf(nfrontp, "td: simulating recv\r\n"); 873 nfrontp += strlen(nfrontp);}); 874 willoption(TELOPT_ECHO); 875 } 876 877 /* 878 * Finally, to clean things up, we turn on our echo. This 879 * will break stupid 4.2 telnets out of local terminal echo. 880 */ 881 882 if (my_state_is_wont(TELOPT_ECHO)) 883 send_will(TELOPT_ECHO, 1); 884 885 #ifndef STREAMSPTY 886 /* 887 * Turn on packet mode 888 */ 889 (void) ioctl(p, TIOCPKT, (char *)&on); 890 #endif 891 892 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 893 /* 894 * Continuing line mode support. If client does not support 895 * real linemode, attempt to negotiate kludge linemode by sending 896 * the do timing mark sequence. 897 */ 898 if (lmodetype < REAL_LINEMODE) 899 send_do(TELOPT_TM, 1); 900 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 901 902 /* 903 * Call telrcv() once to pick up anything received during 904 * terminal type negotiation, 4.2/4.3 determination, and 905 * linemode negotiation. 906 */ 907 telrcv(); 908 909 (void) ioctl(f, FIONBIO, (char *)&on); 910 (void) ioctl(p, FIONBIO, (char *)&on); 911 #if defined(CRAY2) && defined(UNICOS5) 912 init_termdriver(f, p, interrupt, sendbrk); 913 #endif 914 915 #if defined(SO_OOBINLINE) 916 (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, 917 (char *)&on, sizeof on); 918 #endif /* defined(SO_OOBINLINE) */ 919 920 #ifdef SIGTSTP 921 (void) signal(SIGTSTP, SIG_IGN); 922 #endif 923 #ifdef SIGTTOU 924 /* 925 * Ignoring SIGTTOU keeps the kernel from blocking us 926 * in ttioct() in /sys/tty.c. 927 */ 928 (void) signal(SIGTTOU, SIG_IGN); 929 #endif 930 931 (void) signal(SIGCHLD, cleanup); 932 933 #if defined(CRAY2) && defined(UNICOS5) 934 /* 935 * Cray-2 will send a signal when pty modes are changed by slave 936 * side. Set up signal handler now. 937 */ 938 if ((int)signal(SIGUSR1, termstat) < 0) 939 perror("signal"); 940 else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) 941 perror("ioctl:TCSIGME"); 942 /* 943 * Make processing loop check terminal characteristics early on. 944 */ 945 termstat(); 946 #endif 947 948 #ifdef TIOCNOTTY 949 { 950 register int t; 951 t = open(_PATH_TTY, O_RDWR); 952 if (t >= 0) { 953 (void) ioctl(t, TIOCNOTTY, (char *)0); 954 (void) close(t); 955 } 956 } 957 #endif 958 959 #if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) 960 (void) setsid(); 961 ioctl(p, TIOCSCTTY, 0); 962 #endif 963 964 /* 965 * Show banner that getty never gave. 966 * 967 * We put the banner in the pty input buffer. This way, it 968 * gets carriage return null processing, etc., just like all 969 * other pty --> client data. 970 */ 971 972 #if !defined(CRAY) || !defined(NEWINIT) 973 if (getenv("USER")) 974 hostinfo = 0; 975 #endif 976 977 if (getent(defent, "default") == 1) { 978 char *getstr(); 979 char *cp=defstrs; 980 981 HE = getstr("he", &cp); 982 HN = getstr("hn", &cp); 983 IM = getstr("im", &cp); 984 if (HN && *HN) 985 (void) strcpy(host_name, HN); 986 if (IM == 0) 987 IM = ""; 988 } else { 989 IM = DEFAULT_IM; 990 HE = 0; 991 } 992 edithost(HE, host_name); 993 if (hostinfo && *IM) 994 putf(IM, ptyibuf2); 995 996 if (pcc) 997 (void) strncat(ptyibuf2, ptyip, pcc+1); 998 ptyip = ptyibuf2; 999 pcc = strlen(ptyip); 1000 #ifdef LINEMODE 1001 /* 1002 * Last check to make sure all our states are correct. 1003 */ 1004 init_termbuf(); 1005 localstat(); 1006 #endif /* LINEMODE */ 1007 1008 DIAG(TD_REPORT, 1009 {sprintf(nfrontp, "td: Entering processing loop\r\n"); 1010 nfrontp += strlen(nfrontp);}); 1011 1012 #ifdef convex 1013 startslave(host); 1014 #endif 1015 1016 for (;;) { 1017 fd_set ibits, obits, xbits; 1018 register int c; 1019 1020 if (ncc < 0 && pcc < 0) 1021 break; 1022 1023 #if defined(CRAY2) && defined(UNICOS5) 1024 if (needtermstat) 1025 _termstat(); 1026 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1027 FD_ZERO(&ibits); 1028 FD_ZERO(&obits); 1029 FD_ZERO(&xbits); 1030 /* 1031 * Never look for input if there's still 1032 * stuff in the corresponding output buffer 1033 */ 1034 if (nfrontp - nbackp || pcc > 0) { 1035 FD_SET(f, &obits); 1036 } else { 1037 FD_SET(p, &ibits); 1038 } 1039 if (pfrontp - pbackp || ncc > 0) { 1040 FD_SET(p, &obits); 1041 } else { 1042 FD_SET(f, &ibits); 1043 } 1044 if (!SYNCHing) { 1045 FD_SET(f, &xbits); 1046 } 1047 if ((c = select(16, &ibits, &obits, &xbits, 1048 (struct timeval *)0)) < 1) { 1049 if (c == -1) { 1050 if (errno == EINTR) { 1051 continue; 1052 } 1053 } 1054 sleep(5); 1055 continue; 1056 } 1057 1058 /* 1059 * Any urgent data? 1060 */ 1061 if (FD_ISSET(net, &xbits)) { 1062 SYNCHing = 1; 1063 } 1064 1065 /* 1066 * Something to read from the network... 1067 */ 1068 if (FD_ISSET(net, &ibits)) { 1069 #if !defined(SO_OOBINLINE) 1070 /* 1071 * In 4.2 (and 4.3 beta) systems, the 1072 * OOB indication and data handling in the kernel 1073 * is such that if two separate TCP Urgent requests 1074 * come in, one byte of TCP data will be overlaid. 1075 * This is fatal for Telnet, but we try to live 1076 * with it. 1077 * 1078 * In addition, in 4.2 (and...), a special protocol 1079 * is needed to pick up the TCP Urgent data in 1080 * the correct sequence. 1081 * 1082 * What we do is: if we think we are in urgent 1083 * mode, we look to see if we are "at the mark". 1084 * If we are, we do an OOB receive. If we run 1085 * this twice, we will do the OOB receive twice, 1086 * but the second will fail, since the second 1087 * time we were "at the mark", but there wasn't 1088 * any data there (the kernel doesn't reset 1089 * "at the mark" until we do a normal read). 1090 * Once we've read the OOB data, we go ahead 1091 * and do normal reads. 1092 * 1093 * There is also another problem, which is that 1094 * since the OOB byte we read doesn't put us 1095 * out of OOB state, and since that byte is most 1096 * likely the TELNET DM (data mark), we would 1097 * stay in the TELNET SYNCH (SYNCHing) state. 1098 * So, clocks to the rescue. If we've "just" 1099 * received a DM, then we test for the 1100 * presence of OOB data when the receive OOB 1101 * fails (and AFTER we did the normal mode read 1102 * to clear "at the mark"). 1103 */ 1104 if (SYNCHing) { 1105 int atmark; 1106 1107 (void) ioctl(net, SIOCATMARK, (char *)&atmark); 1108 if (atmark) { 1109 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); 1110 if ((ncc == -1) && (errno == EINVAL)) { 1111 ncc = read(net, netibuf, sizeof (netibuf)); 1112 if (sequenceIs(didnetreceive, gotDM)) { 1113 SYNCHing = stilloob(net); 1114 } 1115 } 1116 } else { 1117 ncc = read(net, netibuf, sizeof (netibuf)); 1118 } 1119 } else { 1120 ncc = read(net, netibuf, sizeof (netibuf)); 1121 } 1122 settimer(didnetreceive); 1123 #else /* !defined(SO_OOBINLINE)) */ 1124 ncc = read(net, netibuf, sizeof (netibuf)); 1125 #endif /* !defined(SO_OOBINLINE)) */ 1126 if (ncc < 0 && errno == EWOULDBLOCK) 1127 ncc = 0; 1128 else { 1129 if (ncc <= 0) { 1130 break; 1131 } 1132 netip = netibuf; 1133 } 1134 DIAG((TD_REPORT | TD_NETDATA), 1135 {sprintf(nfrontp, "td: netread %d chars\r\n", ncc); 1136 nfrontp += strlen(nfrontp);}); 1137 DIAG(TD_NETDATA, printdata("nd", netip, ncc)); 1138 } 1139 1140 /* 1141 * Something to read from the pty... 1142 */ 1143 if (FD_ISSET(p, &ibits)) { 1144 #ifndef STREAMSPTY 1145 pcc = read(p, ptyibuf, BUFSIZ); 1146 #else 1147 pcc = readstream(p, ptyibuf, BUFSIZ); 1148 #endif 1149 /* 1150 * On some systems, if we try to read something 1151 * off the master side before the slave side is 1152 * opened, we get EIO. 1153 */ 1154 if (pcc < 0 && (errno == EWOULDBLOCK || 1155 #ifdef EAGAIN 1156 errno == EAGAIN || 1157 #endif 1158 errno == EIO)) { 1159 pcc = 0; 1160 } else { 1161 if (pcc <= 0) 1162 break; 1163 #if !defined(CRAY2) || !defined(UNICOS5) 1164 #ifdef LINEMODE 1165 /* 1166 * If ioctl from pty, pass it through net 1167 */ 1168 if (ptyibuf[0] & TIOCPKT_IOCTL) { 1169 copy_termbuf(ptyibuf+1, pcc-1); 1170 localstat(); 1171 pcc = 1; 1172 } 1173 #endif /* LINEMODE */ 1174 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { 1175 netclear(); /* clear buffer back */ 1176 #ifndef NO_URGENT 1177 /* 1178 * There are client telnets on some 1179 * operating systems get screwed up 1180 * royally if we send them urgent 1181 * mode data. 1182 */ 1183 *nfrontp++ = IAC; 1184 *nfrontp++ = DM; 1185 neturg = nfrontp-1; /* off by one XXX */ 1186 #endif 1187 } 1188 if (his_state_is_will(TELOPT_LFLOW) && 1189 (ptyibuf[0] & 1190 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { 1191 (void) sprintf(nfrontp, "%c%c%c%c%c%c", 1192 IAC, SB, TELOPT_LFLOW, 1193 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0, 1194 IAC, SE); 1195 nfrontp += 6; 1196 } 1197 pcc--; 1198 ptyip = ptyibuf+1; 1199 #else /* defined(CRAY2) && defined(UNICOS5) */ 1200 if (!uselinemode) { 1201 unpcc = pcc; 1202 unptyip = ptyibuf; 1203 pcc = term_output(&unptyip, ptyibuf2, 1204 &unpcc, BUFSIZ); 1205 ptyip = ptyibuf2; 1206 } else 1207 ptyip = ptyibuf; 1208 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1209 } 1210 } 1211 1212 while (pcc > 0) { 1213 if ((&netobuf[BUFSIZ] - nfrontp) < 2) 1214 break; 1215 c = *ptyip++ & 0377, pcc--; 1216 if (c == IAC) 1217 *nfrontp++ = c; 1218 #if defined(CRAY2) && defined(UNICOS5) 1219 else if (c == '\n' && 1220 my_state_is_wont(TELOPT_BINARY) && newmap) 1221 *nfrontp++ = '\r'; 1222 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1223 *nfrontp++ = c; 1224 if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { 1225 if (pcc > 0 && ((*ptyip & 0377) == '\n')) { 1226 *nfrontp++ = *ptyip++ & 0377; 1227 pcc--; 1228 } else 1229 *nfrontp++ = '\0'; 1230 } 1231 } 1232 #if defined(CRAY2) && defined(UNICOS5) 1233 /* 1234 * If chars were left over from the terminal driver, 1235 * note their existence. 1236 */ 1237 if (!uselinemode && unpcc) { 1238 pcc = unpcc; 1239 unpcc = 0; 1240 ptyip = unptyip; 1241 } 1242 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1243 1244 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) 1245 netflush(); 1246 if (ncc > 0) 1247 telrcv(); 1248 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) 1249 ptyflush(); 1250 } 1251 cleanup(0); 1252 } /* end of telnet */ 1253 1254 #ifndef TCSIG 1255 # ifdef TIOCSIG 1256 # define TCSIG TIOCSIG 1257 # endif 1258 #endif 1259 1260 #ifdef STREAMSPTY 1261 1262 int flowison = -1; /* current state of flow: -1 is unknown */ 1263 1264 int readstream(p, ibuf, bufsize) 1265 int p; 1266 char *ibuf; 1267 int bufsize; 1268 { 1269 int flags = 0; 1270 int ret = 0; 1271 struct termios *tsp; 1272 struct termio *tp; 1273 struct iocblk *ip; 1274 char vstop, vstart; 1275 int ixon; 1276 int newflow; 1277 1278 strbufc.maxlen = BUFSIZ; 1279 strbufc.buf = ctlbuf; 1280 strbufd.maxlen = bufsize-1; 1281 strbufd.len = 0; 1282 strbufd.buf = ibuf+1; 1283 ibuf[0] = 0; 1284 1285 ret = getmsg(p, &strbufc, &strbufd, &flags); 1286 if (ret < 0) /* error of some sort -- probably EAGAIN */ 1287 return(-1); 1288 1289 if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { 1290 /* data message */ 1291 if (strbufd.len > 0) { /* real data */ 1292 return(strbufd.len + 1); /* count header char */ 1293 } else { 1294 /* nothing there */ 1295 errno = EAGAIN; 1296 return(-1); 1297 } 1298 } 1299 1300 /* 1301 * It's a control message. Return 1, to look at the flag we set 1302 */ 1303 1304 switch (ctlbuf[0]) { 1305 case M_FLUSH: 1306 if (ibuf[1] & FLUSHW) 1307 ibuf[0] = TIOCPKT_FLUSHWRITE; 1308 return(1); 1309 1310 case M_IOCTL: 1311 ip = (struct iocblk *) (ibuf+1); 1312 1313 switch (ip->ioc_cmd) { 1314 case TCSETS: 1315 case TCSETSW: 1316 case TCSETSF: 1317 tsp = (struct termios *) 1318 (ibuf+1 + sizeof(struct iocblk)); 1319 vstop = tsp->c_cc[VSTOP]; 1320 vstart = tsp->c_cc[VSTART]; 1321 ixon = tsp->c_iflag & IXON; 1322 break; 1323 case TCSETA: 1324 case TCSETAW: 1325 case TCSETAF: 1326 tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); 1327 vstop = tp->c_cc[VSTOP]; 1328 vstart = tp->c_cc[VSTART]; 1329 ixon = tp->c_iflag & IXON; 1330 break; 1331 default: 1332 errno = EAGAIN; 1333 return(-1); 1334 } 1335 1336 newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; 1337 if (newflow != flowison) { /* it's a change */ 1338 flowison = newflow; 1339 ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; 1340 return(1); 1341 } 1342 } 1343 1344 /* nothing worth doing anything about */ 1345 errno = EAGAIN; 1346 return(-1); 1347 } 1348 #endif /* STREAMSPTY */ 1349 1350 /* 1351 * Send interrupt to process on other side of pty. 1352 * If it is in raw mode, just write NULL; 1353 * otherwise, write intr char. 1354 */ 1355 void 1356 interrupt() 1357 { 1358 ptyflush(); /* half-hearted */ 1359 1360 #ifdef TCSIG 1361 (void) ioctl(pty, TCSIG, (char *)SIGINT); 1362 #else /* TCSIG */ 1363 init_termbuf(); 1364 *pfrontp++ = slctab[SLC_IP].sptr ? 1365 (unsigned char)*slctab[SLC_IP].sptr : '\177'; 1366 #endif /* TCSIG */ 1367 } 1368 1369 /* 1370 * Send quit to process on other side of pty. 1371 * If it is in raw mode, just write NULL; 1372 * otherwise, write quit char. 1373 */ 1374 void 1375 sendbrk() 1376 { 1377 ptyflush(); /* half-hearted */ 1378 #ifdef TCSIG 1379 (void) ioctl(pty, TCSIG, (char *)SIGQUIT); 1380 #else /* TCSIG */ 1381 init_termbuf(); 1382 *pfrontp++ = slctab[SLC_ABORT].sptr ? 1383 (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; 1384 #endif /* TCSIG */ 1385 } 1386 1387 void 1388 sendsusp() 1389 { 1390 #ifdef SIGTSTP 1391 ptyflush(); /* half-hearted */ 1392 # ifdef TCSIG 1393 (void) ioctl(pty, TCSIG, (char *)SIGTSTP); 1394 # else /* TCSIG */ 1395 *pfrontp++ = slctab[SLC_SUSP].sptr ? 1396 (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; 1397 # endif /* TCSIG */ 1398 #endif /* SIGTSTP */ 1399 } 1400 1401 /* 1402 * When we get an AYT, if ^T is enabled, use that. Otherwise, 1403 * just send back "[Yes]". 1404 */ 1405 void 1406 recv_ayt() 1407 { 1408 #if defined(SIGINFO) && defined(TCSIG) 1409 if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { 1410 (void) ioctl(pty, TCSIG, (char *)SIGINFO); 1411 return; 1412 } 1413 #endif 1414 (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); 1415 nfrontp += 9; 1416 } 1417 1418 void 1419 doeof() 1420 { 1421 init_termbuf(); 1422 1423 #if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) 1424 if (!tty_isediting()) { 1425 extern char oldeofc; 1426 *pfrontp++ = oldeofc; 1427 return; 1428 } 1429 #endif 1430 *pfrontp++ = slctab[SLC_EOF].sptr ? 1431 (unsigned char)*slctab[SLC_EOF].sptr : '\004'; 1432 } 1433