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