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