1 /* 2 * Copyright (c) 1983, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1983, 1986 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)telnetd.c 5.37 (Berkeley) 05/11/89"; 26 #endif /* not lint */ 27 28 /* 29 * Telnet server. 30 */ 31 #include <sys/param.h> 32 #include <sys/socket.h> 33 #include <sys/wait.h> 34 #include <sys/file.h> 35 #include <sys/stat.h> 36 #include <sys/time.h> 37 38 #include <netinet/in.h> 39 40 #include <arpa/telnet.h> 41 42 #include <stdio.h> 43 #include <signal.h> 44 #include <errno.h> 45 #include <sgtty.h> 46 #include <netdb.h> 47 #include <syslog.h> 48 #include <ctype.h> 49 #include "pathnames.h" 50 51 #define OPT_NO 0 /* won't do this option */ 52 #define OPT_YES 1 /* will do this option */ 53 #define OPT_YES_BUT_ALWAYS_LOOK 2 54 #define OPT_NO_BUT_ALWAYS_LOOK 3 55 char hisopts[256]; 56 char myopts[256]; 57 58 char doopt[] = { IAC, DO, '%', 'c', 0 }; 59 char dont[] = { IAC, DONT, '%', 'c', 0 }; 60 char will[] = { IAC, WILL, '%', 'c', 0 }; 61 char wont[] = { IAC, WONT, '%', 'c', 0 }; 62 63 /* 64 * I/O data buffers, pointers, and counters. 65 */ 66 char ptyibuf[BUFSIZ], *ptyip = ptyibuf; 67 68 char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf; 69 70 char netibuf[BUFSIZ], *netip = netibuf; 71 #define NIACCUM(c) { *netip++ = c; \ 72 ncc++; \ 73 } 74 75 char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; 76 char *neturg = 0; /* one past last bye of urgent data */ 77 /* the remote system seems to NOT be an old 4.2 */ 78 int not42 = 1; 79 80 #define BANNER "\r\n\r\n4.3 BSD UNIX (%s)\r\n\r\r\n\r" 81 82 /* buffer for sub-options */ 83 char subbuffer[100], *subpointer= subbuffer, *subend= subbuffer; 84 #define SB_CLEAR() subpointer = subbuffer; 85 #define SB_TERM() { subend = subpointer; SB_CLEAR(); } 86 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ 87 *subpointer++ = (c); \ 88 } 89 #define SB_GET() ((*subpointer++)&0xff) 90 #define SB_EOF() (subpointer >= subend) 91 92 int pcc, ncc; 93 94 int pty, net; 95 int inter; 96 extern char **environ; 97 extern int errno; 98 char *line; 99 int SYNCHing = 0; /* we are in TELNET SYNCH mode */ 100 /* 101 * The following are some clocks used to decide how to interpret 102 * the relationship between various variables. 103 */ 104 105 struct { 106 int 107 system, /* what the current time is */ 108 echotoggle, /* last time user entered echo character */ 109 modenegotiated, /* last time operating mode negotiated */ 110 didnetreceive, /* last time we read data from network */ 111 ttypeopt, /* ttype will/won't received */ 112 ttypesubopt, /* ttype subopt is received */ 113 getterminal, /* time started to get terminal information */ 114 gotDM; /* when did we last see a data mark */ 115 } clocks; 116 117 #define settimer(x) (clocks.x = ++clocks.system) 118 #define sequenceIs(x,y) (clocks.x < clocks.y) 119 120 main(argc, argv) 121 char *argv[]; 122 { 123 struct sockaddr_in from; 124 int on = 1, fromlen; 125 126 if ((argc > 1) && (strcmp(argv[1], "-debug") == 0)) { 127 int s, ns, foo; 128 struct servent *sp; 129 static struct sockaddr_in sin = { AF_INET }; 130 131 argc--, argv++; 132 if (argc > 1) { 133 sin.sin_port = atoi(argv[1]); 134 sin.sin_port = htons((u_short)sin.sin_port); 135 } else { 136 sp = getservbyname("telnet", "tcp"); 137 if (sp == 0) { 138 fprintf(stderr, 139 "telnetd: tcp/telnet: unknown service\n"); 140 exit(1); 141 } 142 sin.sin_port = sp->s_port; 143 } 144 145 s = socket(AF_INET, SOCK_STREAM, 0); 146 if (s < 0) { 147 perror("telnetd: socket");; 148 exit(1); 149 } 150 if (bind(s, &sin, sizeof sin) < 0) { 151 perror("bind"); 152 exit(1); 153 } 154 if (listen(s, 1) < 0) { 155 perror("listen"); 156 exit(1); 157 } 158 foo = sizeof sin; 159 ns = accept(s, &sin, &foo); 160 if (ns < 0) { 161 perror("accept"); 162 exit(1); 163 } 164 dup2(ns, 0); 165 close(s); 166 } 167 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 168 fromlen = sizeof (from); 169 if (getpeername(0, &from, &fromlen) < 0) { 170 fprintf(stderr, "%s: ", argv[0]); 171 perror("getpeername"); 172 _exit(1); 173 } 174 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { 175 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 176 } 177 doit(0, &from); 178 } 179 180 char *terminaltype = 0; 181 char *envinit[2]; 182 int cleanup(); 183 184 /* 185 * ttloop 186 * 187 * A small subroutine to flush the network output buffer, get some data 188 * from the network, and pass it through the telnet state machine. We 189 * also flush the pty input buffer (by dropping its data) if it becomes 190 * too full. 191 */ 192 193 void 194 ttloop() 195 { 196 if (nfrontp-nbackp) { 197 netflush(); 198 } 199 ncc = read(net, netibuf, sizeof netibuf); 200 if (ncc < 0) { 201 syslog(LOG_INFO, "ttloop: read: %m\n"); 202 exit(1); 203 } else if (ncc == 0) { 204 syslog(LOG_INFO, "ttloop: peer died: %m\n"); 205 exit(1); 206 } 207 netip = netibuf; 208 telrcv(); /* state machine */ 209 if (ncc > 0) { 210 pfrontp = pbackp = ptyobuf; 211 telrcv(); 212 } 213 } 214 215 /* 216 * getterminalspeed 217 * 218 * Ask the other end to send along its terminal speed. 219 * subopt does the rest. 220 */ 221 222 void 223 getterminalspeed() 224 { 225 static char sbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; 226 227 bcopy(sbuf, nfrontp, sizeof sbuf); 228 nfrontp += sizeof sbuf; 229 } 230 231 /* 232 * getterminaltype 233 * 234 * Ask the other end to send along its terminal type. 235 * Output is the variable terminaltype filled in. 236 */ 237 238 void 239 getterminaltype() 240 { 241 static char sbuf[] = { IAC, DO, TELOPT_TTYPE }; 242 243 settimer(getterminal); 244 bcopy(sbuf, nfrontp, sizeof sbuf); 245 nfrontp += sizeof sbuf; 246 hisopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK; 247 while (sequenceIs(ttypeopt, getterminal)) { 248 ttloop(); 249 } 250 if (hisopts[TELOPT_TTYPE] == OPT_YES) { 251 static char sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE }; 252 253 bcopy(sbbuf, nfrontp, sizeof sbbuf); 254 nfrontp += sizeof sbbuf; 255 while (sequenceIs(ttypesubopt, getterminal)) { 256 ttloop(); 257 } 258 } 259 } 260 261 /* 262 * Get a pty, scan input lines. 263 */ 264 doit(f, who) 265 int f; 266 struct sockaddr_in *who; 267 { 268 char *host, *inet_ntoa(); 269 int i, p, t; 270 struct sgttyb b; 271 struct hostent *hp; 272 int c; 273 274 for (c = 'p'; c <= 's'; c++) { 275 struct stat stb; 276 277 line = "/dev/ptyXX"; 278 line[strlen("/dev/pty")] = c; 279 line[strlen("/dev/ptyp")] = '0'; 280 if (stat(line, &stb) < 0) 281 break; 282 for (i = 0; i < 16; i++) { 283 line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 284 p = open(line, O_RDWR); 285 if (p > 0) 286 goto gotpty; 287 } 288 } 289 fatal(f, "All network ports in use"); 290 /*NOTREACHED*/ 291 gotpty: 292 dup2(f, 0); 293 line[strlen("/dev/")] = 't'; 294 t = open(_PATH_TTY, O_RDWR); 295 if (t >= 0) { 296 ioctl(t, TIOCNOTTY, 0); 297 close(t); 298 } 299 t = open(line, O_RDWR); 300 if (t < 0) 301 fatalperror(f, line); 302 if (fchmod(t, 0)) 303 fatalperror(f, line); 304 (void)signal(SIGHUP, SIG_IGN); 305 vhangup(); 306 (void)signal(SIGHUP, SIG_DFL); 307 t = open(line, O_RDWR); 308 if (t < 0) 309 fatalperror(f, line); 310 ioctl(t, TIOCGETP, &b); 311 b.sg_flags = CRMOD|XTABS|ANYP; 312 ioctl(t, TIOCSETP, &b); 313 ioctl(p, TIOCGETP, &b); 314 b.sg_flags &= ~ECHO; 315 b.sg_ospeed = b.sg_ispeed = B9600; 316 ioctl(p, TIOCSETP, &b); 317 hp = gethostbyaddr(&who->sin_addr, sizeof (struct in_addr), 318 who->sin_family); 319 if (hp) 320 host = hp->h_name; 321 else 322 host = inet_ntoa(who->sin_addr); 323 324 net = f; 325 pty = p; 326 327 /* 328 * get terminal type and size. 329 */ 330 getterminaltype(); 331 332 if ((i = fork()) < 0) 333 fatalperror(f, "fork"); 334 if (i) { 335 close(t); 336 telnet(f, p); 337 } 338 if (setsid() < 0) 339 fatalperror(f, "setsid"); 340 if (ioctl(t, TIOCSCTTY, 0) < 0) 341 fatalperror(f, "ioctl(sctty)"); 342 close(f); 343 close(p); 344 dup2(t, 0); 345 dup2(t, 1); 346 dup2(t, 2); 347 close(t); 348 envinit[0] = terminaltype; 349 envinit[1] = 0; 350 environ = envinit; 351 /* 352 * -h : pass on name of host. 353 * WARNING: -h is accepted by login if and only if 354 * getuid() == 0. 355 * -p : don't clobber the environment (so terminal type stays set). 356 */ 357 execl(_PATH_LOGIN, "login", "-h", host, 358 terminaltype ? "-p" : 0, 0); 359 syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 360 fatalperror(2, _PATH_LOGIN); 361 /*NOTREACHED*/ 362 } 363 364 fatal(f, msg) 365 int f; 366 char *msg; 367 { 368 char buf[BUFSIZ]; 369 370 (void) sprintf(buf, "telnetd: %s.\r\n", msg); 371 (void) write(f, buf, strlen(buf)); 372 exit(1); 373 } 374 375 fatalperror(f, msg) 376 int f; 377 char *msg; 378 { 379 char buf[BUFSIZ]; 380 extern char *sys_errlist[]; 381 382 (void) sprintf(buf, "%s: %s\r\n", msg, sys_errlist[errno]); 383 fatal(f, buf); 384 } 385 386 387 /* 388 * Check a descriptor to see if out of band data exists on it. 389 */ 390 391 392 stilloob(s) 393 int s; /* socket number */ 394 { 395 static struct timeval timeout = { 0 }; 396 fd_set excepts; 397 int value; 398 399 do { 400 FD_ZERO(&excepts); 401 FD_SET(s, &excepts); 402 value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); 403 } while ((value == -1) && (errno == EINTR)); 404 405 if (value < 0) { 406 fatalperror(pty, "select"); 407 } 408 if (FD_ISSET(s, &excepts)) { 409 return 1; 410 } else { 411 return 0; 412 } 413 } 414 415 /* 416 * Main loop. Select from pty and network, and 417 * hand data to telnet receiver finite state machine. 418 */ 419 telnet(f, p) 420 { 421 int on = 1; 422 char hostname[MAXHOSTNAMELEN]; 423 #define TABBUFSIZ 512 424 char defent[TABBUFSIZ]; 425 char defstrs[TABBUFSIZ]; 426 #undef TABBUFSIZ 427 char *HE; 428 char *HN; 429 char *IM; 430 431 ioctl(f, FIONBIO, &on); 432 ioctl(p, FIONBIO, &on); 433 ioctl(p, TIOCPKT, &on); 434 #if defined(SO_OOBINLINE) 435 setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on); 436 #endif /* defined(SO_OOBINLINE) */ 437 signal(SIGTSTP, SIG_IGN); 438 /* 439 * Ignoring SIGTTOU keeps the kernel from blocking us 440 * in ttioctl() in /sys/tty.c. 441 */ 442 signal(SIGTTOU, SIG_IGN); 443 signal(SIGCHLD, cleanup); 444 setpgrp(0, 0); 445 446 /* 447 * Request to do remote echo and to suppress go ahead. 448 */ 449 if (!myopts[TELOPT_ECHO]) { 450 dooption(TELOPT_ECHO); 451 } 452 if (!myopts[TELOPT_SGA]) { 453 dooption(TELOPT_SGA); 454 } 455 if (!hisopts[TELOPT_NAWS]) { 456 willoption(TELOPT_NAWS); 457 hisopts[TELOPT_NAWS] = OPT_NO; 458 } 459 if (!hisopts[TELOPT_TSPEED]) { 460 willoption(TELOPT_TSPEED); 461 hisopts[TELOPT_TSPEED] = OPT_NO; 462 } 463 if (!hisopts[TELOPT_LFLOW]) { 464 willoption(TELOPT_LFLOW); 465 hisopts[TELOPT_LFLOW] = OPT_NO; 466 } 467 468 /* 469 * Is the client side a 4.2 (NOT 4.3) system? We need to know this 470 * because 4.2 clients are unable to deal with TCP urgent data. 471 * 472 * To find out, we send out a "DO ECHO". If the remote system 473 * answers "WILL ECHO" it is probably a 4.2 client, and we note 474 * that fact ("WILL ECHO" ==> that the client will echo what 475 * WE, the server, sends it; it does NOT mean that the client will 476 * echo the terminal input). 477 */ 478 (void) sprintf(nfrontp, doopt, TELOPT_ECHO); 479 nfrontp += sizeof doopt-2; 480 hisopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK; 481 482 /* 483 * Show banner that getty never gave. 484 * 485 * We put the banner in the pty input buffer. This way, it 486 * gets carriage return null processing, etc., just like all 487 * other pty --> client data. 488 */ 489 490 gethostname(hostname, sizeof (hostname)); 491 if (getent(defent, "default") == 1) { 492 char *getstr(); 493 char *p=defstrs; 494 495 HE = getstr("he", &p); 496 HN = getstr("hn", &p); 497 IM = getstr("im", &p); 498 if (HN && *HN) 499 strcpy(hostname, HN); 500 edithost(HE, hostname); 501 if (IM && *IM) 502 putf(IM, ptyibuf+1); 503 } else { 504 sprintf(ptyibuf+1, BANNER, hostname); 505 } 506 507 ptyip = ptyibuf+1; /* Prime the pump */ 508 pcc = strlen(ptyip); /* ditto */ 509 510 /* Clear ptybuf[0] - where the packet information is received */ 511 ptyibuf[0] = 0; 512 513 /* 514 * Call telrcv() once to pick up anything received during 515 * terminal type negotiation. 516 */ 517 telrcv(); 518 519 for (;;) { 520 fd_set ibits, obits, xbits; 521 register int c; 522 523 if (ncc < 0 && pcc < 0) 524 break; 525 526 FD_ZERO(&ibits); 527 FD_ZERO(&obits); 528 FD_ZERO(&xbits); 529 /* 530 * Never look for input if there's still 531 * stuff in the corresponding output buffer 532 */ 533 if (nfrontp - nbackp || pcc > 0) { 534 FD_SET(f, &obits); 535 } else { 536 FD_SET(p, &ibits); 537 } 538 if (pfrontp - pbackp || ncc > 0) { 539 FD_SET(p, &obits); 540 } else { 541 FD_SET(f, &ibits); 542 } 543 if (!SYNCHing) { 544 FD_SET(f, &xbits); 545 } 546 FD_SET(p, &xbits); 547 if ((c = select(16, &ibits, &obits, &xbits, 548 (struct timeval *)0)) < 1) { 549 if (c == -1) { 550 if (errno == EINTR) { 551 continue; 552 } 553 } 554 sleep(5); 555 continue; 556 } 557 558 /* 559 * Any urgent data? 560 */ 561 if (FD_ISSET(net, &xbits)) { 562 SYNCHing = 1; 563 } 564 565 /* 566 * Something to read from the network... 567 */ 568 if (FD_ISSET(net, &ibits)) { 569 #if !defined(SO_OOBINLINE) 570 /* 571 * In 4.2 (and 4.3 beta) systems, the 572 * OOB indication and data handling in the kernel 573 * is such that if two separate TCP Urgent requests 574 * come in, one byte of TCP data will be overlaid. 575 * This is fatal for Telnet, but we try to live 576 * with it. 577 * 578 * In addition, in 4.2 (and...), a special protocol 579 * is needed to pick up the TCP Urgent data in 580 * the correct sequence. 581 * 582 * What we do is: if we think we are in urgent 583 * mode, we look to see if we are "at the mark". 584 * If we are, we do an OOB receive. If we run 585 * this twice, we will do the OOB receive twice, 586 * but the second will fail, since the second 587 * time we were "at the mark", but there wasn't 588 * any data there (the kernel doesn't reset 589 * "at the mark" until we do a normal read). 590 * Once we've read the OOB data, we go ahead 591 * and do normal reads. 592 * 593 * There is also another problem, which is that 594 * since the OOB byte we read doesn't put us 595 * out of OOB state, and since that byte is most 596 * likely the TELNET DM (data mark), we would 597 * stay in the TELNET SYNCH (SYNCHing) state. 598 * So, clocks to the rescue. If we've "just" 599 * received a DM, then we test for the 600 * presence of OOB data when the receive OOB 601 * fails (and AFTER we did the normal mode read 602 * to clear "at the mark"). 603 */ 604 if (SYNCHing) { 605 int atmark; 606 607 ioctl(net, SIOCATMARK, (char *)&atmark); 608 if (atmark) { 609 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); 610 if ((ncc == -1) && (errno == EINVAL)) { 611 ncc = read(net, netibuf, sizeof (netibuf)); 612 if (sequenceIs(didnetreceive, gotDM)) { 613 SYNCHing = stilloob(net); 614 } 615 } 616 } else { 617 ncc = read(net, netibuf, sizeof (netibuf)); 618 } 619 } else { 620 ncc = read(net, netibuf, sizeof (netibuf)); 621 } 622 settimer(didnetreceive); 623 #else /* !defined(SO_OOBINLINE)) */ 624 ncc = read(net, netibuf, sizeof (netibuf)); 625 #endif /* !defined(SO_OOBINLINE)) */ 626 if (ncc < 0 && errno == EWOULDBLOCK) 627 ncc = 0; 628 else { 629 if (ncc <= 0) { 630 break; 631 } 632 netip = netibuf; 633 } 634 } 635 636 /* 637 * Something to read from the pty... 638 */ 639 if (FD_ISSET(p, &ibits) || FD_ISSET(p, &xbits)) { 640 pcc = read(p, ptyibuf, BUFSIZ); 641 if (pcc < 0 && errno == EWOULDBLOCK) 642 pcc = 0; 643 else { 644 if (pcc <= 0) 645 break; 646 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { 647 netclear(); /* clear buffer back */ 648 *nfrontp++ = IAC; 649 *nfrontp++ = DM; 650 neturg = nfrontp-1; /* off by one XXX */ 651 } 652 if (hisopts[TELOPT_LFLOW] && 653 (ptyibuf[0] & 654 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { 655 sprintf(nfrontp,"%c%c%c%c%c%c", 656 IAC, SB, TELOPT_LFLOW, 657 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0, 658 IAC, SE); 659 nfrontp += 6; 660 } 661 pcc--; 662 ptyip = ptyibuf+1; 663 } 664 } 665 666 while (pcc > 0) { 667 if ((&netobuf[BUFSIZ] - nfrontp) < 2) 668 break; 669 c = *ptyip++ & 0377, pcc--; 670 if (c == IAC) 671 *nfrontp++ = c; 672 *nfrontp++ = c; 673 /* Don't do CR-NUL if we are in binary mode */ 674 if ((c == '\r') && (myopts[TELOPT_BINARY] == OPT_NO)) { 675 if (pcc > 0 && ((*ptyip & 0377) == '\n')) { 676 *nfrontp++ = *ptyip++ & 0377; 677 pcc--; 678 } else 679 *nfrontp++ = '\0'; 680 } 681 } 682 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) 683 netflush(); 684 if (ncc > 0) 685 telrcv(); 686 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) 687 ptyflush(); 688 } 689 cleanup(); 690 } 691 692 /* 693 * State for recv fsm 694 */ 695 #define TS_DATA 0 /* base state */ 696 #define TS_IAC 1 /* look for double IAC's */ 697 #define TS_CR 2 /* CR-LF ->'s CR */ 698 #define TS_SB 3 /* throw away begin's... */ 699 #define TS_SE 4 /* ...end's (suboption negotiation) */ 700 #define TS_WILL 5 /* will option negotiation */ 701 #define TS_WONT 6 /* wont " */ 702 #define TS_DO 7 /* do " */ 703 #define TS_DONT 8 /* dont " */ 704 705 telrcv() 706 { 707 register int c; 708 static int state = TS_DATA; 709 710 while (ncc > 0) { 711 if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) 712 return; 713 c = *netip++ & 0377, ncc--; 714 switch (state) { 715 716 case TS_CR: 717 state = TS_DATA; 718 /* Strip off \n or \0 after a \r */ 719 if ((c == 0) || (c == '\n')) { 720 break; 721 } 722 /* FALL THROUGH */ 723 724 case TS_DATA: 725 if (c == IAC) { 726 state = TS_IAC; 727 break; 728 } 729 if (inter > 0) 730 break; 731 /* 732 * We now map \r\n ==> \r for pragmatic reasons. 733 * Many client implementations send \r\n when 734 * the user hits the CarriageReturn key. 735 * 736 * We USED to map \r\n ==> \n, since \r\n says 737 * that we want to be in column 1 of the next 738 * printable line, and \n is the standard 739 * unix way of saying that (\r is only good 740 * if CRMOD is set, which it normally is). 741 */ 742 if ((c == '\r') && (hisopts[TELOPT_BINARY] == OPT_NO)) { 743 state = TS_CR; 744 } 745 *pfrontp++ = c; 746 break; 747 748 case TS_IAC: 749 switch (c) { 750 751 /* 752 * Send the process on the pty side an 753 * interrupt. Do this with a NULL or 754 * interrupt char; depending on the tty mode. 755 */ 756 case IP: 757 interrupt(); 758 break; 759 760 case BREAK: 761 sendbrk(); 762 break; 763 764 /* 765 * Are You There? 766 */ 767 case AYT: 768 strcpy(nfrontp, "\r\n[Yes]\r\n"); 769 nfrontp += 9; 770 break; 771 772 /* 773 * Abort Output 774 */ 775 case AO: { 776 struct ltchars tmpltc; 777 778 ptyflush(); /* half-hearted */ 779 ioctl(pty, TIOCGLTC, &tmpltc); 780 if (tmpltc.t_flushc != '\377') { 781 *pfrontp++ = tmpltc.t_flushc; 782 } 783 netclear(); /* clear buffer back */ 784 *nfrontp++ = IAC; 785 *nfrontp++ = DM; 786 neturg = nfrontp-1; /* off by one XXX */ 787 break; 788 } 789 790 /* 791 * Erase Character and 792 * Erase Line 793 */ 794 case EC: 795 case EL: { 796 struct sgttyb b; 797 char ch; 798 799 ptyflush(); /* half-hearted */ 800 ioctl(pty, TIOCGETP, &b); 801 ch = (c == EC) ? 802 b.sg_erase : b.sg_kill; 803 if (ch != '\377') { 804 *pfrontp++ = ch; 805 } 806 break; 807 } 808 809 /* 810 * Check for urgent data... 811 */ 812 case DM: 813 SYNCHing = stilloob(net); 814 settimer(gotDM); 815 break; 816 817 818 /* 819 * Begin option subnegotiation... 820 */ 821 case SB: 822 state = TS_SB; 823 SB_CLEAR(); 824 continue; 825 826 case WILL: 827 state = TS_WILL; 828 continue; 829 830 case WONT: 831 state = TS_WONT; 832 continue; 833 834 case DO: 835 state = TS_DO; 836 continue; 837 838 case DONT: 839 state = TS_DONT; 840 continue; 841 842 case IAC: 843 *pfrontp++ = c; 844 break; 845 } 846 state = TS_DATA; 847 break; 848 849 case TS_SB: 850 if (c == IAC) { 851 state = TS_SE; 852 } else { 853 SB_ACCUM(c); 854 } 855 break; 856 857 case TS_SE: 858 if (c != SE) { 859 if (c != IAC) { 860 SB_ACCUM(IAC); 861 } 862 SB_ACCUM(c); 863 state = TS_SB; 864 } else { 865 SB_TERM(); 866 suboption(); /* handle sub-option */ 867 state = TS_DATA; 868 } 869 break; 870 871 case TS_WILL: 872 if (hisopts[c] != OPT_YES) 873 willoption(c); 874 state = TS_DATA; 875 if (c == TELOPT_TSPEED) 876 getterminalspeed(); 877 continue; 878 879 case TS_WONT: 880 if (hisopts[c] != OPT_NO) 881 wontoption(c); 882 state = TS_DATA; 883 continue; 884 885 case TS_DO: 886 if (myopts[c] != OPT_YES) 887 dooption(c); 888 state = TS_DATA; 889 continue; 890 891 case TS_DONT: 892 if (myopts[c] != OPT_NO) { 893 dontoption(c); 894 } 895 state = TS_DATA; 896 continue; 897 898 default: 899 syslog(LOG_ERR, "telnetd: panic state=%d\n", state); 900 printf("telnetd: panic state=%d\n", state); 901 exit(1); 902 } 903 } 904 } 905 906 willoption(option) 907 int option; 908 { 909 char *fmt; 910 911 switch (option) { 912 913 case TELOPT_BINARY: 914 mode(RAW, 0); 915 fmt = doopt; 916 break; 917 918 case TELOPT_ECHO: 919 not42 = 0; /* looks like a 4.2 system */ 920 /* 921 * Now, in a 4.2 system, to break them out of ECHOing 922 * (to the terminal) mode, we need to send a "WILL ECHO". 923 * Kludge upon kludge! 924 */ 925 if (myopts[TELOPT_ECHO] == OPT_YES) { 926 dooption(TELOPT_ECHO); 927 } 928 fmt = dont; 929 break; 930 931 case TELOPT_TTYPE: 932 settimer(ttypeopt); 933 if (hisopts[TELOPT_TTYPE] == OPT_YES_BUT_ALWAYS_LOOK) { 934 hisopts[TELOPT_TTYPE] = OPT_YES; 935 return; 936 } 937 fmt = doopt; 938 break; 939 940 case TELOPT_NAWS: 941 case TELOPT_TSPEED: 942 case TELOPT_LFLOW: 943 case TELOPT_SGA: 944 fmt = doopt; 945 break; 946 947 case TELOPT_TM: 948 fmt = dont; 949 break; 950 951 default: 952 fmt = dont; 953 break; 954 } 955 if (fmt == doopt) { 956 hisopts[option] = OPT_YES; 957 } else { 958 hisopts[option] = OPT_NO; 959 } 960 (void) sprintf(nfrontp, fmt, option); 961 nfrontp += sizeof (dont) - 2; 962 } 963 964 wontoption(option) 965 int option; 966 { 967 char *fmt; 968 969 switch (option) { 970 case TELOPT_ECHO: 971 not42 = 1; /* doesn't seem to be a 4.2 system */ 972 break; 973 974 case TELOPT_BINARY: 975 mode(0, RAW); 976 break; 977 978 case TELOPT_TTYPE: 979 settimer(ttypeopt); 980 break; 981 } 982 983 fmt = dont; 984 hisopts[option] = OPT_NO; 985 (void) sprintf(nfrontp, fmt, option); 986 nfrontp += sizeof (doopt) - 2; 987 } 988 989 dooption(option) 990 int option; 991 { 992 char *fmt; 993 994 switch (option) { 995 996 case TELOPT_TM: 997 fmt = wont; 998 break; 999 1000 case TELOPT_ECHO: 1001 mode(ECHO|CRMOD, 0); 1002 fmt = will; 1003 break; 1004 1005 case TELOPT_BINARY: 1006 mode(RAW, 0); 1007 fmt = will; 1008 break; 1009 1010 case TELOPT_SGA: 1011 fmt = will; 1012 break; 1013 1014 default: 1015 fmt = wont; 1016 break; 1017 } 1018 if (fmt == will) { 1019 myopts[option] = OPT_YES; 1020 } else { 1021 myopts[option] = OPT_NO; 1022 } 1023 (void) sprintf(nfrontp, fmt, option); 1024 nfrontp += sizeof (doopt) - 2; 1025 } 1026 1027 1028 dontoption(option) 1029 int option; 1030 { 1031 char *fmt; 1032 1033 switch (option) { 1034 case TELOPT_ECHO: /* we should stop echoing */ 1035 mode(0, ECHO); 1036 fmt = wont; 1037 break; 1038 1039 default: 1040 fmt = wont; 1041 break; 1042 } 1043 1044 if (fmt = wont) { 1045 myopts[option] = OPT_NO; 1046 } else { 1047 myopts[option] = OPT_YES; 1048 } 1049 (void) sprintf(nfrontp, fmt, option); 1050 nfrontp += sizeof (wont) - 2; 1051 } 1052 1053 /* 1054 * Given a string, assign the "best" speed which we support. 1055 * 1056 * "Best" is defined as rounding up, unless what is presented is 1057 * higher than the highest. 1058 */ 1059 1060 string2speed(s) 1061 char *s; 1062 { 1063 /* 1064 * The order here is important. The index of each speed needs to 1065 * correspond with the sgtty structure value for that speed. 1066 * 1067 * Additionally, the search algorithm assumes the table is in 1068 * ascending sequence. 1069 */ 1070 static int ttyspeeds[] = { 1071 0, 50, 75, 110, 134, 150, 200, 300, 1072 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 }; 1073 #define NUMSPEEDS sizeof ttyspeeds/sizeof ttyspeeds[0] 1074 int i; 1075 int theirspeed = atoi(s); 1076 1077 for (i = 0; i < NUMSPEEDS; i++) { 1078 if (ttyspeeds[i] == theirspeed) { /* Exact match */ 1079 return(i); 1080 } else if (ttyspeeds[i] > theirspeed) { 1081 if (i > 0) { 1082 return i-1; 1083 } 1084 } 1085 } 1086 /* Their number is greater than any of our numbers */ 1087 return(NUMSPEEDS-1); 1088 } 1089 1090 /* 1091 * suboption() 1092 * 1093 * Look at the sub-option buffer, and try to be helpful to the other 1094 * side. 1095 * 1096 * Currently we recognize: 1097 * 1098 * Terminal type is 1099 * Terminal size 1100 * Terminal speed is 1101 */ 1102 1103 suboption() 1104 { 1105 switch (SB_GET()) { 1106 case TELOPT_TTYPE: { /* Yaaaay! */ 1107 static char terminalname[5+41] = "TERM="; 1108 1109 settimer(ttypesubopt); 1110 1111 if (SB_GET() != TELQUAL_IS) { 1112 return; /* ??? XXX but, this is the most robust */ 1113 } 1114 1115 terminaltype = terminalname+strlen(terminalname); 1116 1117 while ((terminaltype < (terminalname + sizeof terminalname-1)) && 1118 !SB_EOF()) { 1119 register int c; 1120 1121 c = SB_GET(); 1122 if (isupper(c)) { 1123 c = tolower(c); 1124 } 1125 *terminaltype++ = c; /* accumulate name */ 1126 } 1127 *terminaltype = 0; 1128 terminaltype = terminalname; 1129 break; 1130 } 1131 case TELOPT_NAWS: { 1132 struct winsize win; 1133 1134 ioctl(pty, TIOCGWINSZ, &win); 1135 settimer(ttypesubopt); 1136 1137 syslog(LOG_INFO, "%x %x %x %x", 1138 subpointer[0],subpointer[1],subpointer[2],subpointer[3]); 1139 win.ws_col = SB_GET() << 8; 1140 win.ws_col |= SB_GET(); 1141 win.ws_row = SB_GET() << 8; 1142 win.ws_row |= SB_GET(); 1143 syslog(LOG_INFO, "col %d row %d", win.ws_col, win.ws_row); 1144 ioctl(pty, TIOCSWINSZ, &win); 1145 break; 1146 } 1147 case TELOPT_TSPEED: { 1148 char speeds[41],*cp=speeds; 1149 struct sgttyb b; 1150 int ispeed,ospeed; 1151 char *ispeeds,*ospeeds; 1152 1153 if (SB_GET() != TELQUAL_IS) { 1154 return; /* ??? XXX but, this is the most robust */ 1155 } 1156 1157 ispeeds = NULL; 1158 ospeeds = speeds; 1159 ispeed = 0; 1160 ospeed = 0; 1161 while ((cp < (speeds + sizeof speeds-1)) && !SB_EOF()) { 1162 register int c; 1163 1164 c = SB_GET(); 1165 if (c == ',') { 1166 c = 0; 1167 ispeeds = cp+1; 1168 } 1169 *cp++ = c; /* accumulate name */ 1170 } 1171 *cp = 0; 1172 1173 if (ispeeds) 1174 ispeed = string2speed(ispeeds); 1175 if (ospeeds) 1176 ospeed = string2speed(ospeeds); 1177 1178 if (ispeed && ospeed) { 1179 ioctl(pty, TIOCGETP, &b); 1180 b.sg_ospeed = ospeed; 1181 b.sg_ispeed = ispeed; 1182 ioctl(pty, TIOCSETP, &b); 1183 } 1184 1185 break; 1186 } 1187 default: 1188 ; 1189 } 1190 } 1191 1192 mode(on, off) 1193 int on, off; 1194 { 1195 struct sgttyb b; 1196 1197 ptyflush(); 1198 ioctl(pty, TIOCGETP, &b); 1199 b.sg_flags |= on; 1200 b.sg_flags &= ~off; 1201 ioctl(pty, TIOCSETP, &b); 1202 } 1203 1204 /* 1205 * Send interrupt to process on other side of pty. 1206 * If it is in raw mode, just write NULL; 1207 * otherwise, write intr char. 1208 */ 1209 interrupt() 1210 { 1211 struct sgttyb b; 1212 struct tchars tchars; 1213 1214 ptyflush(); /* half-hearted */ 1215 ioctl(pty, TIOCGETP, &b); 1216 if (b.sg_flags & RAW) { 1217 *pfrontp++ = '\0'; 1218 return; 1219 } 1220 *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ? 1221 '\177' : tchars.t_intrc; 1222 } 1223 1224 /* 1225 * Send quit to process on other side of pty. 1226 * If it is in raw mode, just write NULL; 1227 * otherwise, write quit char. 1228 */ 1229 sendbrk() 1230 { 1231 struct sgttyb b; 1232 struct tchars tchars; 1233 1234 ptyflush(); /* half-hearted */ 1235 ioctl(pty, TIOCGETP, &b); 1236 if (b.sg_flags & RAW) { 1237 *pfrontp++ = '\0'; 1238 return; 1239 } 1240 *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ? 1241 '\034' : tchars.t_quitc; 1242 } 1243 1244 ptyflush() 1245 { 1246 int n; 1247 1248 if ((n = pfrontp - pbackp) > 0) 1249 n = write(pty, pbackp, n); 1250 if (n < 0) 1251 return; 1252 pbackp += n; 1253 if (pbackp == pfrontp) 1254 pbackp = pfrontp = ptyobuf; 1255 } 1256 1257 /* 1258 * nextitem() 1259 * 1260 * Return the address of the next "item" in the TELNET data 1261 * stream. This will be the address of the next character if 1262 * the current address is a user data character, or it will 1263 * be the address of the character following the TELNET command 1264 * if the current address is a TELNET IAC ("I Am a Command") 1265 * character. 1266 */ 1267 1268 char * 1269 nextitem(current) 1270 char *current; 1271 { 1272 if ((*current&0xff) != IAC) { 1273 return current+1; 1274 } 1275 switch (*(current+1)&0xff) { 1276 case DO: 1277 case DONT: 1278 case WILL: 1279 case WONT: 1280 return current+3; 1281 case SB: /* loop forever looking for the SE */ 1282 { 1283 register char *look = current+2; 1284 1285 for (;;) { 1286 if ((*look++&0xff) == IAC) { 1287 if ((*look++&0xff) == SE) { 1288 return look; 1289 } 1290 } 1291 } 1292 } 1293 default: 1294 return current+2; 1295 } 1296 } 1297 1298 1299 /* 1300 * netclear() 1301 * 1302 * We are about to do a TELNET SYNCH operation. Clear 1303 * the path to the network. 1304 * 1305 * Things are a bit tricky since we may have sent the first 1306 * byte or so of a previous TELNET command into the network. 1307 * So, we have to scan the network buffer from the beginning 1308 * until we are up to where we want to be. 1309 * 1310 * A side effect of what we do, just to keep things 1311 * simple, is to clear the urgent data pointer. The principal 1312 * caller should be setting the urgent data pointer AFTER calling 1313 * us in any case. 1314 */ 1315 1316 netclear() 1317 { 1318 register char *thisitem, *next; 1319 char *good; 1320 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 1321 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 1322 1323 thisitem = netobuf; 1324 1325 while ((next = nextitem(thisitem)) <= nbackp) { 1326 thisitem = next; 1327 } 1328 1329 /* Now, thisitem is first before/at boundary. */ 1330 1331 good = netobuf; /* where the good bytes go */ 1332 1333 while (nfrontp > thisitem) { 1334 if (wewant(thisitem)) { 1335 int length; 1336 1337 next = thisitem; 1338 do { 1339 next = nextitem(next); 1340 } while (wewant(next) && (nfrontp > next)); 1341 length = next-thisitem; 1342 bcopy(thisitem, good, length); 1343 good += length; 1344 thisitem = next; 1345 } else { 1346 thisitem = nextitem(thisitem); 1347 } 1348 } 1349 1350 nbackp = netobuf; 1351 nfrontp = good; /* next byte to be sent */ 1352 neturg = 0; 1353 } 1354 1355 /* 1356 * netflush 1357 * Send as much data as possible to the network, 1358 * handling requests for urgent data. 1359 */ 1360 1361 1362 netflush() 1363 { 1364 int n; 1365 1366 if ((n = nfrontp - nbackp) > 0) { 1367 /* 1368 * if no urgent data, or if the other side appears to be an 1369 * old 4.2 client (and thus unable to survive TCP urgent data), 1370 * write the entire buffer in non-OOB mode. 1371 */ 1372 if ((neturg == 0) || (not42 == 0)) { 1373 n = write(net, nbackp, n); /* normal write */ 1374 } else { 1375 n = neturg - nbackp; 1376 /* 1377 * In 4.2 (and 4.3) systems, there is some question about 1378 * what byte in a sendOOB operation is the "OOB" data. 1379 * To make ourselves compatible, we only send ONE byte 1380 * out of band, the one WE THINK should be OOB (though 1381 * we really have more the TCP philosophy of urgent data 1382 * rather than the Unix philosophy of OOB data). 1383 */ 1384 if (n > 1) { 1385 n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ 1386 } else { 1387 n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ 1388 } 1389 } 1390 } 1391 if (n < 0) { 1392 if (errno == EWOULDBLOCK) 1393 return; 1394 /* should blow this guy away... */ 1395 return; 1396 } 1397 nbackp += n; 1398 if (nbackp >= neturg) { 1399 neturg = 0; 1400 } 1401 if (nbackp == nfrontp) { 1402 nbackp = nfrontp = netobuf; 1403 } 1404 } 1405 1406 cleanup() 1407 { 1408 char *p; 1409 1410 p = line + sizeof("/dev/") - 1; 1411 if (logout(p)) 1412 logwtmp(p, "", ""); 1413 (void)chmod(line, 0666); 1414 (void)chown(line, 0, 0); 1415 *p = 'p'; 1416 (void)chmod(line, 0666); 1417 (void)chown(line, 0, 0); 1418 shutdown(net, 2); 1419 exit(1); 1420 } 1421 1422 char editedhost[32]; 1423 1424 edithost(pat, host) 1425 register char *pat; 1426 register char *host; 1427 { 1428 register char *res = editedhost; 1429 1430 if (!pat) 1431 pat = ""; 1432 while (*pat) { 1433 switch (*pat) { 1434 1435 case '#': 1436 if (*host) 1437 host++; 1438 break; 1439 1440 case '@': 1441 if (*host) 1442 *res++ = *host++; 1443 break; 1444 1445 default: 1446 *res++ = *pat; 1447 break; 1448 1449 } 1450 if (res == &editedhost[sizeof editedhost - 1]) { 1451 *res = '\0'; 1452 return; 1453 } 1454 pat++; 1455 } 1456 if (*host) 1457 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); 1458 else 1459 *res = '\0'; 1460 editedhost[sizeof editedhost - 1] = '\0'; 1461 } 1462 1463 static char *putlocation; 1464 1465 puts(s) 1466 register char *s; 1467 { 1468 1469 while (*s) 1470 putchr(*s++); 1471 } 1472 1473 putchr(cc) 1474 { 1475 *putlocation++ = cc; 1476 } 1477 1478 putf(cp, where) 1479 register char *cp; 1480 char *where; 1481 { 1482 char *slash; 1483 char datebuffer[60]; 1484 extern char *rindex(); 1485 1486 putlocation = where; 1487 1488 while (*cp) { 1489 if (*cp != '%') { 1490 putchr(*cp++); 1491 continue; 1492 } 1493 switch (*++cp) { 1494 1495 case 't': 1496 slash = rindex(line, '/'); 1497 if (slash == (char *) 0) 1498 puts(line); 1499 else 1500 puts(&slash[1]); 1501 break; 1502 1503 case 'h': 1504 puts(editedhost); 1505 break; 1506 1507 case 'd': 1508 get_date(datebuffer); 1509 puts(datebuffer); 1510 break; 1511 1512 case '%': 1513 putchr('%'); 1514 break; 1515 } 1516 cp++; 1517 } 1518 } 1519