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