xref: /haiku/src/bin/network/telnetd/telnetd.c (revision 2600324b57fa31cdea1627d584d314f2a579c4a8)
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 #if 0
35 #ifndef lint
36 static const char sccsid[] = "@(#)telnetd.c	8.4 (Berkeley) 5/30/95";
37 #endif
38 #endif
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD: src/contrib/telnet/telnetd/telnetd.c,v 1.28 2005/05/21 15:28:42 ume Exp $");
41 
42 #include "telnetd.h"
43 #include "pathnames.h"
44 
45 //#include <sys/mman.h>
46 #include <err.h>
47 #include <libutil.h>
48 #include <paths.h>
49 #include <termcap.h>
50 #if (!defined(__BEOS__) && !defined(__HAIKU__))
51 # include <utmp.h>
52 #endif
53 
54 #include <arpa/inet.h>
55 
56 #ifdef	AUTHENTICATION
57 #include <libtelnet/auth.h>
58 int	auth_level = 0;
59 #endif
60 #ifdef	ENCRYPTION
61 #include <libtelnet/encrypt.h>
62 #endif
63 #include <libtelnet/misc.h>
64 
65 char	remote_hostname[MAXHOSTNAMELEN];
66 size_t	utmp_len = sizeof(remote_hostname) - 1;
67 int	registerd_host_only = 0;
68 
69 
70 /*
71  * I/O data buffers,
72  * pointers, and counters.
73  */
74 char	ptyibuf[BUFSIZ], *ptyip = ptyibuf;
75 char	ptyibuf2[BUFSIZ];
76 
77 int readstream(int, char *, int);
78 void doit(struct sockaddr *);
79 int terminaltypeok(char *);
80 
81 int	hostinfo = 1;			/* do we print login banner? */
82 
83 static int debug = 0;
84 int keepalive = 1;
85 const char *altlogin;
86 
87 void doit(struct sockaddr *);
88 int terminaltypeok(char *);
89 void startslave(char *, int, char *);
90 extern void usage(void);
91 static void _gettermname(void);
92 
93 /*
94  * The string to pass to getopt().  We do it this way so
95  * that only the actual options that we support will be
96  * passed off to getopt().
97  */
98 char valid_opts[] = {
99 	'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U',
100 	'4', '6',
101 #ifdef	AUTHENTICATION
102 	'a', ':', 'X', ':',
103 #endif
104 #ifdef BFTPDAEMON
105 	'B',
106 #endif
107 #ifdef DIAGNOSTICS
108 	'D', ':',
109 #endif
110 #ifdef	ENCRYPTION
111 	'e', ':',
112 #endif
113 #ifdef	LINEMODE
114 	'l',
115 #endif
116 	'\0'
117 };
118 
119 int family = AF_INET;
120 
121 #ifndef	MAXHOSTNAMELEN
122 #define	MAXHOSTNAMELEN 256
123 #endif	/* MAXHOSTNAMELEN */
124 
125 char *hostname;
126 char host_name[MAXHOSTNAMELEN];
127 
128 extern void telnet(int, int, char *);
129 
130 int level;
131 char user_name[256];
132 
133 int
134 main(int argc, char *argv[])
135 {
136 	struct sockaddr_storage from;
137 	int on = 1, fromlen;
138 	int ch;
139 #if (!defined(__BEOS__) && !defined(__HAIKU__))
140 	u_long ultmp;
141 	char *ep;
142 #endif
143 #if	defined(IPPROTO_IP) && defined(IP_TOS)
144 	int tos = -1;
145 #endif
146 
147 	pfrontp = pbackp = ptyobuf;
148 	netip = netibuf;
149 	nfrontp = nbackp = netobuf;
150 #ifdef	ENCRYPTION
151 	nclearto = 0;
152 #endif	/* ENCRYPTION */
153 
154 	/*
155 	 * This initialization causes linemode to default to a configuration
156 	 * that works on all telnet clients, including the FreeBSD client.
157 	 * This is not quite the same as the telnet client issuing a "mode
158 	 * character" command, but has most of the same benefits, and is
159 	 * preferable since some clients (like usofts) don't have the
160 	 * mode character command anyway and linemode breaks things.
161 	 * The most notable symptom of fix is that csh "set filec" operations
162 	 * like <ESC> (filename completion) and ^D (choices) keys now work
163 	 * in telnet sessions and can be used more than once on the same line.
164 	 * CR/LF handling is also corrected in some termio modes.  This
165 	 * change resolves problem reports bin/771 and bin/1037.
166 	 */
167 
168 	linemode=1;	/*Default to mode that works on bulk of clients*/
169 
170 	while ((ch = getopt(argc, argv, valid_opts)) != -1) {
171 		switch(ch) {
172 
173 #ifdef	AUTHENTICATION
174 		case 'a':
175 			/*
176 			 * Check for required authentication level
177 			 */
178 			if (strcmp(optarg, "debug") == 0) {
179 				extern int auth_debug_mode;
180 				auth_debug_mode = 1;
181 			} else if (strcasecmp(optarg, "none") == 0) {
182 				auth_level = 0;
183 			} else if (strcasecmp(optarg, "other") == 0) {
184 				auth_level = AUTH_OTHER;
185 			} else if (strcasecmp(optarg, "user") == 0) {
186 				auth_level = AUTH_USER;
187 			} else if (strcasecmp(optarg, "valid") == 0) {
188 				auth_level = AUTH_VALID;
189 			} else if (strcasecmp(optarg, "off") == 0) {
190 				/*
191 				 * This hack turns off authentication
192 				 */
193 				auth_level = -1;
194 			} else {
195 				warnx("unknown authorization level for -a");
196 			}
197 			break;
198 #endif	/* AUTHENTICATION */
199 
200 #ifdef BFTPDAEMON
201 		case 'B':
202 			bftpd++;
203 			break;
204 #endif /* BFTPDAEMON */
205 
206 		case 'd':
207 			if (strcmp(optarg, "ebug") == 0) {
208 				debug++;
209 				break;
210 			}
211 			usage();
212 			/* NOTREACHED */
213 			break;
214 
215 #ifdef DIAGNOSTICS
216 		case 'D':
217 			/*
218 			 * Check for desired diagnostics capabilities.
219 			 */
220 			if (!strcmp(optarg, "report")) {
221 				diagnostic |= TD_REPORT|TD_OPTIONS;
222 			} else if (!strcmp(optarg, "exercise")) {
223 				diagnostic |= TD_EXERCISE;
224 			} else if (!strcmp(optarg, "netdata")) {
225 				diagnostic |= TD_NETDATA;
226 			} else if (!strcmp(optarg, "ptydata")) {
227 				diagnostic |= TD_PTYDATA;
228 			} else if (!strcmp(optarg, "options")) {
229 				diagnostic |= TD_OPTIONS;
230 			} else {
231 				usage();
232 				/* NOT REACHED */
233 			}
234 			break;
235 #endif /* DIAGNOSTICS */
236 
237 #ifdef	ENCRYPTION
238 		case 'e':
239 			if (strcmp(optarg, "debug") == 0) {
240 				extern int encrypt_debug_mode;
241 				encrypt_debug_mode = 1;
242 				break;
243 			}
244 			usage();
245 			/* NOTREACHED */
246 			break;
247 #endif	/* ENCRYPTION */
248 
249 		case 'h':
250 			hostinfo = 0;
251 			break;
252 
253 #ifdef	LINEMODE
254 		case 'l':
255 			alwayslinemode = 1;
256 			break;
257 #endif	/* LINEMODE */
258 
259 		case 'k':
260 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
261 			lmodetype = NO_AUTOKLUDGE;
262 #else
263 			/* ignore -k option if built without kludge linemode */
264 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
265 			break;
266 
267 		case 'n':
268 			keepalive = 0;
269 			break;
270 
271 		case 'p':
272 			altlogin = optarg;
273 			break;
274 
275 		case 'S':
276 #if (defined(__BEOS__) || defined(__HAIKU__))
277 			fprintf(stderr, "-S option is not supported\n");
278 #else
279 # ifdef	HAS_GETTOS
280 			if ((tos = parsetos(optarg, "tcp")) < 0)
281 				warnx("%s%s%s",
282 					"bad TOS argument '", optarg,
283 					"'; will try to use default TOS");
284 # else
285 # define	MAXTOS	255
286 			ultmp = strtoul(optarg, &ep, 0);
287 			if (*ep || ep == optarg || ultmp > MAXTOS)
288 				warnx("%s%s%s",
289 					"bad TOS argument '", optarg,
290 					"'; will try to use default TOS");
291 			else
292 				tos = ultmp;
293 # endif
294 #endif	/* !__BEOS__ */
295 			break;
296 
297 		case 'u':
298 			utmp_len = (size_t)atoi(optarg);
299 			if (utmp_len >= sizeof(remote_hostname))
300 				utmp_len = sizeof(remote_hostname) - 1;
301 			break;
302 
303 		case 'U':
304 			registerd_host_only = 1;
305 			break;
306 
307 #ifdef	AUTHENTICATION
308 		case 'X':
309 			/*
310 			 * Check for invalid authentication types
311 			 */
312 			auth_disable_name(optarg);
313 			break;
314 #endif	/* AUTHENTICATION */
315 
316 		case '4':
317 			family = AF_INET;
318 			break;
319 
320 #ifdef INET6
321 		case '6':
322 			family = AF_INET6;
323 			break;
324 #endif
325 
326 		default:
327 			warnx("%c: unknown option", ch);
328 			/* FALLTHROUGH */
329 		case '?':
330 			usage();
331 			/* NOTREACHED */
332 		}
333 	}
334 
335 	argc -= optind;
336 	argv += optind;
337 
338 	if (debug) {
339 	    int s, ns, foo, error;
340 	    const char *service = "telnet";
341 	    struct addrinfo hints, *res;
342 
343 	    if (argc > 1) {
344 		usage();
345 		/* NOT REACHED */
346 	    } else if (argc == 1)
347 		service = *argv;
348 
349 	    memset(&hints, 0, sizeof(hints));
350 	    hints.ai_flags = AI_PASSIVE;
351 	    hints.ai_family = family;
352 	    hints.ai_socktype = SOCK_STREAM;
353 	    hints.ai_protocol = 0;
354 	    error = getaddrinfo(NULL, service, &hints, &res);
355 
356 	    if (error) {
357 		errx(1, "tcp/%s: %s\n", service, gai_strerror(error));
358 		if (error == EAI_SYSTEM)
359 		    errx(1, "tcp/%s: %s\n", service, strerror(errno));
360 		usage();
361 	    }
362 
363 	    s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
364 	    if (s < 0)
365 		    err(1, "socket");
366 	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
367 				(char *)&on, sizeof(on));
368 	    if (debug > 1)
369 	        (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
370 				(char *)&on, sizeof(on));
371 	    if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
372 		err(1, "bind");
373 	    if (listen(s, 1) < 0)
374 		err(1, "listen");
375 	    foo = res->ai_addrlen;
376 	    ns = accept(s, res->ai_addr, &foo);
377 	    if (ns < 0)
378 		err(1, "accept");
379 	    (void) setsockopt(ns, SOL_SOCKET, SO_DEBUG,
380 				(char *)&on, sizeof(on));
381 	    (void) dup2(ns, 0);
382 	    (void) close(ns);
383 	    (void) close(s);
384 #ifdef convex
385 	} else if (argc == 1) {
386 		; /* VOID*/		/* Just ignore the host/port name */
387 #endif
388 	} else if (argc > 0) {
389 		usage();
390 		/* NOT REACHED */
391 	}
392 
393 	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
394 	fromlen = sizeof (from);
395 	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
396 		warn("getpeername");
397 		_exit(1);
398 	}
399 	if (keepalive &&
400 	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
401 			(char *)&on, sizeof (on)) < 0) {
402 		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
403 	}
404 
405 #if	defined(IPPROTO_IP) && defined(IP_TOS)
406 	if (from.ss_family == AF_INET) {
407 # if	defined(HAS_GETTOS)
408 		struct tosent *tp;
409 		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
410 			tos = tp->t_tos;
411 # endif
412 		if (tos < 0)
413 			tos = 020;	/* Low Delay bit */
414 		if (tos
415 		   && (setsockopt(0, IPPROTO_IP, IP_TOS,
416 				  (char *)&tos, sizeof(tos)) < 0)
417 		   && (errno != ENOPROTOOPT) )
418 			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
419 	}
420 #endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
421 	net = 0;
422 	doit((struct sockaddr *)&from);
423 	/* NOTREACHED */
424 	return(0);
425 }  /* end of main */
426 
427 	void
428 usage()
429 {
430 	fprintf(stderr, "usage: telnetd");
431 #ifdef	AUTHENTICATION
432 	fprintf(stderr,
433 	    " [-4] [-6] [-a (debug|other|user|valid|off|none)]\n\t");
434 #endif
435 #ifdef BFTPDAEMON
436 	fprintf(stderr, " [-B]");
437 #endif
438 	fprintf(stderr, " [-debug]");
439 #ifdef DIAGNOSTICS
440 	fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
441 #endif
442 #ifdef	AUTHENTICATION
443 	fprintf(stderr, " [-edebug]");
444 #endif
445 	fprintf(stderr, " [-h]");
446 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
447 	fprintf(stderr, " [-k]");
448 #endif
449 #ifdef LINEMODE
450 	fprintf(stderr, " [-l]");
451 #endif
452 	fprintf(stderr, " [-n]");
453 	fprintf(stderr, "\n\t");
454 #ifdef	HAS_GETTOS
455 	fprintf(stderr, " [-S tos]");
456 #endif
457 #ifdef	AUTHENTICATION
458 	fprintf(stderr, " [-X auth-type]");
459 #endif
460 	fprintf(stderr, " [-u utmp_hostname_length] [-U]");
461 	fprintf(stderr, " [port]\n");
462 	exit(1);
463 }
464 
465 /*
466  * getterminaltype
467  *
468  *	Ask the other end to send along its terminal type and speed.
469  * Output is the variable terminaltype filled in.
470  */
471 static unsigned char ttytype_sbbuf[] = {
472 	IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
473 };
474 
475 
476 #ifndef	AUTHENTICATION
477 #define undef2 __unused
478 #else
479 #define undef2
480 #endif
481 
482 static int
483 getterminaltype(char *name undef2)
484 {
485     int retval = -1;
486 
487     settimer(baseline);
488 #ifdef	AUTHENTICATION
489     /*
490      * Handle the Authentication option before we do anything else.
491      */
492     send_do(TELOPT_AUTHENTICATION, 1);
493     while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
494 	ttloop();
495     if (his_state_is_will(TELOPT_AUTHENTICATION)) {
496 	retval = auth_wait(name);
497     }
498 #endif
499 
500 #ifdef	ENCRYPTION
501     send_will(TELOPT_ENCRYPT, 1);
502 #endif	/* ENCRYPTION */
503     send_do(TELOPT_TTYPE, 1);
504     send_do(TELOPT_TSPEED, 1);
505     send_do(TELOPT_XDISPLOC, 1);
506     send_do(TELOPT_NEW_ENVIRON, 1);
507     send_do(TELOPT_OLD_ENVIRON, 1);
508     while (
509 #ifdef	ENCRYPTION
510 	   his_do_dont_is_changing(TELOPT_ENCRYPT) ||
511 #endif	/* ENCRYPTION */
512 	   his_will_wont_is_changing(TELOPT_TTYPE) ||
513 	   his_will_wont_is_changing(TELOPT_TSPEED) ||
514 	   his_will_wont_is_changing(TELOPT_XDISPLOC) ||
515 	   his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||
516 	   his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {
517 	ttloop();
518     }
519 #ifdef	ENCRYPTION
520     /*
521      * Wait for the negotiation of what type of encryption we can
522      * send with.  If autoencrypt is not set, this will just return.
523      */
524     if (his_state_is_will(TELOPT_ENCRYPT)) {
525 	encrypt_wait();
526     }
527 #endif	/* ENCRYPTION */
528     if (his_state_is_will(TELOPT_TSPEED)) {
529 	static unsigned char sb[] =
530 			{ IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
531 
532 	output_datalen(sb, sizeof sb);
533 	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
534     }
535     if (his_state_is_will(TELOPT_XDISPLOC)) {
536 	static unsigned char sb[] =
537 			{ IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
538 
539 	output_datalen(sb, sizeof sb);
540 	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
541     }
542     if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
543 	static unsigned char sb[] =
544 			{ IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
545 
546 	output_datalen(sb, sizeof sb);
547 	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
548     }
549     else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
550 	static unsigned char sb[] =
551 			{ IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
552 
553 	output_datalen(sb, sizeof sb);
554 	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
555     }
556     if (his_state_is_will(TELOPT_TTYPE)) {
557 
558 	output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf);
559 	DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
560 					sizeof ttytype_sbbuf - 2););
561     }
562     if (his_state_is_will(TELOPT_TSPEED)) {
563 	while (sequenceIs(tspeedsubopt, baseline))
564 	    ttloop();
565     }
566     if (his_state_is_will(TELOPT_XDISPLOC)) {
567 	while (sequenceIs(xdisplocsubopt, baseline))
568 	    ttloop();
569     }
570     if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
571 	while (sequenceIs(environsubopt, baseline))
572 	    ttloop();
573     }
574     if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
575 	while (sequenceIs(oenvironsubopt, baseline))
576 	    ttloop();
577     }
578     if (his_state_is_will(TELOPT_TTYPE)) {
579 	char first[256], last[256];
580 
581 	while (sequenceIs(ttypesubopt, baseline))
582 	    ttloop();
583 
584 	/*
585 	 * If the other side has already disabled the option, then
586 	 * we have to just go with what we (might) have already gotten.
587 	 */
588 	if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
589 	    (void) strncpy(first, terminaltype, sizeof(first)-1);
590 	    first[sizeof(first)-1] = '\0';
591 	    for(;;) {
592 		/*
593 		 * Save the unknown name, and request the next name.
594 		 */
595 		(void) strncpy(last, terminaltype, sizeof(last)-1);
596 		last[sizeof(last)-1] = '\0';
597 		_gettermname();
598 		if (terminaltypeok(terminaltype))
599 		    break;
600 		if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
601 		    his_state_is_wont(TELOPT_TTYPE)) {
602 		    /*
603 		     * We've hit the end.  If this is the same as
604 		     * the first name, just go with it.
605 		     */
606 		    if (strncmp(first, terminaltype, sizeof(first)) == 0)
607 			break;
608 		    /*
609 		     * Get the terminal name one more time, so that
610 		     * RFC1091 compliant telnets will cycle back to
611 		     * the start of the list.
612 		     */
613 		     _gettermname();
614 		    if (strncmp(first, terminaltype, sizeof(first)) != 0) {
615 			(void) strncpy(terminaltype, first, sizeof(terminaltype)-1);
616 			terminaltype[sizeof(terminaltype)-1] = '\0';
617 		    }
618 		    break;
619 		}
620 	    }
621 	}
622     }
623     return(retval);
624 }  /* end of getterminaltype */
625 
626 static void
627 _gettermname(void)
628 {
629     /*
630      * If the client turned off the option,
631      * we can't send another request, so we
632      * just return.
633      */
634     if (his_state_is_wont(TELOPT_TTYPE))
635 	return;
636     settimer(baseline);
637     output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf);
638     DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
639 					sizeof ttytype_sbbuf - 2););
640     while (sequenceIs(ttypesubopt, baseline))
641 	ttloop();
642 }
643 
644 int
645 terminaltypeok(char *s)
646 {
647     char buf[1024];
648 
649     if (terminaltype == NULL)
650 	return(1);
651 
652     /*
653      * tgetent() will return 1 if the type is known, and
654      * 0 if it is not known.  If it returns -1, it couldn't
655      * open the database.  But if we can't open the database,
656      * it won't help to say we failed, because we won't be
657      * able to verify anything else.  So, we treat -1 like 1.
658      */
659     if (tgetent(buf, s) == 0)
660 	return(0);
661     return(1);
662 }
663 
664 /*
665  * Get a pty, scan input lines.
666  */
667 void
668 doit(struct sockaddr *who)
669 {
670 	int err_; /* XXX */
671 	int ptynum;
672 
673 	/*
674 	 * Find an available pty to use.
675 	 */
676 #ifndef	convex
677 	pty = getpty(&ptynum);
678 	if (pty < 0)
679 		fatal(net, "All network ports in use");
680 #else
681 	for (;;) {
682 		char *lp;
683 
684 		if ((lp = getpty()) == NULL)
685 			fatal(net, "Out of ptys");
686 
687 		if ((pty = open(lp, 2)) >= 0) {
688 			strlcpy(line,lp,sizeof(line));
689 			line[5] = 't';
690 			break;
691 		}
692 	}
693 #endif
694 
695 	/* get name of connected client */
696 	if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1,
697 	    who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only)
698 		fatal(net, "Couldn't resolve your address into a host name.\r\n\
699 	Please contact your net administrator");
700 	remote_hostname[sizeof(remote_hostname) - 1] = '\0';
701 
702 #if (!defined(__BEOS__) && !defined(__HAIKU__))
703 	trimdomain(remote_hostname, UT_HOSTSIZE);
704 #endif
705 	if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len)
706 		err_ = getnameinfo(who, who->sa_len, remote_hostname,
707 				  sizeof(remote_hostname), NULL, 0,
708 				  NI_NUMERICHOST);
709 		/* XXX: do 'err_' check */
710 
711 	(void) gethostname(host_name, sizeof(host_name) - 1);
712 	host_name[sizeof(host_name) - 1] = '\0';
713 	hostname = host_name;
714 
715 #ifdef	AUTHENTICATION
716 #ifdef	ENCRYPTION
717 /* The above #ifdefs should actually be "or"'ed, not "and"'ed.
718  * This is a byproduct of needing "#ifdef" and not "#if defined()"
719  * for unifdef. XXX MarkM
720  */
721 	auth_encrypt_init(hostname, remote_hostname, "TELNETD", 1);
722 #endif
723 #endif
724 
725 	init_env();
726 	/*
727 	 * get terminal type.
728 	 */
729 	*user_name = 0;
730 	level = getterminaltype(user_name);
731 	setenv("TERM", terminaltype ? terminaltype : "network", 1);
732 
733 	telnet(net, pty, remote_hostname);	/* begin server process */
734 
735 	/*NOTREACHED*/
736 }  /* end of doit */
737 
738 /*
739  * Main loop.  Select from pty and network, and
740  * hand data to telnet receiver finite state machine.
741  */
742 void
743 telnet(int f, int p, char *host)
744 {
745 	int on = 1;
746 #define	TABBUFSIZ	512
747 	char	defent[TABBUFSIZ];
748 	char	defstrs[TABBUFSIZ];
749 #undef	TABBUFSIZ
750 	char *HE;
751 	char *HN;
752 	char *IM;
753 	int nfd;
754 
755 	/*
756 	 * Initialize the slc mapping table.
757 	 */
758 	get_slc_defaults();
759 
760 	/*
761 	 * Do some tests where it is desireable to wait for a response.
762 	 * Rather than doing them slowly, one at a time, do them all
763 	 * at once.
764 	 */
765 	if (my_state_is_wont(TELOPT_SGA))
766 		send_will(TELOPT_SGA, 1);
767 	/*
768 	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
769 	 * because 4.2 clients are unable to deal with TCP urgent data.
770 	 *
771 	 * To find out, we send out a "DO ECHO".  If the remote system
772 	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
773 	 * that fact ("WILL ECHO" ==> that the client will echo what
774 	 * WE, the server, sends it; it does NOT mean that the client will
775 	 * echo the terminal input).
776 	 */
777 	send_do(TELOPT_ECHO, 1);
778 
779 #ifdef	LINEMODE
780 	if (his_state_is_wont(TELOPT_LINEMODE)) {
781 		/* Query the peer for linemode support by trying to negotiate
782 		 * the linemode option.
783 		 */
784 		linemode = 0;
785 		editmode = 0;
786 		send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
787 	}
788 #endif	/* LINEMODE */
789 
790 	/*
791 	 * Send along a couple of other options that we wish to negotiate.
792 	 */
793 	send_do(TELOPT_NAWS, 1);
794 	send_will(TELOPT_STATUS, 1);
795 	flowmode = 1;		/* default flow control state */
796 	restartany = -1;	/* uninitialized... */
797 	send_do(TELOPT_LFLOW, 1);
798 
799 	/*
800 	 * Spin, waiting for a response from the DO ECHO.  However,
801 	 * some REALLY DUMB telnets out there might not respond
802 	 * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
803 	 * telnets so far seem to respond with WONT for a DO that
804 	 * they don't understand...) because by the time we get the
805 	 * response, it will already have processed the DO ECHO.
806 	 * Kludge upon kludge.
807 	 */
808 	while (his_will_wont_is_changing(TELOPT_NAWS))
809 		ttloop();
810 
811 	/*
812 	 * But...
813 	 * The client might have sent a WILL NAWS as part of its
814 	 * startup code; if so, we'll be here before we get the
815 	 * response to the DO ECHO.  We'll make the assumption
816 	 * that any implementation that understands about NAWS
817 	 * is a modern enough implementation that it will respond
818 	 * to our DO ECHO request; hence we'll do another spin
819 	 * waiting for the ECHO option to settle down, which is
820 	 * what we wanted to do in the first place...
821 	 */
822 	if (his_want_state_is_will(TELOPT_ECHO) &&
823 	    his_state_is_will(TELOPT_NAWS)) {
824 		while (his_will_wont_is_changing(TELOPT_ECHO))
825 			ttloop();
826 	}
827 	/*
828 	 * On the off chance that the telnet client is broken and does not
829 	 * respond to the DO ECHO we sent, (after all, we did send the
830 	 * DO NAWS negotiation after the DO ECHO, and we won't get here
831 	 * until a response to the DO NAWS comes back) simulate the
832 	 * receipt of a will echo.  This will also send a WONT ECHO
833 	 * to the client, since we assume that the client failed to
834 	 * respond because it believes that it is already in DO ECHO
835 	 * mode, which we do not want.
836 	 */
837 	if (his_want_state_is_will(TELOPT_ECHO)) {
838 		DIAG(TD_OPTIONS, output_data("td: simulating recv\r\n"));
839 		willoption(TELOPT_ECHO);
840 	}
841 
842 	/*
843 	 * Finally, to clean things up, we turn on our echo.  This
844 	 * will break stupid 4.2 telnets out of local terminal echo.
845 	 */
846 
847 	if (my_state_is_wont(TELOPT_ECHO))
848 		send_will(TELOPT_ECHO, 1);
849 
850 #if (!defined(__BEOS__) && !defined(__HAIKU__))
851 	/*
852 	 * Turn on packet mode
853 	 */
854 	(void) ioctl(p, TIOCPKT, (char *)&on);
855 #endif
856 
857 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
858 	/*
859 	 * Continuing line mode support.  If client does not support
860 	 * real linemode, attempt to negotiate kludge linemode by sending
861 	 * the do timing mark sequence.
862 	 */
863 	if (lmodetype < REAL_LINEMODE)
864 		send_do(TELOPT_TM, 1);
865 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
866 
867 	/*
868 	 * Call telrcv() once to pick up anything received during
869 	 * terminal type negotiation, 4.2/4.3 determination, and
870 	 * linemode negotiation.
871 	 */
872 	telrcv();
873 
874 	(void) ioctl(f, FIONBIO, (char *)&on);
875 	(void) ioctl(p, FIONBIO, (char *)&on);
876 
877 #if	defined(SO_OOBINLINE)
878 	(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
879 				(char *)&on, sizeof on);
880 #endif	/* defined(SO_OOBINLINE) */
881 
882 #ifdef	SIGTSTP
883 	(void) signal(SIGTSTP, SIG_IGN);
884 #endif
885 #ifdef	SIGTTOU
886 	/*
887 	 * Ignoring SIGTTOU keeps the kernel from blocking us
888 	 * in ttioct() in /sys/tty.c.
889 	 */
890 	(void) signal(SIGTTOU, SIG_IGN);
891 #endif
892 
893 	(void) signal(SIGCHLD, cleanup);
894 
895 #ifdef  TIOCNOTTY
896 	{
897 		int t;
898 		t = open(_PATH_TTY, O_RDWR);
899 		if (t >= 0) {
900 			(void) ioctl(t, TIOCNOTTY, (char *)0);
901 			(void) close(t);
902 		}
903 	}
904 #endif
905 
906 	/*
907 	 * Show banner that getty never gave.
908 	 *
909 	 * We put the banner in the pty input buffer.  This way, it
910 	 * gets carriage return null processing, etc., just like all
911 	 * other pty --> client data.
912 	 */
913 
914 	if (getent(defent, "default") == 1) {
915 		char *cp=defstrs;
916 
917 		HE = Getstr("he", &cp);
918 		HN = Getstr("hn", &cp);
919 		IM = Getstr("im", &cp);
920 		if (HN && *HN)
921 			(void) strlcpy(host_name, HN, sizeof(host_name));
922 		if (IM == 0)
923 			IM = strdup("");
924 	} else {
925 		IM = strdup(DEFAULT_IM);
926 		HE = 0;
927 	}
928 	edithost(HE, host_name);
929 	if (hostinfo && *IM)
930 		putf(IM, ptyibuf2);
931 
932 	if (pcc)
933 		(void) strncat(ptyibuf2, ptyip, pcc+1);
934 	ptyip = ptyibuf2;
935 	pcc = strlen(ptyip);
936 #ifdef	LINEMODE
937 	/*
938 	 * Last check to make sure all our states are correct.
939 	 */
940 	init_termbuf();
941 	localstat();
942 #endif	/* LINEMODE */
943 
944 	DIAG(TD_REPORT, output_data("td: Entering processing loop\r\n"));
945 
946 	/*
947 	 * Startup the login process on the slave side of the terminal
948 	 * now.  We delay this until here to insure option negotiation
949 	 * is complete.
950 	 */
951 	startslave(host, level, user_name);
952 
953 	nfd = ((f > p) ? f : p) + 1;
954 	for (;;) {
955 		fd_set ibits, obits, xbits;
956 		int c;
957 
958 		if (ncc < 0 && pcc < 0)
959 			break;
960 
961 		FD_ZERO(&ibits);
962 		FD_ZERO(&obits);
963 		FD_ZERO(&xbits);
964 		/*
965 		 * Never look for input if there's still
966 		 * stuff in the corresponding output buffer
967 		 */
968 		if (nfrontp - nbackp || pcc > 0) {
969 			FD_SET(f, &obits);
970 		} else {
971 			FD_SET(p, &ibits);
972 		}
973 		if (pfrontp - pbackp || ncc > 0) {
974 			FD_SET(p, &obits);
975 		} else {
976 			FD_SET(f, &ibits);
977 		}
978 		if (!SYNCHing) {
979 			FD_SET(f, &xbits);
980 		}
981 		if ((c = select(nfd, &ibits, &obits, &xbits,
982 						(struct timeval *)0)) < 1) {
983 			if (c == -1) {
984 				if (errno == EINTR) {
985 					continue;
986 				}
987 			}
988 			sleep(5);
989 			continue;
990 		}
991 
992 		/*
993 		 * Any urgent data?
994 		 */
995 		if (FD_ISSET(net, &xbits)) {
996 		    SYNCHing = 1;
997 		}
998 
999 		/*
1000 		 * Something to read from the network...
1001 		 */
1002 		if (FD_ISSET(net, &ibits)) {
1003 #if	!defined(SO_OOBINLINE)
1004 			/*
1005 			 * In 4.2 (and 4.3 beta) systems, the
1006 			 * OOB indication and data handling in the kernel
1007 			 * is such that if two separate TCP Urgent requests
1008 			 * come in, one byte of TCP data will be overlaid.
1009 			 * This is fatal for Telnet, but we try to live
1010 			 * with it.
1011 			 *
1012 			 * In addition, in 4.2 (and...), a special protocol
1013 			 * is needed to pick up the TCP Urgent data in
1014 			 * the correct sequence.
1015 			 *
1016 			 * What we do is:  if we think we are in urgent
1017 			 * mode, we look to see if we are "at the mark".
1018 			 * If we are, we do an OOB receive.  If we run
1019 			 * this twice, we will do the OOB receive twice,
1020 			 * but the second will fail, since the second
1021 			 * time we were "at the mark", but there wasn't
1022 			 * any data there (the kernel doesn't reset
1023 			 * "at the mark" until we do a normal read).
1024 			 * Once we've read the OOB data, we go ahead
1025 			 * and do normal reads.
1026 			 *
1027 			 * There is also another problem, which is that
1028 			 * since the OOB byte we read doesn't put us
1029 			 * out of OOB state, and since that byte is most
1030 			 * likely the TELNET DM (data mark), we would
1031 			 * stay in the TELNET SYNCH (SYNCHing) state.
1032 			 * So, clocks to the rescue.  If we've "just"
1033 			 * received a DM, then we test for the
1034 			 * presence of OOB data when the receive OOB
1035 			 * fails (and AFTER we did the normal mode read
1036 			 * to clear "at the mark").
1037 			 */
1038 		    if (SYNCHing) {
1039 			int atmark;
1040 
1041 			(void) ioctl(net, SIOCATMARK, (char *)&atmark);
1042 			if (atmark) {
1043 			    ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
1044 			    if ((ncc == -1) && (errno == EINVAL)) {
1045 				ncc = read(net, netibuf, sizeof (netibuf));
1046 				if (sequenceIs(didnetreceive, gotDM)) {
1047 				    SYNCHing = stilloob(net);
1048 				}
1049 			    }
1050 			} else {
1051 			    ncc = read(net, netibuf, sizeof (netibuf));
1052 			}
1053 		    } else {
1054 			ncc = read(net, netibuf, sizeof (netibuf));
1055 		    }
1056 		    settimer(didnetreceive);
1057 #else	/* !defined(SO_OOBINLINE)) */
1058 		    ncc = read(net, netibuf, sizeof (netibuf));
1059 #endif	/* !defined(SO_OOBINLINE)) */
1060 		    if (ncc < 0 && errno == EWOULDBLOCK)
1061 			ncc = 0;
1062 		    else {
1063 			if (ncc <= 0) {
1064 			    break;
1065 			}
1066 			netip = netibuf;
1067 		    }
1068 		    DIAG((TD_REPORT | TD_NETDATA),
1069 			output_data("td: netread %d chars\r\n", ncc));
1070 		    DIAG(TD_NETDATA, printdata("nd", netip, ncc));
1071 		}
1072 
1073 		/*
1074 		 * Something to read from the pty...
1075 		 */
1076 		if (FD_ISSET(p, &ibits)) {
1077 			pcc = read(p, ptyibuf, BUFSIZ);
1078 			/*
1079 			 * On some systems, if we try to read something
1080 			 * off the master side before the slave side is
1081 			 * opened, we get EIO.
1082 			 */
1083 			if (pcc < 0 && (errno == EWOULDBLOCK ||
1084 #ifdef	EAGAIN
1085 					errno == EAGAIN ||
1086 #endif
1087 					errno == EIO)) {
1088 				pcc = 0;
1089 			} else {
1090 				if (pcc <= 0)
1091 					break;
1092 #ifdef	LINEMODE
1093 				/*
1094 				 * If ioctl from pty, pass it through net
1095 				 */
1096 				if (ptyibuf[0] & TIOCPKT_IOCTL) {
1097 					copy_termbuf(ptyibuf+1, pcc-1);
1098 					localstat();
1099 					pcc = 1;
1100 				}
1101 #endif	/* LINEMODE */
1102 #if (!defined(__BEOS__) && !defined(__HAIKU__))
1103 				if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
1104 					netclear();	/* clear buffer back */
1105 # ifndef	NO_URGENT
1106 					/*
1107 					 * There are client telnets on some
1108 					 * operating systems get screwed up
1109 					 * royally if we send them urgent
1110 					 * mode data.
1111 					 */
1112 					output_data("%c%c", IAC, DM);
1113 					neturg = nfrontp-1; /* off by one XXX */
1114 					DIAG(TD_OPTIONS,
1115 					    printoption("td: send IAC", DM));
1116 
1117 # endif
1118 				}
1119 				if (his_state_is_will(TELOPT_LFLOW) &&
1120 				    (ptyibuf[0] &
1121 				     (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
1122 					int newflow =
1123 					    ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
1124 					if (newflow != flowmode) {
1125 						flowmode = newflow;
1126 						output_data("%c%c%c%c%c%c",
1127 							IAC, SB, TELOPT_LFLOW,
1128 							flowmode ? LFLOW_ON
1129 								 : LFLOW_OFF,
1130 							IAC, SE);
1131 						DIAG(TD_OPTIONS, printsub('>',
1132 						    (unsigned char *)nfrontp-4,
1133 						    4););
1134 					}
1135 				}
1136 				pcc--;
1137 #endif	/* !__BEOS__ */
1138 				//ptyip = ptyibuf+1;
1139 				ptyip = ptyibuf;
1140 			}
1141 		}
1142 
1143 		while (pcc > 0) {
1144 			if ((&netobuf[BUFSIZ] - nfrontp) < 2)
1145 				break;
1146 			c = *ptyip++ & 0377, pcc--;
1147 			if (c == IAC)
1148 				output_data("%c", c);
1149 			output_data("%c", c);
1150 			if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
1151 				if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
1152 					output_data("%c", *ptyip++ & 0377);
1153 					pcc--;
1154 				} else
1155 					output_data("%c", '\0');
1156 			}
1157 		}
1158 
1159 		if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
1160 			netflush();
1161 		if (ncc > 0)
1162 			telrcv();
1163 		if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
1164 			ptyflush();
1165 	}
1166 	cleanup(0);
1167 }  /* end of telnet */
1168 
1169 #ifndef	TCSIG
1170 # ifdef	TIOCSIG
1171 #  define TCSIG TIOCSIG
1172 # endif
1173 #endif
1174 
1175 /*
1176  * Send interrupt to process on other side of pty.
1177  * If it is in raw mode, just write NULL;
1178  * otherwise, write intr char.
1179  */
1180 void
1181 interrupt(void)
1182 {
1183 	ptyflush();	/* half-hearted */
1184 
1185 #ifdef	TCSIG
1186 	(void) ioctl(pty, TCSIG, (char *)SIGINT);
1187 #else	/* TCSIG */
1188 	init_termbuf();
1189 	*pfrontp++ = slctab[SLC_IP].sptr ?
1190 			(unsigned char)*slctab[SLC_IP].sptr : '\177';
1191 #endif	/* TCSIG */
1192 }
1193 
1194 /*
1195  * Send quit to process on other side of pty.
1196  * If it is in raw mode, just write NULL;
1197  * otherwise, write quit char.
1198  */
1199 void
1200 sendbrk(void)
1201 {
1202 	ptyflush();	/* half-hearted */
1203 #ifdef	TCSIG
1204 	(void) ioctl(pty, TCSIG, (char *)SIGQUIT);
1205 #else	/* TCSIG */
1206 	init_termbuf();
1207 	*pfrontp++ = slctab[SLC_ABORT].sptr ?
1208 			(unsigned char)*slctab[SLC_ABORT].sptr : '\034';
1209 #endif	/* TCSIG */
1210 }
1211 
1212 void
1213 sendsusp(void)
1214 {
1215 #ifdef	SIGTSTP
1216 	ptyflush();	/* half-hearted */
1217 # ifdef	TCSIG
1218 	(void) ioctl(pty, TCSIG, (char *)SIGTSTP);
1219 # else	/* TCSIG */
1220 	*pfrontp++ = slctab[SLC_SUSP].sptr ?
1221 			(unsigned char)*slctab[SLC_SUSP].sptr : '\032';
1222 # endif	/* TCSIG */
1223 #endif	/* SIGTSTP */
1224 }
1225 
1226 /*
1227  * When we get an AYT, if ^T is enabled, use that.  Otherwise,
1228  * just send back "[Yes]".
1229  */
1230 void
1231 recv_ayt(void)
1232 {
1233 #if	defined(SIGINFO) && defined(TCSIG)
1234 	if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
1235 		(void) ioctl(pty, TCSIG, (char *)SIGINFO);
1236 		return;
1237 	}
1238 #endif
1239 	output_data("\r\n[Yes]\r\n");
1240 }
1241 
1242 void
1243 doeof(void)
1244 {
1245 	init_termbuf();
1246 
1247 #if	defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN)
1248 	if (!tty_isediting()) {
1249 		extern char oldeofc;
1250 		*pfrontp++ = oldeofc;
1251 		return;
1252 	}
1253 #endif
1254 	*pfrontp++ = slctab[SLC_EOF].sptr ?
1255 			(unsigned char)*slctab[SLC_EOF].sptr : '\004';
1256 }
1257