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