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