1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
29 * All Rights Reserved.
30 */
31
32/*
33 * University Copyright- Copyright (c) 1982, 1986, 1988
34 * The Regents of the University of California.
35 * All Rights Reserved.
36 *
37 * University Acknowledgment- Portions of this document are derived from
38 * software developed by the University of California, Berkeley, and its
39 * contributors.
40 */
41
42/*
43 * Telnet server.
44 */
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/socket.h>
48#include <sys/wait.h>
49#include <sys/file.h>
50#include <sys/stat.h>
51#include <sys/filio.h>
52#include <sys/time.h>
53#include <sys/stropts.h>
54#include <sys/stream.h>
55#include <sys/tihdr.h>
56#include <sys/utsname.h>
57#include <unistd.h>
58
59#include <netinet/in.h>
60
61#define	AUTHWHO_STR
62#define	AUTHTYPE_NAMES
63#define	AUTHHOW_NAMES
64#define	AUTHRSP_NAMES
65#define	ENCRYPT_NAMES
66
67#include <arpa/telnet.h>
68#include <arpa/inet.h>
69#include <stdio.h>
70#include <stdarg.h>
71#include <signal.h>
72#include <errno.h>
73#include <netdb.h>
74#include <syslog.h>
75#include <ctype.h>
76#include <fcntl.h>
77#include <sac.h>	/* for SC_WILDC */
78#include <utmpx.h>
79#include <sys/ttold.h>
80#include <malloc.h>
81#include <string.h>
82#include <security/pam_appl.h>
83#include <sys/tihdr.h>
84#include <sys/logindmux.h>
85#include <sys/telioctl.h>
86#include <deflt.h>
87#include <stdlib.h>
88#include <string.h>
89#include <stropts.h>
90#include <termios.h>
91
92#include <com_err.h>
93#include <krb5.h>
94#include <krb5_repository.h>
95#include <des/des.h>
96#include <rpc/des_crypt.h>
97#include <sys/cryptmod.h>
98#include <bsm/adt.h>
99
100#define	TELNETD_OPTS "Ss:a:dEXUhR:M:"
101#ifdef DEBUG
102#define	DEBUG_OPTS "p:e"
103#else
104#define	DEBUG_OPTS ""
105#endif /* DEBUG */
106
107#define	OPT_NO			0		/* won't do this option */
108#define	OPT_YES			1		/* will do this option */
109#define	OPT_YES_BUT_ALWAYS_LOOK	2
110#define	OPT_NO_BUT_ALWAYS_LOOK	3
111
112#define	MAXOPTLEN 256
113#define	MAXUSERNAMELEN 256
114
115static char	remopts[MAXOPTLEN];
116static char	myopts[MAXOPTLEN];
117static uchar_t	doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 };
118static uchar_t	dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 };
119static uchar_t	will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 };
120static uchar_t	wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 };
121/*
122 * I/O data buffers, pointers, and counters.
123 */
124static char	ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
125
126static char	*netibuf, *netip;
127static int	netibufsize;
128
129#define	NIACCUM(c)	{   *netip++ = c; \
130			    ncc++; \
131			}
132
133static char	netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
134static char	*neturg = 0;		/* one past last bye of urgent data */
135/* the remote system seems to NOT be an old 4.2 */
136static int	not42 = 1;
137static char	defaultfile[] = "/etc/default/telnetd";
138static char	bannervar[] = "BANNER=";
139
140static char BANNER1[] = "\r\n\r\n";
141static char BANNER2[] = "\r\n\r\0\r\n\r\0";
142
143/*
144 * buffer for sub-options - enlarged to 4096 to handle credentials
145 * from AUTH options
146 */
147static char	subbuffer[4096], *subpointer = subbuffer, *subend = subbuffer;
148#define	SB_CLEAR()	subpointer = subbuffer;
149#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
150#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof (subbuffer))) { \
151				*subpointer++ = (c); \
152			}
153#define	SB_GET()	((*subpointer++)&0xff)
154#define	SB_EOF()	(subpointer >= subend)
155#define	SB_LEN()	(subend - subpointer)
156
157#define	MAXERRSTRLEN 1024
158#define	MAXPRINCLEN 256
159
160extern uint_t kwarn_add_warning(char *, int);
161extern uint_t kwarn_del_warning(char *);
162
163static boolean_t auth_debug = 0;
164static boolean_t negotiate_auth_krb5 = 1;
165static boolean_t auth_negotiated = 0;
166static int auth_status = 0;
167static int auth_level = 0;
168static char	*AuthenticatingUser = NULL;
169static char	*krb5_name = NULL;
170
171static krb5_address rsaddr = { 0, 0, 0, NULL };
172static krb5_address rsport = { 0, 0, 0, NULL };
173
174static krb5_context telnet_context = 0;
175static krb5_auth_context auth_context = 0;
176
177/* telnetd gets session key from here */
178static krb5_ticket *ticket = NULL;
179static krb5_keyblock *session_key = NULL;
180static char *telnet_srvtab = NULL;
181
182typedef struct {
183	uchar_t AuthName;
184	uchar_t AuthHow;
185	char  *AuthString;
186} AuthInfo;
187
188static AuthInfo auth_list[] = {
189	{AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL |
190	AUTH_ENCRYPT_ON, "KRB5 MUTUAL CRYPTO"},
191	{AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL,
192	"KRB5 MUTUAL" },
193	{AUTHTYPE_KERBEROS_V5,	AUTH_WHO_CLIENT | AUTH_HOW_ONE_WAY,
194	"KRB5 1-WAY" },
195	{0, 0, "NONE"}
196};
197
198static AuthInfo NoAuth = {0, 0, NULL};
199
200static AuthInfo *authenticated = NULL;
201
202#define	PREAMBLE_SIZE		5	/* for auth_reply_str allocation */
203#define	POSTAMBLE_SIZE		5
204#define	STR_DATA_LEN(len)	((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
205
206static void auth_name(uchar_t *, int);
207static void auth_is(uchar_t *, int);
208
209#define	NO_ENCRYPTION   0x00
210#define	SEND_ENCRYPTED  0x01
211#define	RECV_ENCRYPTED  0x02
212#define	ENCRYPT_BOTH_WAYS    (SEND_ENCRYPTED | RECV_ENCRYPTED)
213
214static telnet_enc_data_t  encr_data;
215static boolean_t negotiate_encrypt = B_TRUE;
216static boolean_t sent_encrypt_support = B_FALSE;
217static boolean_t sent_will_encrypt = B_FALSE;
218static boolean_t sent_do_encrypt = B_FALSE;
219static boolean_t enc_debug = 0;
220
221static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo);
222static int  encrypt_send_encrypt_is();
223
224extern void mit_des_fixup_key_parity(Block);
225extern int krb5_setenv(const char *, const char *, int);
226/* need to know what FD to use to talk to the crypto module */
227static int cryptmod_fd = -1;
228
229#define	LOGIN_PROGRAM "/bin/login"
230
231/*
232 * State for recv fsm
233 */
234#define	TS_DATA		0	/* base state */
235#define	TS_IAC		1	/* look for double IAC's */
236#define	TS_CR		2	/* CR-LF ->'s CR */
237#define	TS_SB		3	/* throw away begin's... */
238#define	TS_SE		4	/* ...end's (suboption negotiation) */
239#define	TS_WILL		5	/* will option negotiation */
240#define	TS_WONT		6	/* wont " */
241#define	TS_DO		7	/* do " */
242#define	TS_DONT		8	/* dont " */
243
244static int	ncc;
245static int	master;		/* master side of pty */
246static int	pty;		/* side of pty that gets ioctls */
247static int	net;
248static int	inter;
249extern char **environ;
250static char	*line;
251static int	SYNCHing = 0;		/* we are in TELNET SYNCH mode */
252static int	state = TS_DATA;
253
254static int env_ovar = -1;	/* XXX.sparker */
255static int env_ovalue = -1;	/* XXX.sparker */
256static char pam_svc_name[64];
257static boolean_t	telmod_init_done = B_FALSE;
258
259static void	doit(int, struct sockaddr_storage *);
260static void	willoption(int);
261static void	wontoption(int);
262static void	dooption(int);
263static void	dontoption(int);
264static void	fatal(int, char *);
265static void	fatalperror(int, char *, int);
266static void	mode(int, int);
267static void	interrupt(void);
268static void	drainstream(int);
269static int	readstream(int, char *, int);
270static int	send_oob(int fd, char *ptr, int count);
271static int	local_setenv(const char *name, const char *value, int rewrite);
272static void	local_unsetenv(const char *name);
273static void	suboption(void);
274static int	removemod(int f, char *modname);
275static void	willoption(int option);
276static void	wontoption(int option);
277static void	dooption(int option);
278static void	dontoption(int option);
279static void	write_data(const char *, ...);
280static void	write_data_len(const char *, int);
281static void	rmut(void);
282static void	cleanup(int);
283static void	telnet(int, int);
284static void	telrcv(void);
285static void	sendbrk(void);
286static void	ptyflush(void);
287static void	netclear(void);
288static void	netflush(void);
289static void	showbanner(void);
290static void	map_banner(char *);
291static void	defbanner(void);
292static void ttloop(void);
293
294/*
295 * The env_list linked list is used to store the environment variables
296 * until the final exec of login.  A malevolent client might try to
297 * send an environment variable intended to affect the telnet daemon's
298 * execution.  Right now the BANNER expansion is the only instance.
299 * Note that it is okay to pass the environment variables to login
300 * because login protects itself against environment variables mischief.
301 */
302
303struct envlist {
304	struct envlist	*next;
305	char		*name;
306	char		*value;
307	int		delete;
308};
309
310static struct envlist *envlist_head = NULL;
311
312/*
313 * The following are some clocks used to decide how to interpret
314 * the relationship between various variables.
315 */
316
317static struct {
318	int
319	system,			/* what the current time is */
320	echotoggle,		/* last time user entered echo character */
321	modenegotiated,		/* last time operating mode negotiated */
322	didnetreceive,		/* last time we read data from network */
323	ttypeopt,		/* ttype will/won't received */
324	ttypesubopt,		/* ttype subopt is received */
325	getterminal,		/* time started to get terminal information */
326	xdisplocopt,		/* xdisploc will/wont received */
327	xdisplocsubopt,		/* xdisploc suboption received */
328	nawsopt,		/* window size will/wont received */
329	nawssubopt,		/* window size received */
330	environopt,		/* environment option will/wont received */
331	oenvironopt,		/* "old" environ option will/wont received */
332	environsubopt,		/* environment option suboption received */
333	oenvironsubopt,		/* "old environ option suboption received */
334	gotDM;			/* when did we last see a data mark */
335
336	int getauth;
337	int authopt;	/* Authentication option negotiated */
338	int authdone;
339
340	int getencr;
341	int encropt;
342	int encr_support;
343} clocks;
344
345static int init_neg_done = 0;
346static boolean_t resolve_hostname = 0;
347static boolean_t show_hostinfo = 1;
348
349#define	settimer(x)	(clocks.x = ++clocks.system)
350#define	sequenceIs(x, y)	(clocks.x < clocks.y)
351
352static void send_will(int);
353static void send_wont(int);
354static void send_do(int);
355static char *__findenv(const char *name, int *offset);
356
357/* ARGSUSED */
358static void
359auth_finished(AuthInfo *ap, int result)
360{
361	if ((authenticated = ap) == NULL) {
362		authenticated = &NoAuth;
363		if (myopts[TELOPT_ENCRYPT] == OPT_YES)
364			send_wont(TELOPT_ENCRYPT);
365		myopts[TELOPT_ENCRYPT] = remopts[TELOPT_ENCRYPT] = OPT_NO;
366		encr_data.encrypt.autoflag = 0;
367	} else if (result != AUTH_REJECT &&
368		myopts[TELOPT_ENCRYPT] == OPT_YES &&
369		remopts[TELOPT_ENCRYPT] == OPT_YES) {
370
371		/*
372		 * Authentication successful, so we have a session key, and
373		 * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
374		 *
375		 * Can't have sent ENCRYPT SUPPORT yet!  And if we're sending it
376		 * now it's really only because we did the DO ENCRYPT/WILL
377		 * ENCRYPT dance before authentication, which is ok, but not too
378		 * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
379		 * dance if authentication fails, though clients typically just
380		 * don't care.
381		 */
382		write_data("%c%c%c%c%c%c%c",
383			(uchar_t)IAC,
384			(uchar_t)SB,
385			(uchar_t)TELOPT_ENCRYPT,
386			(uchar_t)ENCRYPT_SUPPORT,
387			(uchar_t)TELOPT_ENCTYPE_DES_CFB64,
388			(uchar_t)IAC,
389			(uchar_t)SE);
390
391		netflush();
392
393		sent_encrypt_support = B_TRUE;
394
395		if (enc_debug)
396			(void) fprintf(stderr,
397			"SENT ENCRYPT SUPPORT\n");
398
399		(void) encrypt_send_encrypt_is();
400	}
401
402	auth_status = result;
403
404	settimer(authdone);
405}
406
407static void
408reply_to_client(AuthInfo *ap, int type, void *data, int len)
409{
410	uchar_t reply[BUFSIZ];
411	uchar_t *p = reply;
412	uchar_t *cd = (uchar_t *)data;
413
414	if (len == -1 && data != NULL)
415		len = strlen((char *)data);
416	else if (len > (sizeof (reply) - 9)) {
417		syslog(LOG_ERR,
418		    "krb5 auth reply length too large (%d)", len);
419		if (auth_debug)
420			(void) fprintf(stderr,
421				    "krb5 auth reply length too large (%d)\n",
422				    len);
423		return;
424	} else if (data == NULL)
425		len = 0;
426
427	*p++ = IAC;
428	*p++ = SB;
429	*p++ = TELOPT_AUTHENTICATION;
430	*p++ = AUTHTYPE_KERBEROS_V5;
431	*p++ = ap->AuthName;
432	*p++ = ap->AuthHow; /* MUTUAL, ONE-WAY, etc */
433	*p++ = type;	    /* RESPONSE or ACCEPT */
434	while (len-- > 0) {
435		if ((*p++ = *cd++) == IAC)
436			*p++ = IAC;
437	}
438	*p++ = IAC;
439	*p++ = SE;
440
441	/* queue the data to be sent */
442	write_data_len((const char *)reply, p-reply);
443
444#if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
445defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
446	if (auth_debug) {
447		(void) fprintf(stderr, "SENT TELOPT_AUTHENTICATION REPLY "
448			    "%s %s|%s %s\n",
449			    AUTHTYPE_NAME(ap->AuthName),
450			    AUTHWHO_NAME(ap->AuthHow & AUTH_WHO_MASK),
451			    AUTHHOW_NAME(ap->AuthHow & AUTH_HOW_MASK),
452			    AUTHRSP_NAME(type));
453	}
454#endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
455
456	netflush();
457}
458
459/* Decode, decrypt and store the forwarded creds in the local ccache. */
460static krb5_error_code
461rd_and_store_forwarded_creds(krb5_context context,
462			    krb5_auth_context auth_context,
463			    krb5_data *inbuf, krb5_ticket *ticket,
464			    char *username)
465{
466	krb5_creds **creds;
467	krb5_error_code retval;
468	char ccname[MAXPATHLEN];
469	krb5_ccache ccache = NULL;
470	char *client_name = NULL;
471
472	if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))
473		return (retval);
474
475	(void) sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", getpid());
476	(void) krb5_setenv("KRB5CCNAME", ccname, 1);
477
478	if ((retval = krb5_cc_default(context, &ccache)))
479		goto cleanup;
480
481	if ((retval = krb5_cc_initialize(context, ccache,
482					ticket->enc_part2->client)) != 0)
483		goto cleanup;
484
485	if ((retval = krb5_cc_store_cred(context, ccache, *creds)) != 0)
486		goto cleanup;
487
488	if ((retval = krb5_cc_close(context, ccache)) != 0)
489		goto cleanup;
490
491	/* Register with ktkt_warnd(1M) */
492	if ((retval = krb5_unparse_name(context, (*creds)->client,
493					&client_name)) != 0)
494		goto cleanup;
495	(void) kwarn_del_warning(client_name);
496	if (kwarn_add_warning(client_name, (*creds)->times.endtime) != 0) {
497		syslog(LOG_AUTH|LOG_NOTICE,
498		    "rd_and_store_forwarded_creds: kwarn_add_warning"
499		    " failed: ktkt_warnd(1M) down? ");
500		if (auth_debug)
501			(void) fprintf(stderr,
502				    "kwarn_add_warning failed:"
503				    " ktkt_warnd(1M) down?\n");
504	}
505	free(client_name);
506	client_name = NULL;
507
508	if (username != NULL) {
509		/*
510		 * This verifies that the user is valid on the local system,
511		 * maps the username from KerberosV5 to unix,
512		 * and moves the KRB5CCNAME file to the correct place
513		 *  /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
514		 *
515		 * NOTE: the user must be in the gsscred table in order to map
516		 * from KRB5 to Unix.
517		 */
518		(void) krb5_kuserok(context, ticket->enc_part2->client,
519				username);
520	}
521	if (auth_debug)
522		(void) fprintf(stderr,
523			    "Successfully stored forwarded creds\n");
524
525cleanup:
526	krb5_free_creds(context, *creds);
527	return (retval);
528}
529
530static void
531kerberos5_is(AuthInfo *ap, uchar_t *data, int cnt)
532{
533	krb5_error_code err = 0;
534	krb5_principal server;
535	krb5_keyblock *newkey = NULL;
536	krb5_keytab keytabid = 0;
537	krb5_data outbuf;
538	krb5_data inbuf;
539	krb5_authenticator *authenticator;
540	char errbuf[MAXERRSTRLEN];
541	char *name;
542	krb5_data auth;
543
544	Session_Key skey;
545
546	if (cnt-- < 1)
547		return;
548	switch (*data++) {
549	case KRB_AUTH:
550		auth.data = (char *)data;
551		auth.length = cnt;
552
553		if (auth_context == NULL) {
554			err = krb5_auth_con_init(telnet_context, &auth_context);
555			if (err)
556				syslog(LOG_ERR,
557				    "Error getting krb5 auth "
558				    "context: %s", error_message(err));
559		}
560		if (!err) {
561			krb5_rcache rcache;
562
563			err = krb5_auth_con_getrcache(telnet_context,
564						    auth_context,
565						    &rcache);
566			if (!err && !rcache) {
567				err = krb5_sname_to_principal(telnet_context,
568							    0, 0,
569							    KRB5_NT_SRV_HST,
570							    &server);
571				if (!err) {
572					err = krb5_get_server_rcache(
573						telnet_context,
574						krb5_princ_component(
575							telnet_context,
576							server, 0),
577						&rcache);
578
579					krb5_free_principal(telnet_context,
580							    server);
581				}
582			}
583			if (err)
584				syslog(LOG_ERR,
585				    "Error allocating krb5 replay cache: %s",
586				    error_message(err));
587			else {
588				err = krb5_auth_con_setrcache(telnet_context,
589							    auth_context,
590							    rcache);
591				if (err)
592					syslog(LOG_ERR,
593					    "Error creating krb5 "
594					    "replay cache: %s",
595					    error_message(err));
596			}
597		}
598		if (!err && telnet_srvtab != NULL)
599			err = krb5_kt_resolve(telnet_context,
600					    telnet_srvtab, &keytabid);
601		if (!err)
602			err = krb5_rd_req(telnet_context, &auth_context, &auth,
603					NULL, keytabid, NULL, &ticket);
604		if (err) {
605			(void) snprintf(errbuf, sizeof (errbuf),
606				"Error reading krb5 auth information:"
607				" %s", error_message(err));
608			goto errout;
609		}
610
611		/*
612		 * Verify that the correct principal was used
613		 */
614		if (krb5_princ_component(telnet_context,
615				ticket->server, 0)->length < MAXPRINCLEN) {
616			char princ[MAXPRINCLEN];
617			(void) strncpy(princ,
618				    krb5_princ_component(telnet_context,
619						ticket->server, 0)->data,
620				    krb5_princ_component(telnet_context,
621					    ticket->server, 0)->length);
622			princ[krb5_princ_component(telnet_context,
623					ticket->server, 0)->length] = '\0';
624			if (strcmp("host", princ)) {
625				if (strlen(princ) < sizeof (errbuf) - 39) {
626				    (void) snprintf(errbuf, sizeof (errbuf),
627						"incorrect service "
628						    "name: \"%s\" != "
629						    "\"host\"",
630						    princ);
631			    } else {
632				    (void) strncpy(errbuf,
633						"incorrect service "
634						"name: principal != "
635						"\"host\"",
636						sizeof (errbuf));
637			    }
638			    goto errout;
639			}
640		} else {
641			(void) strlcpy(errbuf, "service name too long",
642					sizeof (errbuf));
643			goto errout;
644		}
645
646		err = krb5_auth_con_getauthenticator(telnet_context,
647						auth_context,
648						&authenticator);
649		if (err) {
650			(void) snprintf(errbuf, sizeof (errbuf),
651				"Failed to get authenticator: %s",
652				error_message(err));
653			goto errout;
654		}
655		if ((ap->AuthHow & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
656			!authenticator->checksum) {
657			(void) strlcpy(errbuf,
658				    "authenticator is missing checksum",
659				    sizeof (errbuf));
660			goto errout;
661		}
662		if (authenticator->checksum) {
663			char type_check[2];
664			krb5_checksum *cksum = authenticator->checksum;
665			krb5_keyblock *key;
666			krb5_data input;
667			krb5_boolean valid;
668
669			type_check[0] = ap->AuthName;
670			type_check[1] = ap->AuthHow;
671
672			err = krb5_auth_con_getkey(telnet_context,
673						auth_context, &key);
674			if (err) {
675				(void) snprintf(errbuf, sizeof (errbuf),
676					"Failed to get key from "
677					"authenticator: %s",
678					error_message(err));
679				goto errout;
680			}
681
682			input.data = type_check;
683			input.length = 2;
684			err = krb5_c_verify_checksum(telnet_context,
685							key, 0,
686							&input,
687							cksum,
688							&valid);
689			if (!err && !valid)
690				err = KRB5KRB_AP_ERR_BAD_INTEGRITY;
691
692			if (err) {
693				(void) snprintf(errbuf, sizeof (errbuf),
694						"Kerberos checksum "
695						"verification failed: "
696						"%s",
697						error_message(err));
698				goto errout;
699			}
700			krb5_free_keyblock(telnet_context, key);
701		}
702
703		krb5_free_authenticator(telnet_context, authenticator);
704		if ((ap->AuthHow & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
705			/* do ap_rep stuff here */
706			if ((err = krb5_mk_rep(telnet_context, auth_context,
707					    &outbuf))) {
708				(void) snprintf(errbuf, sizeof (errbuf),
709						"Failed to make "
710						"Kerberos auth reply: "
711						"%s",
712						error_message(err));
713				goto errout;
714			}
715			reply_to_client(ap, KRB_RESPONSE, outbuf.data,
716					outbuf.length);
717		}
718		if (krb5_unparse_name(telnet_context,
719				    ticket->enc_part2->client,
720				    &name))
721			name = 0;
722		reply_to_client(ap, KRB_ACCEPT, name, name ? -1 : 0);
723		if (auth_debug) {
724			syslog(LOG_NOTICE,
725			    "\tKerberos5 identifies user as ``%s''\r\n",
726			    name ? name : "");
727		}
728		if (name != NULL) {
729			krb5_name = (char *)strdup(name);
730		}
731		auth_finished(ap, AUTH_USER);
732
733		if (name != NULL)
734			free(name);
735		(void) krb5_auth_con_getremotesubkey(telnet_context,
736		    auth_context, &newkey);
737		if (session_key != NULL) {
738			krb5_free_keyblock(telnet_context, session_key);
739			session_key = 0;
740		}
741		if (newkey != NULL) {
742			(void) krb5_copy_keyblock(telnet_context,
743			    newkey, &session_key);
744			krb5_free_keyblock(telnet_context, newkey);
745		} else {
746			(void) krb5_copy_keyblock(telnet_context,
747			    ticket->enc_part2->session, &session_key);
748		}
749
750		/*
751		 * Initialize encryption stuff.  Currently, we are only
752		 * supporting 8 byte keys and blocks. Check for this later.
753		 */
754		skey.type = SK_DES;
755		skey.length = DES_BLOCKSIZE;
756		skey.data = session_key->contents;
757		encrypt_session_key(&skey, &encr_data.encrypt);
758		encrypt_session_key(&skey, &encr_data.decrypt);
759		break;
760	case KRB_FORWARD:
761		inbuf.length = cnt;
762		inbuf.data = (char *)data;
763		if (auth_debug)
764			(void) fprintf(stderr,
765				    "RCVD KRB_FORWARD data (%d bytes)\n", cnt);
766
767		if (auth_context != NULL) {
768			krb5_rcache rcache;
769
770			err = krb5_auth_con_getrcache(telnet_context,
771						    auth_context, &rcache);
772			if (!err && !rcache) {
773				err = krb5_sname_to_principal(telnet_context,
774					0, 0, KRB5_NT_SRV_HST, &server);
775				if (!err) {
776					err = krb5_get_server_rcache(
777						telnet_context,
778						krb5_princ_component(
779							telnet_context,
780							server, 0),
781						&rcache);
782					krb5_free_principal(telnet_context,
783								server);
784				}
785			}
786			if (err) {
787				syslog(LOG_ERR,
788				    "Error allocating krb5 replay cache: %s",
789				    error_message(err));
790			} else {
791				err = krb5_auth_con_setrcache(telnet_context,
792					auth_context, rcache);
793				if (err)
794					syslog(LOG_ERR,
795					    "Error creating krb5 replay cache:"
796					    " %s",
797					    error_message(err));
798			}
799		}
800		/*
801		 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
802		 * from the original connection.  This data is used to
803		 * verify the forwarded credentials.
804		 */
805		if (!(err = krb5_auth_con_setaddrs(telnet_context, auth_context,
806					    NULL, &rsaddr)))
807			err = krb5_auth_con_setports(telnet_context,
808						auth_context, NULL, &rsport);
809
810		if (err == 0)
811			/*
812			 * If all is well, store the forwarded creds in
813			 * the users local credential cache.
814			 */
815			err = rd_and_store_forwarded_creds(telnet_context,
816							auth_context, &inbuf,
817							ticket,
818							AuthenticatingUser);
819		if (err) {
820			(void) snprintf(errbuf, sizeof (errbuf),
821					"Read forwarded creds failed: %s",
822					error_message(err));
823			syslog(LOG_ERR, "%s", errbuf);
824
825			reply_to_client(ap, KRB_FORWARD_REJECT, errbuf, -1);
826			if (auth_debug)
827				(void) fprintf(stderr,
828					    "\tCould not read "
829					    "forwarded credentials\r\n");
830		} else
831			reply_to_client(ap, KRB_FORWARD_ACCEPT, (void *) 0, 0);
832
833		if (rsaddr.contents != NULL)
834			free(rsaddr.contents);
835
836		if (rsport.contents != NULL)
837			free(rsport.contents);
838
839		if (auth_debug)
840			(void) fprintf(stderr, "\tForwarded "
841						"credentials obtained\r\n");
842		break;
843	default:
844		if (auth_debug)
845			(void) fprintf(stderr,
846				    "\tUnknown Kerberos option %d\r\n",
847				    data[-1]);
848		reply_to_client(ap, KRB_REJECT, (void *) 0, 0);
849		break;
850	}
851	return;
852
853errout:
854	reply_to_client(ap, KRB_REJECT, errbuf, -1);
855
856	if (auth_debug)
857		(void) fprintf(stderr, "\tKerberos V5 error: %s\r\n", errbuf);
858
859	syslog(LOG_ERR, "%s", errbuf);
860
861	if (auth_context != NULL) {
862		(void) krb5_auth_con_free(telnet_context, auth_context);
863		auth_context = 0;
864	}
865}
866
867static int
868krb5_init()
869{
870	int code = 0;
871
872	if (telnet_context == NULL) {
873		code = krb5_init_context(&telnet_context);
874		if (code != 0 && auth_debug)
875			syslog(LOG_NOTICE,
876			    "Cannot initialize Kerberos V5: %s",
877			    error_message(code));
878	}
879
880	return (code);
881}
882
883static void
884auth_name(uchar_t *data, int cnt)
885{
886	char namebuf[MAXPRINCLEN];
887
888	if (cnt < 1) {
889		if (auth_debug)
890			(void) fprintf(stderr,
891				    "\t(auth_name) Empty NAME in auth "
892				    "reply\n");
893		return;
894	}
895	if (cnt > sizeof (namebuf)-1) {
896		if (auth_debug)
897			(void) fprintf(stderr,
898				    "\t(auth_name) NAME exceeds %d bytes\n",
899				sizeof (namebuf)-1);
900		return;
901	}
902	(void) memcpy((void *)namebuf, (void *)data, cnt);
903	namebuf[cnt] = 0;
904	if (auth_debug)
905		(void) fprintf(stderr, "\t(auth_name) name [%s]\n", namebuf);
906	AuthenticatingUser = (char *)strdup(namebuf);
907}
908
909static void
910auth_is(uchar_t *data, int cnt)
911{
912	AuthInfo *aptr = auth_list;
913
914	if (cnt < 2)
915		return;
916
917	/*
918	 * We failed to negoiate secure authentication
919	 */
920	if (data[0] == AUTHTYPE_NULL) {
921		auth_finished(0, AUTH_REJECT);
922		return;
923	}
924
925	while (aptr->AuthName != 0 &&
926	    (aptr->AuthName != data[0] || aptr->AuthHow != data[1]))
927		aptr++;
928
929	if (aptr != NULL) {
930		if (auth_debug)
931			(void) fprintf(stderr, "\t(auth_is) auth type is %s "
932				"(%d bytes)\n",	aptr->AuthString, cnt);
933
934		if (aptr->AuthName == AUTHTYPE_KERBEROS_V5)
935			kerberos5_is(aptr, data+2, cnt-2);
936	}
937}
938
939static int
940krb5_user_status(char *name, int namelen, int level)
941{
942	int retval = AUTH_USER;
943
944	if (auth_debug)
945		(void) fprintf(stderr, "\t(krb5_user_status) level = %d "
946			"auth_level = %d  user = %s\n",
947			level, auth_level,
948			(AuthenticatingUser != NULL ? AuthenticatingUser : ""));
949
950	if (level < AUTH_USER)
951		return (level);
952
953	if (AuthenticatingUser != NULL &&
954	    (retval = krb5_kuserok(telnet_context, ticket->enc_part2->client,
955			    AuthenticatingUser))) {
956		(void) strncpy(name, AuthenticatingUser, namelen);
957		return (AUTH_VALID);
958	} else {
959		if (!retval)
960			syslog(LOG_ERR,
961			    "Krb5 principal lacks permission to "
962			    "access local account for %s",
963			    AuthenticatingUser);
964		return (AUTH_USER);
965	}
966}
967
968/*
969 * Wrapper around /dev/urandom
970 */
971static int
972getrandom(char *buf, int buflen)
973{
974	static int devrandom = -1;
975
976	if (devrandom == -1 &&
977	    (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
978		fatalperror(net, "Unable to open /dev/urandom: ",
979			    errno);
980		return (-1);
981	}
982
983	if (read(devrandom, buf, buflen) == -1) {
984		fatalperror(net, "Unable to read from /dev/urandom: ",
985			    errno);
986		return (-1);
987	}
988
989	return (0);
990}
991
992/*
993 * encrypt_init
994 *
995 * Initialize the encryption data structures
996 */
997static void
998encrypt_init()
999{
1000	(void) memset(&encr_data.encrypt, 0, sizeof (cipher_info_t));
1001	(void) memset(&encr_data.decrypt, 0, sizeof (cipher_info_t));
1002
1003	encr_data.encrypt.state = ENCR_STATE_NOT_READY;
1004	encr_data.decrypt.state = ENCR_STATE_NOT_READY;
1005}
1006
1007/*
1008 * encrypt_send_request_start
1009 *
1010 * Request that the remote side automatically start sending
1011 * encrypted output
1012 */
1013static void
1014encrypt_send_request_start()
1015{
1016	uchar_t buf[6+TELNET_MAXKEYIDLEN], *p;
1017
1018	p = buf;
1019
1020	*p++ = IAC;
1021	*p++ = SB;
1022	*p++ = TELOPT_ENCRYPT;
1023	*p++ = ENCRYPT_REQSTART;
1024	/*
1025	 * We are telling the remote side which
1026	 * decrypt key we will use so that it may
1027	 * encrypt in the same key.
1028	 */
1029	(void) memcpy(p, encr_data.decrypt.keyid, encr_data.decrypt.keyidlen);
1030	p += encr_data.decrypt.keyidlen;
1031
1032	*p++ = IAC;
1033	*p++ = SE;
1034
1035	write_data_len((const char *)buf, p-buf);
1036	netflush();
1037	if (enc_debug)
1038		(void) fprintf(stderr,
1039			    "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
1040}
1041
1042/*
1043 * encrypt_is
1044 *
1045 * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
1046 * message, the client is telling us that it will be sending
1047 * encrypted data using the indicated cipher.
1048 * We must initialize the read (decrypt) side of our connection
1049 */
1050static void
1051encrypt_is(uchar_t *data, int cnt)
1052{
1053	register int type;
1054	register int iv_status = CFB64_IV_OK;
1055	register int lstate = 0;
1056
1057	uchar_t sbbuf[] = {
1058		(uchar_t)IAC,
1059		(uchar_t)SB,
1060		(uchar_t)TELOPT_ENCRYPT,
1061		(uchar_t)ENCRYPT_REPLY,
1062		(uchar_t)0,		/* placeholder:  sbbuf[4] */
1063		(uchar_t)CFB64_IV_OK,	/* placeholder:  sbbuf[5] */
1064		(uchar_t)IAC,
1065		(uchar_t)SE,
1066	};
1067
1068	if (--cnt < 0)
1069		return;
1070
1071	type = sbbuf[4] = *data++;
1072
1073	/*
1074	 * Steps to take:
1075	 *   1. Create the proper stream Initialization vector
1076	 *		- copy the correct 'seed' to IV and output blocks
1077	 *		- set the correct key schedule
1078	 *   2. Generate reply for the other side:
1079	 *		IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
1080	 *		[ data ... ] IAC SE
1081	 *   3. Tell crypto module:  method, direction, IV
1082	 */
1083	switch (type) {
1084	case TELOPT_ENCTYPE_DES_CFB64:
1085		encr_data.decrypt.type = type;
1086
1087		lstate = encr_data.decrypt.state;
1088		if (enc_debug)
1089			(void) fprintf(stderr,
1090				    "\t(encrypt_is) initial state = %d\n",
1091				    lstate);
1092		/*
1093		 * Before we extract the IV bytes, make sure we got
1094		 * enough data.
1095		 */
1096		if (cnt < sizeof (Block)) {
1097			iv_status = CFB64_IV_BAD;
1098			if (enc_debug)
1099				(void) fprintf(stderr,
1100					    "\t(encrypt_is) Not enough "
1101					    "IV bytes\n");
1102			lstate = ENCR_STATE_NOT_READY;
1103		} else {
1104			data++; /* skip over the CFB64_IV byte */
1105			(void) memcpy(encr_data.decrypt.ivec, data,
1106				    sizeof (Block));
1107			lstate = ENCR_STATE_IN_PROGRESS;
1108		}
1109		break;
1110	case TELOPT_ENCTYPE_NULL:
1111		encr_data.decrypt.type = type;
1112		lstate &= ~ENCR_STATE_NO_RECV_IV;
1113		lstate &= ~ENCR_STATE_NO_SEND_IV;
1114		if (enc_debug)
1115			(void) fprintf(stderr,
1116				"\t(encrypt_is) We accept NULL encr\n");
1117		break;
1118	default:
1119		iv_status = CFB64_IV_BAD;
1120		encr_data.decrypt.type = 0;
1121		if (enc_debug)
1122			(void) fprintf(stderr,
1123				    "\t(encrypt_is) Can't find type (%d) "
1124				    "for initial negotiation\r\n",
1125				    type);
1126		lstate = ENCR_STATE_NOT_READY;
1127		break;
1128	}
1129
1130	sbbuf[5] = (uchar_t)iv_status; /* either CFB64_IV_OK or BAD */
1131
1132	if (iv_status == CFB64_IV_OK) {
1133		/*
1134		 * send IV to crypto module and indicate it is for
1135		 * decrypt only
1136		 */
1137		lstate &= ~ENCR_STATE_NO_RECV_IV;  /* we received an OK IV */
1138		lstate &= ~ENCR_STATE_NO_SEND_IV;  /* we dont send an IV */
1139	} else {
1140		/* tell crypto module to disable crypto on "read" stream */
1141		lstate = ENCR_STATE_NOT_READY;
1142	}
1143
1144	write_data_len((const char *)sbbuf, sizeof (sbbuf));
1145	netflush();
1146#ifdef ENCRYPT_NAMES
1147	if (enc_debug)
1148		(void) fprintf(stderr,
1149			    "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
1150			    ENCTYPE_NAME(type),
1151			    (iv_status == CFB64_IV_OK ? "CFB64_IV_OK" :
1152			    "CFB64_IV_BAD"));
1153#endif /* ENCRYPT_NAMES */
1154	/* Update the state of the decryption negotiation */
1155	encr_data.decrypt.state = lstate;
1156
1157	if (lstate == ENCR_STATE_NOT_READY)
1158		encr_data.decrypt.autoflag = 0;
1159	else {
1160		if (lstate == ENCR_STATE_OK && encr_data.decrypt.autoflag)
1161			encrypt_send_request_start();
1162	}
1163	if (enc_debug)
1164		(void) fprintf(stderr,
1165			    "\t(encrypt_is) final DECRYPT state = %d\n",
1166			    encr_data.decrypt.state);
1167}
1168
1169/*
1170 * encrypt_send_encrypt_is
1171 *
1172 * Tell the client what encryption we will use
1173 * and what our IV will be.
1174 */
1175static int
1176encrypt_send_encrypt_is()
1177{
1178	register int lstate;
1179	krb5_error_code kret;
1180	uchar_t sbbuf[MAXOPTLEN], *p;
1181	int i;
1182
1183	lstate = encr_data.encrypt.state;
1184
1185	if (encr_data.encrypt.type == ENCTYPE_NULL) {
1186		/*
1187		 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
1188		 * on a cipher.
1189		 */
1190		return (lstate);
1191	}
1192
1193	/*
1194	 * - Create a random DES key
1195	 *
1196	 * - DES ECB encrypt
1197	 *   encrypt the IV using itself as the key.
1198	 *
1199	 * - Send response
1200	 *   IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
1201	 *   IAC SE
1202	 *
1203	 */
1204	if (lstate == ENCR_STATE_NOT_READY)
1205		lstate = ENCR_STATE_IN_PROGRESS;
1206	else if ((lstate & ENCR_STATE_NO_SEND_IV) == 0) {
1207		if (enc_debug)
1208			(void) fprintf(stderr,
1209				"\t(encrypt_send_is) IV already sent,"
1210				" state = %d\n", lstate);
1211		return (lstate);
1212	}
1213
1214	if (!VALIDKEY(encr_data.encrypt.krbdes_key)) {
1215		/*
1216		 * Invalid key, set flag so we try again later
1217		 * when we get a good one
1218		 */
1219		encr_data.encrypt.need_start = 1;
1220		if (enc_debug)
1221			(void) fprintf(stderr,
1222				"\t(encrypt_send_is) No Key, cannot "
1223				"start encryption yet\n");
1224		return (lstate);
1225	}
1226	if (enc_debug)
1227		(void) fprintf(stderr,
1228			    "\t(encrypt_send_is) Creating new feed\n");
1229
1230	/*
1231	 * Create a random feed and send it over.
1232	 *
1233	 * Use the /dev/[u]random interface to generate
1234	 * our encryption IV.
1235	 */
1236	kret = getrandom((char *)encr_data.encrypt.ivec, sizeof (Block));
1237
1238	if (kret) {
1239		if (enc_debug)
1240			(void) fprintf(stderr,
1241				    "\t(encrypt_send_is) error from "
1242				    "getrandom: %d\n", kret);
1243		syslog(LOG_ERR, "Failed to create encryption key (err %d)\n");
1244		encr_data.encrypt.type = ENCTYPE_NULL;
1245	} else {
1246		mit_des_fixup_key_parity(encr_data.encrypt.ivec);
1247	}
1248
1249	p = sbbuf;
1250	*p++ = IAC;
1251	*p++ = SB;
1252	*p++ = TELOPT_ENCRYPT;
1253	*p++ = ENCRYPT_IS;
1254	*p++ = encr_data.encrypt.type;
1255	*p++ = CFB64_IV;
1256
1257	/*
1258	 * Copy the IV bytes individually so that when a
1259	 * 255 (telnet IAC) is used, it can be "escaped" by
1260	 * adding it twice (telnet RFC 854).
1261	 */
1262	for (i = 0; i < sizeof (Block); i++)
1263		if ((*p++ = encr_data.encrypt.ivec[i]) == IAC)
1264			*p++ = IAC;
1265
1266	*p++ = IAC;
1267	*p++ = SE;
1268	write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1269	netflush();
1270
1271	if (!kret) {
1272		lstate &= ~ENCR_STATE_NO_SEND_IV; /* we sent our IV */
1273		lstate &= ~ENCR_STATE_NO_SEND_IV; /* dont need decrypt IV */
1274	}
1275	encr_data.encrypt.state = lstate;
1276
1277	if (enc_debug) {
1278		int i;
1279		(void) fprintf(stderr,
1280			    "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
1281			    encr_data.encrypt.type);
1282		for (i = 0; i < (p-sbbuf); i++)
1283			(void) fprintf(stderr, "%d ", (int)sbbuf[i]);
1284		(void) fprintf(stderr, "\n");
1285	}
1286
1287	return (lstate);
1288}
1289
1290/*
1291 * stop_stream
1292 *
1293 * Utility routine to send a CRIOCSTOP ioctl to the
1294 * crypto module (cryptmod).
1295 */
1296static void
1297stop_stream(int fd, int dir)
1298{
1299	struct strioctl  crioc;
1300	uint32_t stopdir = dir;
1301
1302	crioc.ic_cmd = CRYPTIOCSTOP;
1303	crioc.ic_timout = -1;
1304	crioc.ic_len = sizeof (stopdir);
1305	crioc.ic_dp = (char *)&stopdir;
1306
1307	if (ioctl(fd, I_STR, &crioc)) {
1308		syslog(LOG_ERR, "Error sending CRYPTIOCSTOP ioctl: %m");
1309	}
1310}
1311
1312/*
1313 * start_stream
1314 *
1315 * Utility routine to send a CRYPTIOCSTART ioctl to the
1316 * crypto module (cryptmod).  This routine may contain optional
1317 * payload data that the cryptmod will interpret as bytes that
1318 * need to be decrypted and sent back up to the application
1319 * via the data stream.
1320 */
1321static void
1322start_stream(int fd, int dir, int datalen, char *data)
1323{
1324	struct strioctl crioc;
1325
1326	crioc.ic_cmd = (dir == CRYPT_ENCRYPT ? CRYPTIOCSTARTENC :
1327			CRYPTIOCSTARTDEC);
1328	crioc.ic_timout = -1;
1329	crioc.ic_len = datalen;
1330	crioc.ic_dp = data;
1331
1332	if (ioctl(fd, I_STR, &crioc)) {
1333		syslog(LOG_ERR, "Error sending CRYPTIOCSTART ioctl: %m");
1334	}
1335}
1336
1337/*
1338 * encrypt_start_output
1339 *
1340 * Tell the other side to start encrypting its data
1341 */
1342static void
1343encrypt_start_output()
1344{
1345	int lstate;
1346	uchar_t *p;
1347	uchar_t sbbuf[MAXOPTLEN];
1348	struct strioctl crioc;
1349	struct cr_info_t cki;
1350
1351	/*
1352	 * Initialize crypto and send the ENCRYPT_IS msg
1353	 */
1354	lstate = encrypt_send_encrypt_is();
1355
1356	if (lstate != ENCR_STATE_OK) {
1357		if (enc_debug)
1358			(void) fprintf(stderr,
1359				"\t(encrypt_start_output) ENCRYPT state "
1360				"= %d\n", lstate);
1361		return;
1362	}
1363
1364	p = sbbuf;
1365
1366	*p++ = IAC;
1367	*p++ = SB;
1368	*p++ = TELOPT_ENCRYPT;
1369	*p++ = ENCRYPT_START;
1370
1371	(void) memcpy(p, encr_data.encrypt.keyid, encr_data.encrypt.keyidlen);
1372	p += encr_data.encrypt.keyidlen;
1373
1374	*p++ = IAC;
1375	*p++ = SE;
1376
1377	/* Flush this data out before we start encrypting */
1378	write_data_len((const char *)sbbuf, (int)(p-sbbuf));
1379	netflush();
1380
1381	if (enc_debug)
1382		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
1383			"(lstate = %d) data waiting = %d\n",
1384			(int)encr_data.encrypt.keyid[0],
1385			lstate, nfrontp-nbackp);
1386
1387	encr_data.encrypt.state = lstate;
1388
1389	/*
1390	 * tell crypto module what key to use for encrypting
1391	 * Note that the ENCRYPT has not yet been enabled, but we
1392	 * need to first set the crypto key to use.
1393	 */
1394	cki.direction_mask = CRYPT_ENCRYPT;
1395
1396	if (encr_data.encrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1397		cki.crypto_method = CRYPT_METHOD_DES_CFB;
1398	} else {
1399		if (enc_debug)
1400			(void) fprintf(stderr,
1401				"\t(encrypt_start_output) - unknown "
1402				"crypto_method %d\n",
1403				encr_data.encrypt.type);
1404		syslog(LOG_ERR, "unrecognized crypto encrypt method: %d",
1405				encr_data.encrypt.type);
1406
1407		return;
1408	}
1409
1410	/*
1411	 * If we previously configured this crypto method, we dont want to
1412	 * overwrite the key or ivec information already given to the crypto
1413	 * module as it will cause the cipher data between the client and server
1414	 * to become out of synch and impossible to decipher.
1415	 */
1416	if (encr_data.encrypt.setup == cki.crypto_method) {
1417		cki.keylen = 0;
1418		cki.iveclen = 0;
1419	} else {
1420		cki.keylen = DES_BLOCKSIZE;
1421		(void) memcpy(cki.key, (void *)encr_data.encrypt.krbdes_key,
1422		    DES_BLOCKSIZE);
1423
1424		cki.iveclen = DES_BLOCKSIZE;
1425		(void) memcpy(cki.ivec, (void *)encr_data.encrypt.ivec,
1426		    DES_BLOCKSIZE);
1427
1428		cki.ivec_usage = IVEC_ONETIME;
1429	}
1430
1431	cki.option_mask = 0;
1432
1433	/* Stop encrypt side prior to setup so we dont lose data */
1434	stop_stream(cryptmod_fd, CRYPT_ENCRYPT);
1435
1436	crioc.ic_cmd = CRYPTIOCSETUP;
1437	crioc.ic_timout = -1;
1438	crioc.ic_len = sizeof (struct cr_info_t);
1439	crioc.ic_dp = (char *)&cki;
1440
1441	if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1442		perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
1443	} else {
1444		/* Setup completed OK */
1445		encr_data.encrypt.setup = cki.crypto_method;
1446	}
1447
1448	/*
1449	 * We do not check for "stuck" data when setting up the
1450	 * outbound "encrypt" channel.  Any data queued prior to
1451	 * this IOCTL will get processed correctly without our help.
1452	 */
1453	start_stream(cryptmod_fd, CRYPT_ENCRYPT, 0, NULL);
1454
1455	/*
1456	 * tell crypto module to start encrypting
1457	 */
1458	if (enc_debug)
1459		(void) fprintf(stderr,
1460			"\t(encrypt_start_output) Encrypting output\n");
1461}
1462
1463/*
1464 * encrypt_request_start
1465 *
1466 * The client requests that we start encryption immediately after
1467 * successful negotiation
1468 */
1469static void
1470encrypt_request_start(void)
1471{
1472	if (encr_data.encrypt.type == ENCTYPE_NULL) {
1473		encr_data.encrypt.autoflag = 1;
1474		if (enc_debug)
1475			(void) fprintf(stderr, "\t(encrypt_request_start) "
1476				"autoencrypt = ON\n");
1477	} else {
1478		encrypt_start_output();
1479	}
1480}
1481
1482/*
1483 * encrypt_end
1484 *
1485 * ENCRYPT END received, stop decrypting the read stream
1486 */
1487static void
1488encrypt_end(int direction)
1489{
1490	struct cr_info_t cki;
1491	struct strioctl  crioc;
1492	uint32_t stopdir;
1493
1494	stopdir = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1495		CRYPT_ENCRYPT);
1496
1497	stop_stream(cryptmod_fd, stopdir);
1498
1499	/*
1500	 * Call this function when we wish to disable crypto in
1501	 * either direction (ENCRYPT or DECRYPT)
1502	 */
1503	cki.direction_mask = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
1504			    CRYPT_ENCRYPT);
1505	cki.crypto_method = CRYPT_METHOD_NONE;
1506	cki.option_mask = 0;
1507
1508	cki.keylen = 0;
1509	cki.iveclen = 0;
1510	cki.ivec_usage = IVEC_ONETIME;
1511
1512	crioc.ic_cmd = CRYPTIOCSETUP;
1513	crioc.ic_timout = -1;
1514	crioc.ic_len = sizeof (cki);
1515	crioc.ic_dp = (char *)&cki;
1516
1517	if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1518		perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
1519	}
1520
1521	start_stream(cryptmod_fd, stopdir, 0, NULL);
1522}
1523
1524/*
1525 * encrypt_request_end
1526 *
1527 * When we receive a REQEND from the client, it means
1528 * that we are supposed to stop encrypting
1529 */
1530static void
1531encrypt_request_end()
1532{
1533	/*
1534	 * Tell the other side we are done encrypting
1535	 */
1536
1537	write_data("%c%c%c%c%c%c",
1538		(uchar_t)IAC,
1539		(uchar_t)SB,
1540		(uchar_t)TELOPT_ENCRYPT,
1541		(uchar_t)ENCRYPT_END,
1542		(uchar_t)IAC,
1543		(uchar_t)SE);
1544	netflush();
1545	if (enc_debug)
1546		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
1547
1548	/*
1549	 * Turn off encryption of the write stream
1550	 */
1551	encrypt_end(TELNET_DIR_ENCRYPT);
1552}
1553
1554/*
1555 * encrypt_send_request_end
1556 *
1557 * We stop encrypting the write stream and tell the other side about it.
1558 */
1559static void
1560encrypt_send_request_end()
1561{
1562	write_data("%c%c%c%c%c%c",
1563		(uchar_t)IAC,
1564		(uchar_t)SB,
1565		(uchar_t)TELOPT_ENCRYPT,
1566		(uchar_t)ENCRYPT_REQEND,
1567		(uchar_t)IAC,
1568		(uchar_t)SE);
1569	netflush();
1570	if (enc_debug)
1571		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
1572}
1573
1574/*
1575 * encrypt_start
1576 *
1577 * The client is going to start sending encrypted data
1578 * using the previously negotiated cipher (see what we set
1579 * when we did the REPLY in encrypt_is).
1580 */
1581static void
1582encrypt_start(void)
1583{
1584	struct cr_info_t cki;
1585	struct strioctl  crioc;
1586	int bytes = 0;
1587	char *dataptr = NULL;
1588
1589	if (encr_data.decrypt.type == ENCTYPE_NULL) {
1590		if (enc_debug)
1591			(void) fprintf(stderr,
1592				"\t(encrypt_start) No DECRYPT method "
1593				"defined yet\n");
1594		encrypt_send_request_end();
1595		return;
1596	}
1597
1598	cki.direction_mask = CRYPT_DECRYPT;
1599
1600	if (encr_data.decrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
1601		cki.crypto_method = CRYPT_METHOD_DES_CFB;
1602	} else {
1603		if (enc_debug)
1604			(void) fprintf(stderr,
1605				"\t(encrypt_start) - unknown "
1606				"crypto_method %d\n", encr_data.decrypt.type);
1607
1608		syslog(LOG_ERR, "unrecognized crypto decrypt method: %d",
1609				encr_data.decrypt.type);
1610
1611		return;
1612	}
1613
1614	/*
1615	 * Don't overwrite previously configured key and ivec info
1616	 */
1617	if (encr_data.decrypt.setup != cki.crypto_method) {
1618		(void) memcpy(cki.key, (void *)encr_data.decrypt.krbdes_key,
1619		    DES_BLOCKSIZE);
1620		(void) memcpy(cki.ivec, (void *)encr_data.decrypt.ivec,
1621		    DES_BLOCKSIZE);
1622
1623		cki.keylen = DES_BLOCKSIZE;
1624		cki.iveclen = DES_BLOCKSIZE;
1625		cki.ivec_usage = IVEC_ONETIME;
1626	} else {
1627		cki.keylen = 0;
1628		cki.iveclen = 0;
1629	}
1630	cki.option_mask = 0;
1631
1632	stop_stream(cryptmod_fd, CRYPT_DECRYPT);
1633
1634	crioc.ic_cmd = CRYPTIOCSETUP;
1635	crioc.ic_timout = -1;
1636	crioc.ic_len = sizeof (struct cr_info_t);
1637	crioc.ic_dp = (char *)&cki;
1638
1639	if (ioctl(cryptmod_fd, I_STR, &crioc)) {
1640		syslog(LOG_ERR, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
1641		    "error: %m");
1642	} else {
1643		encr_data.decrypt.setup = cki.crypto_method;
1644	}
1645	if (enc_debug)
1646		(void) fprintf(stderr,
1647			    "\t(encrypt_start) called CRYPTIOCSETUP for "
1648			    "decrypt side\n");
1649
1650	/*
1651	 * Read any data stuck between the cryptmod and the application
1652	 * so we can pass it back down to be properly decrypted after
1653	 * this operation finishes.
1654	 */
1655	if (ioctl(cryptmod_fd, I_NREAD, &bytes) < 0) {
1656		syslog(LOG_ERR, "I_NREAD returned error %m");
1657		bytes = 0;
1658	}
1659
1660	/*
1661	 * Any data which was read AFTER the ENCRYPT START message
1662	 * must be sent back down to be decrypted properly.
1663	 *
1664	 * 'ncc' is the number of bytes that have been read but
1665	 * not yet processed by the telnet state machine.
1666	 *
1667	 * 'bytes' is the number of bytes waiting to be read from
1668	 * the stream.
1669	 *
1670	 * If either one is a positive value, then those bytes
1671	 * must be pulled up and sent back down to be decrypted.
1672	 */
1673	if (ncc || bytes) {
1674		drainstream(bytes);
1675		if (enc_debug)
1676			(void) fprintf(stderr,
1677				"\t(encrypt_start) after drainstream, "
1678				"ncc=%d bytes = %d\n", ncc, bytes);
1679		bytes += ncc;
1680		dataptr = netip;
1681	}
1682
1683	start_stream(cryptmod_fd, CRYPT_DECRYPT, bytes, dataptr);
1684
1685	/*
1686	 * The bytes putback into the stream are no longer
1687	 * available to be read by the server, so adjust the
1688	 * counter accordingly.
1689	 */
1690	ncc = 0;
1691	netip = netibuf;
1692	(void) memset(netip, 0, netibufsize);
1693
1694#ifdef ENCRYPT_NAMES
1695	if (enc_debug) {
1696		(void) fprintf(stderr,
1697			    "\t(encrypt_start) Start DECRYPT using %s\n",
1698			    ENCTYPE_NAME(encr_data.decrypt.type));
1699	}
1700#endif /* ENCRYPT_NAMES */
1701}
1702
1703/*
1704 * encrypt_support
1705 *
1706 * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
1707 * message from a client.
1708 *
1709 * Choose an agreeable method (DES_CFB64) and
1710 * respond with  TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
1711 *
1712 * from: RFC 2946
1713 */
1714static void
1715encrypt_support(char *data, int cnt)
1716{
1717	int lstate = ENCR_STATE_NOT_READY;
1718	int type, use_type = 0;
1719
1720	while (cnt-- > 0 && use_type == 0) {
1721		type = *data++;
1722#ifdef ENCRYPT_NAMES
1723		if (enc_debug)
1724			(void) fprintf(stderr,
1725				    "RCVD ENCRYPT SUPPORT %s\n",
1726				    ENCTYPE_NAME(type));
1727#endif /* ENCRYPT_NAMES */
1728		/*
1729		 * Prefer CFB64
1730		 */
1731		if (type == TELOPT_ENCTYPE_DES_CFB64) {
1732			use_type = type;
1733		}
1734	}
1735	encr_data.encrypt.type = use_type;
1736
1737	if (use_type != TELOPT_ENCTYPE_NULL &&
1738	    authenticated != NULL && authenticated != &NoAuth &&
1739	    auth_status != AUTH_REJECT) {
1740
1741		/* Authenticated -> have session key -> send ENCRYPT IS */
1742		lstate = encrypt_send_encrypt_is();
1743		if (lstate == ENCR_STATE_OK)
1744			encrypt_start_output();
1745	} else if (use_type == TELOPT_ENCTYPE_NULL) {
1746		if (enc_debug)
1747			(void) fprintf(stderr,
1748				    "\t(encrypt_support) Cannot agree "
1749				    "on crypto algorithm, output encryption "
1750				    "disabled.\n");
1751
1752		/*
1753		 * Cannot agree on crypto algorithm
1754		 * RFC 2946 sez:
1755		 *    send "IAC SB ENCRYPT IS NULL IAC SE"
1756		 *    optionally, also send IAC WONT ENCRYPT
1757		 */
1758		write_data("%c%c%c%c%c%c%c",
1759			(uchar_t)IAC,
1760			(uchar_t)SB,
1761			(uchar_t)TELOPT_ENCRYPT,
1762			(uchar_t)ENCRYPT_IS,
1763			(uchar_t)TELOPT_ENCTYPE_NULL,
1764			(uchar_t)IAC,
1765			(uchar_t)SE);
1766		send_wont(TELOPT_ENCRYPT);
1767		netflush();
1768		if (enc_debug)
1769			(void) fprintf(stderr,
1770				    "SENT TELOPT_ENCRYPT ENCRYPT_IS "
1771				    "[NULL]\n");
1772
1773		remopts[TELOPT_ENCRYPT] = OPT_NO;
1774	}
1775	settimer(encr_support);
1776}
1777
1778/*
1779 * encrypt_send_keyid
1780 *
1781 * Sent the key id we will use to the client
1782 */
1783static void
1784encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, boolean_t saveit)
1785{
1786	uchar_t sbbuf[128], *p;
1787
1788	p = sbbuf;
1789
1790	*p++ = IAC;
1791	*p++ = SB;
1792	*p++ = TELOPT_ENCRYPT;
1793	*p++ = (dir == TELNET_DIR_ENCRYPT ? ENCRYPT_ENC_KEYID :
1794		ENCRYPT_DEC_KEYID);
1795	if (saveit) {
1796		if (enc_debug)
1797			(void) fprintf(stderr,
1798				"\t(send_keyid) store %d byte %s keyid\n",
1799				keylen,
1800				(dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1801				"DECRYPT"));
1802
1803		if (dir == TELNET_DIR_ENCRYPT) {
1804			(void) memcpy(encr_data.encrypt.keyid, keyid, keylen);
1805			encr_data.encrypt.keyidlen = keylen;
1806		} else {
1807			(void) memcpy(encr_data.decrypt.keyid, keyid, keylen);
1808			encr_data.decrypt.keyidlen = keylen;
1809		}
1810	}
1811	(void) memcpy(p, keyid, keylen);
1812	p += keylen;
1813
1814	*p++ = IAC;
1815	*p++ = SE;
1816	write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
1817	netflush();
1818
1819	if (enc_debug)
1820		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT %s %d\n",
1821			(dir == TELNET_DIR_ENCRYPT ? "ENC_KEYID" :
1822			"DEC_KEYID"), keyid[0]);
1823}
1824
1825/*
1826 * encrypt_reply
1827 *
1828 * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
1829 * message, process it accordingly.
1830 * If the vector is acceptable, tell client we are encrypting and
1831 * enable encryption on our write stream.
1832 *
1833 * Negotiate the KEYID next..
1834 * RFC 2946, 2952
1835 */
1836static void
1837encrypt_reply(char *data, int len)
1838{
1839	uchar_t type = (uchar_t)(*data++);
1840	uchar_t result = (uchar_t)(*data);
1841	int lstate;
1842
1843#ifdef ENCRYPT_NAMES
1844	if (enc_debug)
1845		(void) fprintf(stderr,
1846			"\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
1847			ENCRYPT_NAME(type),
1848			(result == CFB64_IV_OK ? "CFB64_IV_OK" :
1849			"CFB64_IV_BAD"), len);
1850#endif /* ENCRYPT_NAMES */
1851
1852	lstate = encr_data.encrypt.state;
1853	if (enc_debug)
1854		(void) fprintf(stderr,
1855			"\t(encrypt_reply) initial ENCRYPT state = %d\n",
1856			lstate);
1857	switch (result) {
1858	case CFB64_IV_OK:
1859		if (lstate == ENCR_STATE_NOT_READY)
1860			lstate = ENCR_STATE_IN_PROGRESS;
1861		lstate &= ~ENCR_STATE_NO_RECV_IV; /* we got the IV */
1862		lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont need to send IV */
1863
1864		/*
1865		 * The correct response here is to send the encryption key id
1866		 * RFC 2752.
1867		 *
1868		 * Send keyid 0 to indicate that we will just use default
1869		 * keys.
1870		 */
1871		encrypt_send_keyid(TELNET_DIR_ENCRYPT, (uchar_t *)"\0", 1, 1);
1872
1873		break;
1874	case CFB64_IV_BAD:
1875		/*
1876		 * Clear the ivec
1877		 */
1878		(void) memset(encr_data.encrypt.ivec, 0, sizeof (Block));
1879		lstate = ENCR_STATE_NOT_READY;
1880		break;
1881	default:
1882		if (enc_debug)
1883			(void) fprintf(stderr,
1884				"\t(encrypt_reply) Got unknown IV value in "
1885				"REPLY message\n");
1886		lstate = ENCR_STATE_NOT_READY;
1887		break;
1888	}
1889
1890	encr_data.encrypt.state = lstate;
1891	if (lstate == ENCR_STATE_NOT_READY) {
1892		encr_data.encrypt.autoflag = 0;
1893		encr_data.encrypt.type = ENCTYPE_NULL;
1894		if (enc_debug)
1895			(void) fprintf(stderr,
1896				    "\t(encrypt_reply) encrypt.autoflag = "
1897				    "OFF\n");
1898	} else {
1899		encr_data.encrypt.type = type;
1900		if ((lstate == ENCR_STATE_OK) && encr_data.encrypt.autoflag)
1901			encrypt_start_output();
1902	}
1903
1904	if (enc_debug)
1905		(void) fprintf(stderr,
1906			    "\t(encrypt_reply) ENCRYPT final state = %d\n",
1907			    lstate);
1908}
1909
1910static void
1911encrypt_set_keyid_state(uchar_t *keyid, int *keyidlen, int dir)
1912{
1913	int lstate;
1914
1915	lstate = (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state :
1916		encr_data.decrypt.state);
1917
1918	if (enc_debug)
1919		(void) fprintf(stderr,
1920			    "\t(set_keyid_state) %s initial state = %d\n",
1921			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1922			    "DECRYPT"), lstate);
1923
1924	/*
1925	 * Currently, we only support using the default keyid,
1926	 * so it should be an error if the len > 1 or the keyid != 0.
1927	 */
1928	if (*keyidlen != 1 || (*keyid != '\0')) {
1929		if (enc_debug)
1930			(void) fprintf(stderr,
1931				    "\t(set_keyid_state) unexpected keyid: "
1932				    "len=%d value=%d\n", *keyidlen, *keyid);
1933		*keyidlen = 0;
1934		syslog(LOG_ERR, "rcvd unexpected keyid %d  - only keyid of 0 "
1935		    "is supported",  *keyid);
1936	} else {
1937		/*
1938		 * We move to the "IN_PROGRESS" state.
1939		 */
1940		if (lstate == ENCR_STATE_NOT_READY)
1941			lstate = ENCR_STATE_IN_PROGRESS;
1942		/*
1943		 * Clear the NO_KEYID bit because we now have a valid keyid
1944		 */
1945		lstate &= ~ENCR_STATE_NO_KEYID;
1946	}
1947
1948	if (enc_debug)
1949		(void) fprintf(stderr,
1950			    "\t(set_keyid_state) %s final state = %d\n",
1951			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1952			    "DECRYPT"), lstate);
1953
1954	if (dir == TELNET_DIR_ENCRYPT)
1955		encr_data.encrypt.state = lstate;
1956	else
1957		encr_data.decrypt.state = lstate;
1958}
1959
1960/*
1961 * encrypt_keyid
1962 *
1963 * Set the keyid value in the key_info structure.
1964 * if necessary send a response to the sender
1965 */
1966static void
1967encrypt_keyid(uchar_t *newkeyid, int *keyidlen, uchar_t *keyid,
1968	int len, int dir)
1969{
1970	if (len > TELNET_MAXNUMKEYS) {
1971		if (enc_debug)
1972			(void) fprintf(stderr,
1973				    "\t(keyid) keylen too big (%d)\n", len);
1974		return;
1975	}
1976
1977	if (enc_debug) {
1978		(void) fprintf(stderr, "\t(keyid) set KEYID for %s len = %d\n",
1979			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
1980			    "DECRYPT"), len);
1981	}
1982
1983	if (len == 0) {
1984		if (*keyidlen == 0) {
1985			if (enc_debug)
1986				(void) fprintf(stderr,
1987					    "\t(keyid) Got 0 length keyid - "
1988					    "failure\n");
1989			return;
1990		}
1991		*keyidlen = 0;
1992		encrypt_set_keyid_state(newkeyid, keyidlen, dir);
1993
1994	} else if (len != *keyidlen || memcmp(keyid, newkeyid, len)) {
1995		if (enc_debug)
1996			(void) fprintf(stderr,
1997				    "\t(keyid) Setting new key (%d bytes)\n",
1998				    len);
1999
2000		*keyidlen = len;
2001		(void) memcpy(newkeyid, keyid, len);
2002
2003		encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2004	} else {
2005		encrypt_set_keyid_state(newkeyid, keyidlen, dir);
2006
2007		if (enc_debug)
2008			(void) fprintf(stderr,
2009				    "\t(keyid) %s Key already in place,"
2010				    "state = %d autoflag=%d\n",
2011			(dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT"),
2012			(dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state:
2013			encr_data.decrypt.state),
2014			(dir == TELNET_DIR_ENCRYPT ?
2015				encr_data.encrypt.autoflag:
2016				encr_data.decrypt.autoflag));
2017
2018		/* key already in place */
2019		if ((encr_data.encrypt.state == ENCR_STATE_OK) &&
2020		    dir == TELNET_DIR_ENCRYPT && encr_data.encrypt.autoflag) {
2021			encrypt_start_output();
2022		}
2023		return;
2024	}
2025
2026	if (enc_debug)
2027		(void) fprintf(stderr, "\t(keyid) %s final state = %d\n",
2028			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
2029			    "DECRYPT"),
2030			    (dir == TELNET_DIR_ENCRYPT ?
2031			    encr_data.encrypt.state :
2032			    encr_data.decrypt.state));
2033
2034	encrypt_send_keyid(dir, newkeyid, *keyidlen, 0);
2035}
2036
2037/*
2038 * encrypt_enc_keyid
2039 *
2040 * We received the ENC_KEYID message from a client indicating that
2041 * the client wishes to verify that the indicated keyid maps to a
2042 * valid key.
2043 */
2044static void
2045encrypt_enc_keyid(char *data, int cnt)
2046{
2047	/*
2048	 * Verify the decrypt keyid is valid
2049	 */
2050	encrypt_keyid(encr_data.decrypt.keyid, &encr_data.decrypt.keyidlen,
2051		    (uchar_t *)data, cnt, TELNET_DIR_DECRYPT);
2052}
2053
2054/*
2055 * encrypt_dec_keyid
2056 *
2057 * We received the DEC_KEYID message from a client indicating that
2058 * the client wants to verify that the indicated keyid maps to a valid key.
2059 */
2060static void
2061encrypt_dec_keyid(char *data, int cnt)
2062{
2063	encrypt_keyid(encr_data.encrypt.keyid, &encr_data.encrypt.keyidlen,
2064		    (uchar_t *)data, cnt, TELNET_DIR_ENCRYPT);
2065}
2066
2067/*
2068 * encrypt_session_key
2069 *
2070 * Store the session key in the encryption data record
2071 */
2072static void
2073encrypt_session_key(Session_Key *key, cipher_info_t *cinfo)
2074{
2075	if (key == NULL || key->type != SK_DES) {
2076		if (enc_debug)
2077			(void) fprintf(stderr,
2078				    "\t(session_key) Cannot set krb5 "
2079				    "session key (unknown type = %d)\n",
2080				    key ? key->type : -1);
2081	}
2082	if (enc_debug)
2083		(void) fprintf(stderr,
2084			    "\t(session_key) Settting session key "
2085			    "for server\n");
2086
2087	/* store the key in the cipher info data struct */
2088	(void) memcpy(cinfo->krbdes_key, (void *)key->data, sizeof (Block));
2089
2090	/*
2091	 * Now look to see if we still need to send the key and start
2092	 * encrypting.
2093	 *
2094	 * If so, go ahead an call it now that we have the key.
2095	 */
2096	if (cinfo->need_start) {
2097		if (encrypt_send_encrypt_is() == ENCR_STATE_OK) {
2098			cinfo->need_start = 0;
2099		}
2100	}
2101}
2102
2103/*
2104 * new_env
2105 *
2106 * Used to add an environment variable and value to the
2107 * linked list structure.
2108 */
2109static int
2110new_env(const char *name, const char *value)
2111{
2112	struct envlist *env;
2113
2114	env = malloc(sizeof (struct envlist));
2115	if (env == NULL)
2116		return (1);
2117	if ((env->name = strdup(name)) == NULL) {
2118		free(env);
2119		return (1);
2120	}
2121	if ((env->value = strdup(value)) == NULL) {
2122		free(env->name);
2123		free(env);
2124		return (1);
2125	}
2126	env->delete = 0;
2127	env->next = envlist_head;
2128	envlist_head = env;
2129	return (0);
2130}
2131
2132/*
2133 * del_env
2134 *
2135 * Used to delete an environment variable from the linked list
2136 * structure.  We just set a flag because we will delete the list
2137 * anyway before we exec login.
2138 */
2139static int
2140del_env(const char *name)
2141{
2142	struct envlist *env;
2143
2144	for (env = envlist_head; env; env = env->next) {
2145		if (strcmp(env->name, name) == 0) {
2146			env->delete = 1;
2147			break;
2148		}
2149	}
2150	return (0);
2151}
2152
2153static int
2154issock(int fd)
2155{
2156	struct stat stats;
2157
2158	if (fstat(fd, &stats) == -1)
2159		return (0);
2160	return (S_ISSOCK(stats.st_mode));
2161}
2162
2163/*
2164 * audit_telnet_settid stores the terminal id while it is still
2165 * available.  Subsequent calls to adt_load_hostname() return
2166 * the id which is stored here.
2167 */
2168static int
2169audit_telnet_settid(int sock) {
2170	adt_session_data_t	*ah;
2171	adt_termid_t		*termid;
2172	int			rc;
2173
2174	if ((rc = adt_start_session(&ah, NULL, 0)) == 0) {
2175		if ((rc = adt_load_termid(sock, &termid)) == 0) {
2176			if ((rc = adt_set_user(ah, ADT_NO_AUDIT,
2177			    ADT_NO_AUDIT, 0, ADT_NO_AUDIT,
2178			    termid, ADT_SETTID)) == 0)
2179				(void) adt_set_proc(ah);
2180			free(termid);
2181		}
2182		(void) adt_end_session(ah);
2183	}
2184	return (rc);
2185}
2186
2187/* ARGSUSED */
2188int
2189main(int argc, char *argv[])
2190{
2191	struct sockaddr_storage from;
2192	int on = 1;
2193	socklen_t fromlen;
2194	int issocket;
2195#if	defined(DEBUG)
2196	ushort_t porttouse = 0;
2197	boolean_t standalone = 0;
2198#endif /* defined(DEBUG) */
2199	extern char *optarg;
2200	char c;
2201	int tos = -1;
2202
2203	while ((c = getopt(argc, argv, TELNETD_OPTS DEBUG_OPTS)) != -1) {
2204		switch (c) {
2205#if defined(DEBUG)
2206		case 'p':
2207			/*
2208			 * note: alternative port number only used in
2209			 * standalone mode.
2210			 */
2211			porttouse = atoi(optarg);
2212			standalone = 1;
2213			break;
2214		case 'e':
2215			enc_debug = 1;
2216			break;
2217#endif /* DEBUG */
2218		case 'a':
2219			if (strcasecmp(optarg, "none") == 0) {
2220				auth_level = 0;
2221			} else if (strcasecmp(optarg, "user") == 0) {
2222				auth_level = AUTH_USER;
2223			} else if (strcasecmp(optarg, "valid") == 0) {
2224				auth_level = AUTH_VALID;
2225			} else if (strcasecmp(optarg, "off") == 0) {
2226				auth_level = -1;
2227				negotiate_auth_krb5 = 0;
2228			} else if (strcasecmp(optarg, "debug") == 0) {
2229				auth_debug = 1;
2230			} else {
2231				syslog(LOG_ERR,
2232				    "unknown authentication level specified "
2233				    "with \'-a\' option (%s)", optarg);
2234				auth_level = AUTH_USER;
2235			}
2236			break;
2237		case 'X':
2238			/* disable authentication negotiation */
2239			negotiate_auth_krb5 = 0;
2240			break;
2241		case 'R':
2242		case 'M':
2243			if (optarg != NULL) {
2244				int ret = krb5_init();
2245				if (ret) {
2246					syslog(LOG_ERR,
2247						"Unable to use Kerberos V5 as "
2248						"requested, exiting");
2249					exit(1);
2250				}
2251				(void) krb5_set_default_realm(telnet_context,
2252				    optarg);
2253				syslog(LOG_NOTICE,
2254				    "using %s as default KRB5 realm", optarg);
2255			}
2256			break;
2257		case 'S':
2258			telnet_srvtab = (char *)strdup(optarg);
2259			break;
2260		case 'E': /* disable automatic encryption */
2261			negotiate_encrypt = B_FALSE;
2262			break;
2263		case 'U':
2264			resolve_hostname = 1;
2265			break;
2266		case 's':
2267			if (optarg == NULL || (tos = atoi(optarg)) < 0 ||
2268			    tos > 255) {
2269				syslog(LOG_ERR, "telnetd: illegal tos value: "
2270				    "%s\n", optarg);
2271			} else {
2272				if (tos < 0)
2273					tos = 020;
2274			}
2275			break;
2276		case 'h':
2277			show_hostinfo = 0;
2278			break;
2279		default:
2280			syslog(LOG_ERR, "telnetd: illegal cmd line option %c",
2281			    c);
2282			break;
2283		}
2284	}
2285
2286	netibufsize = BUFSIZ;
2287	if (!(netibuf = (char *)malloc(netibufsize)))
2288		syslog(LOG_ERR, "netibuf malloc failed\n");
2289	(void) memset(netibuf, 0, netibufsize);
2290	netip = netibuf;
2291
2292#if	defined(DEBUG)
2293	if (standalone) {
2294		int s, ns, foo;
2295		struct servent *sp;
2296		static struct sockaddr_in6 sin6 = { AF_INET6 };
2297		int option = 1;
2298
2299		if (porttouse) {
2300			sin6.sin6_port = htons(porttouse);
2301		} else {
2302			sp = getservbyname("telnet", "tcp");
2303			if (sp == 0) {
2304				(void) fprintf(stderr,
2305					    "telnetd: tcp/telnet: "
2306					    "unknown service\n");
2307				exit(EXIT_FAILURE);
2308			}
2309			sin6.sin6_port = sp->s_port;
2310		}
2311
2312		s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
2313		if (s < 0) {
2314			perror("telnetd: socket");
2315			exit(EXIT_FAILURE);
2316		}
2317		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&option,
2318		    sizeof (option)) == -1)
2319			perror("setsockopt SO_REUSEADDR");
2320		if (bind(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) {
2321			perror("bind");
2322			exit(EXIT_FAILURE);
2323		}
2324		if (listen(s, 32) < 0) {
2325			perror("listen");
2326			exit(EXIT_FAILURE);
2327		}
2328
2329		/* automatically reap all child processes */
2330		(void) signal(SIGCHLD, SIG_IGN);
2331
2332		for (;;) {
2333			pid_t pid;
2334
2335			foo = sizeof (sin6);
2336			ns = accept(s, (struct sockaddr *)&sin6, &foo);
2337			if (ns < 0) {
2338				perror("accept");
2339				exit(EXIT_FAILURE);
2340			}
2341			pid = fork();
2342			if (pid == -1) {
2343				perror("fork");
2344				exit(EXIT_FAILURE);
2345			}
2346			if (pid == 0) {
2347				(void) dup2(ns, 0);
2348				(void) close(s);
2349				(void) signal(SIGCHLD, SIG_DFL);
2350				break;
2351			}
2352			(void) close(ns);
2353		}
2354	}
2355#endif /* defined(DEBUG) */
2356
2357	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
2358
2359	issocket = issock(0);
2360	if (!issocket)
2361		fatal(0, "stdin is not a socket file descriptor");
2362
2363	fromlen = (socklen_t)sizeof (from);
2364	(void) memset((char *)&from, 0, sizeof (from));
2365	if (getpeername(0, (struct sockaddr *)&from, &fromlen)
2366	    < 0) {
2367		(void) fprintf(stderr, "%s: ", argv[0]);
2368		perror("getpeername");
2369		_exit(EXIT_FAILURE);
2370	}
2371
2372	if (audit_telnet_settid(0)) {	/* set terminal ID */
2373		(void) fprintf(stderr, "%s: ", argv[0]);
2374		perror("audit");
2375		exit(EXIT_FAILURE);
2376	}
2377
2378	if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on,
2379						sizeof (on)) < 0) {
2380		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
2381	}
2382
2383	/*
2384	 * Set the TOS value
2385	 */
2386	if (tos != -1 &&
2387	    setsockopt(0, IPPROTO_IP, IP_TOS,
2388		    (char *)&tos, sizeof (tos)) < 0 &&
2389		errno != ENOPROTOOPT) {
2390		syslog(LOG_ERR, "setsockopt (IP_TOS %d): %m", tos);
2391	}
2392
2393	if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
2394	    sizeof (on)) < 0) {
2395		syslog(LOG_WARNING, "setsockopt (SO_OOBINLINE): %m");
2396	}
2397
2398	/* set the default PAM service name */
2399	(void) strcpy(pam_svc_name, "telnet");
2400
2401	doit(0, &from);
2402	return (EXIT_SUCCESS);
2403}
2404
2405static char	*terminaltype = 0;
2406
2407/*
2408 * ttloop
2409 *
2410 *	A small subroutine to flush the network output buffer, get some data
2411 * from the network, and pass it through the telnet state machine.  We
2412 * also flush the pty input buffer (by dropping its data) if it becomes
2413 * too full.
2414 */
2415static void
2416ttloop(void)
2417{
2418	if (nfrontp-nbackp) {
2419		netflush();
2420	}
2421read_again:
2422	ncc = read(net, netibuf, netibufsize);
2423	if (ncc < 0) {
2424		if (errno == EINTR)
2425			goto read_again;
2426		syslog(LOG_INFO, "ttloop:  read: %m");
2427		exit(EXIT_FAILURE);
2428	} else if (ncc == 0) {
2429		syslog(LOG_INFO, "ttloop:  peer closed connection\n");
2430		exit(EXIT_FAILURE);
2431	}
2432
2433	netip = netibuf;
2434	telrcv();		/* state machine */
2435	if (ncc > 0) {
2436		pfrontp = pbackp = ptyobuf;
2437		telrcv();
2438	}
2439}
2440
2441static void
2442send_do(int option)
2443{
2444	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option);
2445}
2446
2447static void
2448send_will(int option)
2449{
2450	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option);
2451}
2452
2453static void
2454send_wont(int option)
2455{
2456	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WONT, (uchar_t)option);
2457}
2458
2459
2460/*
2461 * getauthtype
2462 *
2463 * Negotiate automatic authentication, is possible.
2464 */
2465static int
2466getauthtype(char *username, int *len)
2467{
2468	int init_status = -1;
2469
2470	init_status = krb5_init();
2471
2472	if (auth_level == -1 || init_status != 0) {
2473		remopts[TELOPT_AUTHENTICATION] = OPT_NO;
2474		myopts[TELOPT_AUTHENTICATION] = OPT_NO;
2475		negotiate_auth_krb5 = B_FALSE;
2476		negotiate_encrypt = B_FALSE;
2477		return (AUTH_REJECT);
2478	}
2479
2480	if (init_status == 0 && auth_level != -1) {
2481		if (negotiate_auth_krb5) {
2482			/*
2483			 * Negotiate Authentication FIRST
2484			 */
2485			send_do(TELOPT_AUTHENTICATION);
2486			remopts[TELOPT_AUTHENTICATION] =
2487				OPT_YES_BUT_ALWAYS_LOOK;
2488		}
2489		while (sequenceIs(authopt, getauth))
2490			ttloop();
2491
2492		if (remopts[TELOPT_AUTHENTICATION] == OPT_YES) {
2493			/*
2494			 * Request KRB5 Mutual authentication and if that fails,
2495			 * KRB5 1-way client authentication
2496			 */
2497			uchar_t sbbuf[MAXOPTLEN], *p;
2498			p = sbbuf;
2499			*p++ = (uchar_t)IAC;
2500			*p++ = (uchar_t)SB;
2501			*p++ = (uchar_t)TELOPT_AUTHENTICATION;
2502			*p++ = (uchar_t)TELQUAL_SEND;
2503			if (negotiate_auth_krb5) {
2504				*p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2505				*p++ = (uchar_t)(AUTH_WHO_CLIENT |
2506						AUTH_HOW_MUTUAL |
2507						AUTH_ENCRYPT_ON);
2508				*p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2509				*p++ = (uchar_t)(AUTH_WHO_CLIENT |
2510						AUTH_HOW_MUTUAL);
2511				*p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
2512				*p++ = (uchar_t)(AUTH_WHO_CLIENT|
2513						AUTH_HOW_ONE_WAY);
2514			} else {
2515				*p++ = (uchar_t)AUTHTYPE_NULL;
2516			}
2517			*p++ = (uchar_t)IAC;
2518			*p++ = (uchar_t)SE;
2519
2520			write_data_len((const char *)sbbuf,
2521				    (size_t)(p - sbbuf));
2522			netflush();
2523			if (auth_debug)
2524				(void) fprintf(stderr,
2525					    "SENT TELOPT_AUTHENTICATION "
2526					    "[data]\n");
2527
2528			/* auth_wait returns the authentication level */
2529			/* status = auth_wait(username, len); */
2530			while (sequenceIs(authdone, getauth))
2531				ttloop();
2532			/*
2533			 * Now check to see if the user is valid or not
2534			 */
2535			if (authenticated == NULL || authenticated == &NoAuth)
2536				auth_status = AUTH_REJECT;
2537			else {
2538				/*
2539				 * We cant be VALID until the user status is
2540				 * checked.
2541				 */
2542				if (auth_status == AUTH_VALID)
2543					auth_status = AUTH_USER;
2544
2545				if (authenticated->AuthName ==
2546					AUTHTYPE_KERBEROS_V5)
2547					auth_status = krb5_user_status(
2548						username, *len, auth_status);
2549			}
2550		}
2551	}
2552	return (auth_status);
2553}
2554
2555static void
2556getencrtype(void)
2557{
2558	if (krb5_privacy_allowed() && negotiate_encrypt) {
2559		if (myopts[TELOPT_ENCRYPT] != OPT_YES) {
2560			if (!sent_will_encrypt) {
2561				send_will(TELOPT_ENCRYPT);
2562				sent_will_encrypt = B_TRUE;
2563			}
2564			if (enc_debug)
2565				(void) fprintf(stderr, "SENT WILL ENCRYPT\n");
2566		}
2567		if (remopts[TELOPT_ENCRYPT] != OPT_YES) {
2568			if (!sent_do_encrypt) {
2569				send_do(TELOPT_ENCRYPT);
2570				sent_do_encrypt = B_TRUE;
2571				remopts[TELOPT_ENCRYPT] =
2572				    OPT_YES_BUT_ALWAYS_LOOK;
2573			}
2574			if (enc_debug)
2575				(void) fprintf(stderr, "SENT DO ENCRYPT\n");
2576		}
2577		myopts[TELOPT_ENCRYPT] = OPT_YES;
2578
2579		while (sequenceIs(encropt, getencr))
2580		    ttloop();
2581
2582		if (auth_status != AUTH_REJECT &&
2583		    remopts[TELOPT_ENCRYPT] == OPT_YES &&
2584		    myopts[TELOPT_ENCRYPT] == OPT_YES) {
2585
2586			if (sent_encrypt_support == B_FALSE) {
2587				write_data("%c%c%c%c%c%c%c",
2588					(uchar_t)IAC,
2589					(uchar_t)SB,
2590					(uchar_t)TELOPT_ENCRYPT,
2591					(uchar_t)ENCRYPT_SUPPORT,
2592					(uchar_t)TELOPT_ENCTYPE_DES_CFB64,
2593					(uchar_t)IAC,
2594					(uchar_t)SE);
2595
2596				netflush();
2597			}
2598			/*
2599			 * Now wait for a response to these messages before
2600			 * continuing...
2601			 * Look for TELOPT_ENCRYPT suboptions
2602			 */
2603			while (sequenceIs(encr_support, getencr))
2604				ttloop();
2605		}
2606	} else {
2607		/* Dont need responses to these, so dont wait for them */
2608		settimer(encropt);
2609		remopts[TELOPT_ENCRYPT] = OPT_NO;
2610		myopts[TELOPT_ENCRYPT] = OPT_NO;
2611	}
2612
2613}
2614
2615/*
2616 * getterminaltype
2617 *
2618 * Ask the other end to send along its terminal type.
2619 * Output is the variable terminaltype filled in.
2620 */
2621static void
2622getterminaltype(void)
2623{
2624	/*
2625	 * The remote side may have already sent this info, so
2626	 * dont ask for these options if the other side already
2627	 * sent the information.
2628	 */
2629	if (sequenceIs(ttypeopt, getterminal)) {
2630		send_do(TELOPT_TTYPE);
2631		remopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK;
2632	}
2633
2634	if (sequenceIs(nawsopt, getterminal)) {
2635		send_do(TELOPT_NAWS);
2636		remopts[TELOPT_NAWS] = OPT_YES_BUT_ALWAYS_LOOK;
2637	}
2638
2639	if (sequenceIs(xdisplocopt, getterminal)) {
2640		send_do(TELOPT_XDISPLOC);
2641		remopts[TELOPT_XDISPLOC] = OPT_YES_BUT_ALWAYS_LOOK;
2642	}
2643
2644	if (sequenceIs(environopt, getterminal)) {
2645		send_do(TELOPT_NEW_ENVIRON);
2646		remopts[TELOPT_NEW_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2647	}
2648
2649	if (sequenceIs(oenvironopt, getterminal)) {
2650		send_do(TELOPT_OLD_ENVIRON);
2651		remopts[TELOPT_OLD_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
2652	}
2653
2654	/* make sure encryption is started here */
2655	while (auth_status != AUTH_REJECT &&
2656		authenticated != &NoAuth && authenticated != NULL &&
2657		remopts[TELOPT_ENCRYPT] == OPT_YES &&
2658		encr_data.encrypt.autoflag &&
2659		encr_data.encrypt.state != ENCR_STATE_OK) {
2660	    if (enc_debug)
2661		(void) fprintf(stderr, "getterminaltype() forcing encrypt\n");
2662	    ttloop();
2663	}
2664
2665	if (enc_debug) {
2666	    (void) fprintf(stderr, "getterminaltype() encryption %sstarted\n",
2667		    encr_data.encrypt.state == ENCR_STATE_OK ? "" : "not ");
2668	}
2669
2670	while (sequenceIs(ttypeopt, getterminal) ||
2671	    sequenceIs(nawsopt, getterminal) ||
2672	    sequenceIs(xdisplocopt, getterminal) ||
2673	    sequenceIs(environopt, getterminal) ||
2674	    sequenceIs(oenvironopt, getterminal)) {
2675		ttloop();
2676	}
2677
2678
2679	if (remopts[TELOPT_TTYPE] == OPT_YES) {
2680		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2681		    (uchar_t)TELOPT_TTYPE, (uchar_t)TELQUAL_SEND,
2682		    (uchar_t)IAC, (uchar_t)SE };
2683
2684		write_data_len((const char *)sbbuf, sizeof (sbbuf));
2685	}
2686	if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2687		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2688		    (uchar_t)TELOPT_XDISPLOC, (uchar_t)TELQUAL_SEND,
2689		    (uchar_t)IAC, (uchar_t)SE };
2690
2691		write_data_len((const char *)sbbuf, sizeof (sbbuf));
2692	}
2693	if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2694		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2695		    (uchar_t)TELOPT_NEW_ENVIRON, (uchar_t)TELQUAL_SEND,
2696		    (uchar_t)IAC, (uchar_t)SE };
2697
2698		write_data_len((const char *)sbbuf, sizeof (sbbuf));
2699	}
2700	if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2701		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
2702		    (uchar_t)TELOPT_OLD_ENVIRON, (uchar_t)TELQUAL_SEND,
2703		    (uchar_t)IAC, (uchar_t)SE };
2704
2705		write_data_len((const char *)sbbuf, sizeof (sbbuf));
2706	}
2707
2708	if (remopts[TELOPT_TTYPE] == OPT_YES) {
2709		while (sequenceIs(ttypesubopt, getterminal)) {
2710			ttloop();
2711		}
2712	}
2713	if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
2714		while (sequenceIs(xdisplocsubopt, getterminal)) {
2715			ttloop();
2716		}
2717	}
2718	if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
2719		while (sequenceIs(environsubopt, getterminal)) {
2720			ttloop();
2721		}
2722	}
2723	if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
2724		while (sequenceIs(oenvironsubopt, getterminal)) {
2725			ttloop();
2726		}
2727	}
2728	init_neg_done = 1;
2729}
2730
2731pid_t pid;
2732
2733/*
2734 * Get a pty, scan input lines.
2735 */
2736static void
2737doit(int f, struct sockaddr_storage *who)
2738{
2739	char *host;
2740	char host_name[MAXHOSTNAMELEN];
2741	int p, t, tt;
2742	struct sgttyb b;
2743	int	ptmfd;	/* fd of logindmux connected to pty */
2744	int	netfd;	/* fd of logindmux connected to netf */
2745	struct	stat	buf;
2746	struct	protocol_arg	telnetp;
2747	struct	strioctl	telnetmod;
2748	struct	envlist	*env, *next;
2749	int	nsize = 0;
2750	char abuf[INET6_ADDRSTRLEN];
2751	struct sockaddr_in *sin;
2752	struct sockaddr_in6 *sin6;
2753	socklen_t wholen;
2754	char username[MAXUSERNAMELEN];
2755	int len;
2756	uchar_t passthru;
2757	char *slavename;
2758
2759	if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
2760		fatalperror(f, "open /dev/ptmx", errno);
2761	}
2762	if (grantpt(p) == -1)
2763		fatal(f, "could not grant slave pty");
2764	if (unlockpt(p) == -1)
2765		fatal(f, "could not unlock slave pty");
2766	if ((slavename = ptsname(p)) == NULL)
2767		fatal(f, "could not enable slave pty");
2768	(void) dup2(f, 0);
2769	if ((t = open(slavename, O_RDWR | O_NOCTTY)) == -1)
2770		fatal(f, "could not open slave pty");
2771	if (ioctl(t, I_PUSH, "ptem") == -1)
2772		fatalperror(f, "ioctl I_PUSH ptem", errno);
2773	if (ioctl(t, I_PUSH, "ldterm") == -1)
2774		fatalperror(f, "ioctl I_PUSH ldterm", errno);
2775	if (ioctl(t, I_PUSH, "ttcompat") == -1)
2776		fatalperror(f, "ioctl I_PUSH ttcompat", errno);
2777
2778	line = slavename;
2779
2780	pty = t;
2781
2782	if (ioctl(t, TIOCGETP, &b) == -1)
2783		syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
2784	b.sg_flags = O_CRMOD|O_XTABS|O_ANYP;
2785	/* XXX - ispeed and ospeed must be non-zero */
2786	b.sg_ispeed = B38400;
2787	b.sg_ospeed = B38400;
2788	if (ioctl(t, TIOCSETN, &b) == -1)
2789		syslog(LOG_INFO, "ioctl TIOCSETN pty t: %m\n");
2790	if (ioctl(pty, TIOCGETP, &b) == -1)
2791		syslog(LOG_INFO, "ioctl TIOCGETP pty pty: %m\n");
2792	b.sg_flags &= ~O_ECHO;
2793	if (ioctl(pty, TIOCSETN, &b) == -1)
2794		syslog(LOG_INFO, "ioctl TIOCSETN pty pty: %m\n");
2795
2796	if (who->ss_family == AF_INET) {
2797		char *addrbuf = NULL;
2798		char *portbuf = NULL;
2799
2800		sin = (struct sockaddr_in *)who;
2801		wholen = sizeof (struct sockaddr_in);
2802
2803		addrbuf = (char *)malloc(wholen);
2804		if (addrbuf == NULL)
2805			fatal(f, "Cannot alloc memory for address info\n");
2806		portbuf = (char *)malloc(sizeof (sin->sin_port));
2807		if (portbuf == NULL) {
2808			free(addrbuf);
2809			fatal(f, "Cannot alloc memory for port info\n");
2810		}
2811
2812		(void) memcpy(addrbuf, (const void *)&sin->sin_addr, wholen);
2813		(void) memcpy(portbuf, (const void *)&sin->sin_port,
2814			    sizeof (sin->sin_port));
2815
2816		if (rsaddr.contents != NULL)
2817			free(rsaddr.contents);
2818
2819		rsaddr.contents = (krb5_octet *)addrbuf;
2820		rsaddr.length = wholen;
2821		rsaddr.addrtype = ADDRTYPE_INET;
2822
2823		if (rsport.contents != NULL)
2824			free(rsport.contents);
2825
2826		rsport.contents = (krb5_octet *)portbuf;
2827		rsport.length = sizeof (sin->sin_port);
2828		rsport.addrtype = ADDRTYPE_IPPORT;
2829	} else if (who->ss_family == AF_INET6) {
2830		struct in_addr ipv4_addr;
2831		char *addrbuf = NULL;
2832		char *portbuf = NULL;
2833
2834		sin6 = (struct sockaddr_in6 *)who;
2835		wholen = sizeof (struct sockaddr_in6);
2836
2837		IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2838				    &ipv4_addr);
2839
2840		addrbuf = (char *)malloc(wholen);
2841		if (addrbuf == NULL)
2842			fatal(f, "Cannot alloc memory for address info\n");
2843
2844		portbuf = (char *)malloc(sizeof (sin6->sin6_port));
2845		if (portbuf == NULL) {
2846			free(addrbuf);
2847			fatal(f, "Cannot alloc memory for port info\n");
2848		}
2849
2850		(void) memcpy((void *) addrbuf,
2851			    (const void *)&ipv4_addr,
2852			    wholen);
2853		/*
2854		 * If we already used rsaddr.contents, free the previous
2855		 * buffer.
2856		 */
2857		if (rsaddr.contents != NULL)
2858			free(rsaddr.contents);
2859
2860		rsaddr.contents = (krb5_octet *)addrbuf;
2861		rsaddr.length = sizeof (ipv4_addr);
2862		rsaddr.addrtype = ADDRTYPE_INET;
2863
2864		(void) memcpy((void *) portbuf, (const void *)&sin6->sin6_port,
2865			    sizeof (sin6->sin6_port));
2866
2867		if (rsport.contents != NULL)
2868			free(rsport.contents);
2869
2870		rsport.contents = (krb5_octet *)portbuf;
2871		rsport.length = sizeof (sin6->sin6_port);
2872		rsport.addrtype = ADDRTYPE_IPPORT;
2873	} else {
2874		syslog(LOG_ERR, "unknown address family %d\n",
2875		    who->ss_family);
2876		fatal(f, "getpeername: unknown address family\n");
2877	}
2878
2879	if (getnameinfo((const struct sockaddr *) who, wholen, host_name,
2880	    sizeof (host_name), NULL, 0, 0) == 0) {
2881		host = host_name;
2882	} else {
2883		/*
2884		 * If the '-U' option was given on the cmd line, we must
2885		 * be able to lookup the hostname
2886		 */
2887		if (resolve_hostname) {
2888			fatal(f, "Couldn't resolve your address into a "
2889			    "host name.\r\nPlease contact your net "
2890			    "administrator");
2891		}
2892
2893		if (who->ss_family == AF_INET6) {
2894			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2895				struct in_addr ipv4_addr;
2896
2897				IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
2898				    &ipv4_addr);
2899				host = (char *)inet_ntop(AF_INET,
2900				    &ipv4_addr, abuf, sizeof (abuf));
2901			} else {
2902				host = (char *)inet_ntop(AF_INET6,
2903				    &sin6->sin6_addr, abuf,
2904				    sizeof (abuf));
2905			}
2906		} else if (who->ss_family == AF_INET) {
2907				host = (char *)inet_ntop(AF_INET,
2908				    &sin->sin_addr, abuf, sizeof (abuf));
2909			}
2910	}
2911	/*
2912	 * Note that sockmod has to be removed since readstream assumes
2913	 * a "raw" TPI endpoint (e.g. it uses getmsg).
2914	 */
2915	if (removemod(f, "sockmod") < 0)
2916		fatalperror(f, "couldn't remove sockmod", errno);
2917
2918	encrypt_init();
2919
2920	/*
2921	 * Push the crypto module on the stream before 'telmod' so it
2922	 * can encrypt/decrypt without interfering with telmod functionality
2923	 * We must push it now because many of the crypto options negotiated
2924	 * initially must be saved in the crypto module (via IOCTL calls).
2925	 */
2926	if (ioctl(f, I_PUSH, "cryptmod") < 0)
2927		fatalperror(f, "ioctl I_PUSH cryptmod", errno);
2928
2929	cryptmod_fd = f;
2930	/*
2931	 * gotta set the encryption clock now because it is often negotiated
2932	 * immediately by the client, and if we wait till after we negotiate
2933	 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
2934	 * option is received.
2935	 */
2936	settimer(getencr);
2937
2938	/*
2939	 * get terminal type.
2940	 */
2941	username[0] = '\0';
2942	len = sizeof (username);
2943
2944	settimer(getterminal);
2945	settimer(getauth);
2946	/*
2947	 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
2948	 */
2949	auth_status = getauthtype(username, &len);
2950	/*
2951	 * Exchange TELOPT_ENCRYPT options per RFC 2946
2952	 */
2953	getencrtype();
2954	getterminaltype();
2955
2956	if (ioctl(f, I_PUSH, "telmod") < 0)
2957		fatalperror(f, "ioctl I_PUSH telmod", errno);
2958
2959	/*
2960	 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
2961	 */
2962	passthru = 1;
2963
2964	telnetmod.ic_cmd = CRYPTPASSTHRU;
2965	telnetmod.ic_timout = -1;
2966	telnetmod.ic_len = sizeof (uchar_t);
2967	telnetmod.ic_dp = (char *)&passthru;
2968
2969	if (ioctl(f, I_STR, &telnetmod) < 0)
2970		fatal(f, "ioctl CRPASSTHRU failed\n");
2971
2972	if (!ncc)
2973		netip = netibuf;
2974
2975	/*
2976	 * readstream will do a getmsg till it receives M_PROTO type
2977	 * T_DATA_REQ from telnetmodopen().  This signals that all data
2978	 * in-flight before telmod was pushed has been received at the
2979	 * stream head.
2980	 */
2981	while ((nsize = readstream(f, netibuf, ncc + netip - netibuf)) > 0) {
2982		ncc += nsize;
2983	}
2984
2985	if (nsize < 0) {
2986		fatalperror(f, "readstream failed\n", errno);
2987	}
2988
2989	/*
2990	 * open logindmux drivers and link them with network and ptm
2991	 * file descriptors.
2992	 */
2993	if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1) {
2994		fatalperror(f, "open /dev/logindmux", errno);
2995	}
2996	if ((netfd = open("/dev/logindmux", O_RDWR)) == -1) {
2997		fatalperror(f, "open /dev/logindmux", errno);
2998	}
2999
3000	if (ioctl(ptmfd, I_LINK, p) < 0)
3001		fatal(f, "ioctl I_LINK of /dev/ptmx failed\n");
3002	if (ioctl(netfd, I_LINK, f) < 0)
3003		fatal(f, "ioctl I_LINK of tcp connection failed\n");
3004
3005	/*
3006	 * Figure out the device number of ptm's mux fd, and pass that
3007	 * to the net's mux.
3008	 */
3009	if (fstat(ptmfd, &buf) < 0) {
3010		fatalperror(f, "fstat ptmfd failed", errno);
3011	}
3012	telnetp.dev = buf.st_rdev;
3013	telnetp.flag = 0;
3014
3015	telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
3016	telnetmod.ic_timout = -1;
3017	telnetmod.ic_len = sizeof (struct protocol_arg);
3018	telnetmod.ic_dp = (char *)&telnetp;
3019
3020	if (ioctl(netfd, I_STR, &telnetmod) < 0)
3021		fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
3022
3023	/*
3024	 * Figure out the device number of the net's mux fd, and pass that
3025	 * to the ptm's mux.
3026	 */
3027	if (fstat(netfd, &buf) < 0) {
3028		fatalperror(f, "fstat netfd failed", errno);
3029	}
3030	telnetp.dev = buf.st_rdev;
3031	telnetp.flag = 1;
3032
3033	telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
3034	telnetmod.ic_timout = -1;
3035	telnetmod.ic_len = sizeof (struct protocol_arg);
3036	telnetmod.ic_dp = (char *)&telnetp;
3037
3038	if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
3039		fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
3040
3041	net = netfd;
3042	master = ptmfd;
3043	cryptmod_fd = netfd;
3044
3045	/*
3046	 * Show banner that getty never gave, but
3047	 * only if the user did not automatically authenticate.
3048	 */
3049	if (getenv("USER") == NULL && auth_status < AUTH_USER)
3050		showbanner();
3051
3052	/*
3053	 * If the user automatically authenticated with Kerberos
3054	 * we must set the service name that PAM will use.  We
3055	 * need to do it BEFORE the child fork so that 'cleanup'
3056	 * in the parent can call the PAM cleanup stuff with the
3057	 * same PAM service that /bin/login will use to authenticate
3058	 * this session.
3059	 */
3060	if (auth_level >= 0 && auth_status >= AUTH_USER &&
3061	    (AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) {
3062		(void) strcpy(pam_svc_name, "ktelnet");
3063	}
3064	/*
3065	 * Request to do suppress go ahead.
3066	 *
3067	 * Send this before sending the TELOPT_ECHO stuff below because
3068	 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
3069	 * that has them turn off local echo mode if SGA is not received first.
3070	 * This also has the odd side-effect of causing the client to enable
3071	 * encryption and then immediately disable it during the ECHO option
3072	 * negotiations.  Its just better to to SGA first now that we support
3073	 * encryption.
3074	 */
3075	if (!myopts[TELOPT_SGA]) {
3076	    dooption(TELOPT_SGA);
3077	}
3078
3079	/*
3080	 * Pretend we got a DO ECHO from the client if we have not
3081	 * yet negotiated the ECHO.
3082	 */
3083	if (!myopts[TELOPT_ECHO]) {
3084	    dooption(TELOPT_ECHO);
3085	}
3086
3087	/*
3088	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
3089	 * because 4.2 clients are unable to deal with TCP urgent data.
3090	 *
3091	 * To find out, we send out a "DO ECHO".  If the remote system
3092	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
3093	 * that fact ("WILL ECHO" ==> that the client will echo what
3094	 * WE, the server, sends it; it does NOT mean that the client will
3095	 * echo the terminal input).
3096	 */
3097	send_do(TELOPT_ECHO);
3098	remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
3099
3100	if ((pid = fork()) < 0)
3101		fatalperror(netfd, "fork", errno);
3102	if (pid)
3103		telnet(net, master);
3104	/*
3105	 * The child process needs to be the session leader
3106	 * and have the pty as its controlling tty.  Thus we need
3107	 * to re-open the slave side of the pty no without
3108	 * the O_NOCTTY flag that we have been careful to
3109	 * use up to this point.
3110	 */
3111	(void) setsid();
3112
3113	tt = open(line, O_RDWR);
3114	if (tt < 0)
3115		fatalperror(netfd, line, errno);
3116	(void) close(netfd);
3117	(void) close(ptmfd);
3118	(void) close(f);
3119	(void) close(p);
3120	(void) close(t);
3121	if (tt != 0)
3122		(void) dup2(tt, 0);
3123	if (tt != 1)
3124		(void) dup2(tt, 1);
3125	if (tt != 2)
3126		(void) dup2(tt, 2);
3127	if (tt > 2)
3128		(void) close(tt);
3129
3130	if (terminaltype)
3131		(void) local_setenv("TERM", terminaltype+5, 1);
3132	/*
3133	 * 	-h : pass on name of host.
3134	 *		WARNING:  -h is accepted by login if and only if
3135	 *			getuid() == 0.
3136	 * 	-p : don't clobber the environment (so terminal type stays set).
3137	 */
3138	{
3139		/* System V login expects a utmp entry to already be there */
3140		struct utmpx ut;
3141		(void) memset((char *)&ut, 0, sizeof (ut));
3142		(void) strncpy(ut.ut_user, ".telnet", sizeof (ut.ut_user));
3143		(void) strncpy(ut.ut_line, line, sizeof (ut.ut_line));
3144		ut.ut_pid = getpid();
3145		ut.ut_id[0] = 't';
3146		ut.ut_id[1] = (char)SC_WILDC;
3147		ut.ut_id[2] = (char)SC_WILDC;
3148		ut.ut_id[3] = (char)SC_WILDC;
3149		ut.ut_type = LOGIN_PROCESS;
3150		ut.ut_exit.e_termination = 0;
3151		ut.ut_exit.e_exit = 0;
3152		(void) time(&ut.ut_tv.tv_sec);
3153		if (makeutx(&ut) == NULL)
3154			syslog(LOG_INFO, "in.telnetd:\tmakeutx failed");
3155	}
3156
3157	/*
3158	 * Load in the cached environment variables and either
3159	 * set/unset them in the environment.
3160	 */
3161	for (next = envlist_head; next; ) {
3162		env = next;
3163		if (env->delete)
3164			(void) local_unsetenv(env->name);
3165		else
3166			(void) local_setenv(env->name, env->value, 1);
3167		free(env->name);
3168		free(env->value);
3169		next = env->next;
3170		free(env);
3171	}
3172
3173	if (!username || !username[0])
3174		auth_status = AUTH_REJECT; /* we dont know who this is */
3175
3176	/* If the current auth status is less than the required level, exit */
3177	if (auth_status < auth_level) {
3178		fatal(net, "Authentication failed\n");
3179		exit(EXIT_FAILURE);
3180	}
3181
3182	/*
3183	 * If AUTH_VALID (proper authentication REQUIRED and we have
3184	 * a krb5_name), exec '/bin/login', make sure it uses the
3185	 * correct PAM service name (pam_svc_name). If possible,
3186	 * make sure the krb5 authenticated user's name (krb5_name)
3187	 * is in the PAM REPOSITORY for krb5.
3188	 */
3189	if (auth_level >= 0 &&
3190	    (auth_status == AUTH_VALID || auth_status == AUTH_USER) &&
3191	    ((krb5_name != NULL) && strlen(krb5_name)) &&
3192	    ((AuthenticatingUser != NULL) && strlen(AuthenticatingUser))) {
3193		(void) execl(LOGIN_PROGRAM, "login",
3194			    "-p",
3195			    "-d", slavename,
3196			    "-h", host,
3197			    "-u", krb5_name,
3198			    "-s", pam_svc_name,
3199			    "-R", KRB5_REPOSITORY_NAME,
3200			    AuthenticatingUser, 0);
3201	} else if (auth_level >= 0 &&
3202		auth_status >= AUTH_USER &&
3203		(((AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) ||
3204		getenv("USER"))) {
3205		/*
3206		 * If we only know the name but not the principal,
3207		 * login will have to authenticate further.
3208		 */
3209		(void) execl(LOGIN_PROGRAM, "login",
3210		    "-p",
3211		    "-d", slavename,
3212		    "-h", host,
3213		    "-s", pam_svc_name, "--",
3214		    (AuthenticatingUser != NULL ? AuthenticatingUser :
3215			getenv("USER")), 0);
3216
3217	} else /* default, no auth. info available, login does it all */ {
3218		(void) execl(LOGIN_PROGRAM, "login",
3219		    "-p", "-h", host, "-d", slavename, "--",
3220		    getenv("USER"), 0);
3221	}
3222
3223	fatalperror(netfd, LOGIN_PROGRAM, errno);
3224	/*NOTREACHED*/
3225}
3226
3227static void
3228fatal(int f, char *msg)
3229{
3230	char buf[BUFSIZ];
3231
3232	(void) snprintf(buf, sizeof (buf), "telnetd: %s.\r\n", msg);
3233	(void) write(f, buf, strlen(buf));
3234	exit(EXIT_FAILURE);
3235	/*NOTREACHED*/
3236}
3237
3238static void
3239fatalperror(int f, char *msg, int errnum)
3240{
3241	char buf[BUFSIZ];
3242
3243	(void) snprintf(buf, sizeof (buf),
3244			"%s: %s\r\n", msg, strerror(errnum));
3245	fatal(f, buf);
3246	/*NOTREACHED*/
3247}
3248
3249/*
3250 * Main loop.  Select from pty and network, and
3251 * hand data to telnet receiver finite state machine
3252 * when it receives telnet protocol. Regular data
3253 * flow between pty and network takes place through
3254 * inkernel telnet streams module (telmod).
3255 */
3256static void
3257telnet(int net, int master)
3258{
3259	int on = 1;
3260	char mode;
3261	struct	strioctl	telnetmod;
3262	int	nsize = 0;
3263	char	binary_in = 0;
3264	char binary_out = 0;
3265
3266	if (ioctl(net, FIONBIO, &on) == -1)
3267		syslog(LOG_INFO, "ioctl FIONBIO net: %m\n");
3268	if (ioctl(master, FIONBIO, &on) == -1)
3269		syslog(LOG_INFO, "ioctl FIONBIO pty p: %m\n");
3270	(void) signal(SIGTSTP, SIG_IGN);
3271	(void) signal(SIGCHLD, (void (*)())cleanup);
3272	(void) setpgrp();
3273
3274	/*
3275	 * Call telrcv() once to pick up anything received during
3276	 * terminal type negotiation.
3277	 */
3278	telrcv();
3279
3280	netflush();
3281	ptyflush();
3282
3283	for (;;) {
3284		fd_set ibits, obits, xbits;
3285		int c;
3286
3287		if (ncc < 0)
3288			break;
3289
3290		FD_ZERO(&ibits);
3291		FD_ZERO(&obits);
3292		FD_ZERO(&xbits);
3293
3294		/*
3295		 * If we couldn't flush all our output to the network,
3296		 * keep checking for when we can.
3297		 */
3298		if (nfrontp - nbackp)
3299			FD_SET(net, &obits);
3300		/*
3301		 * Never look for input if there's still
3302		 * stuff in the corresponding output buffer
3303		 */
3304		if (pfrontp - pbackp) {
3305			FD_SET(master, &obits);
3306		} else {
3307			FD_SET(net, &ibits);
3308		}
3309		if (!SYNCHing) {
3310			FD_SET(net, &xbits);
3311		}
3312
3313#define	max(x, y)	(((x) < (y)) ? (y) : (x))
3314
3315		/*
3316		 * make an ioctl to telnet module (net side) to send
3317		 * binary mode of telnet daemon. binary_in and
3318		 * binary_out are 0 if not in binary mode.
3319		 */
3320		if (binary_in != myopts[TELOPT_BINARY] ||
3321		    binary_out != remopts[TELOPT_BINARY]) {
3322
3323			mode = 0;
3324			if (myopts[TELOPT_BINARY] != OPT_NO)
3325				mode |= TEL_BINARY_IN;
3326
3327			if (remopts[TELOPT_BINARY] != OPT_NO)
3328				mode |= TEL_BINARY_OUT;
3329
3330			telnetmod.ic_cmd = TEL_IOC_MODE;
3331			telnetmod.ic_timout = -1;
3332			telnetmod.ic_len = 1;
3333			telnetmod.ic_dp = &mode;
3334
3335			syslog(LOG_DEBUG, "TEL_IOC_MODE binary has changed\n");
3336
3337			if (ioctl(net, I_STR, &telnetmod) < 0)
3338				fatal(net, "ioctl TEL_IOC_MODE failed\n");
3339			binary_in = myopts[TELOPT_BINARY];
3340			binary_out = remopts[TELOPT_BINARY];
3341		}
3342		if (state == TS_DATA) {
3343			if ((nfrontp == nbackp) &&
3344				(pfrontp == pbackp)) {
3345				if (ioctl(net, I_NREAD, &nsize) < 0)
3346					fatalperror(net,
3347					    "ioctl I_NREAD failed\n", errno);
3348				if (nsize)
3349					drainstream(nsize);
3350
3351				/*
3352				 * make an ioctl to reinsert remaining data at
3353				 * streamhead. After this, ioctl reenables the
3354				 * telnet lower put queue. This queue was
3355				 * noenabled by telnet module after sending
3356				 * protocol/urgent data to telnetd.
3357				 */
3358
3359				telnetmod.ic_cmd = TEL_IOC_ENABLE;
3360				telnetmod.ic_timout = -1;
3361				if (ncc || nsize) {
3362					telnetmod.ic_len = ncc + nsize;
3363					telnetmod.ic_dp = netip;
3364				} else {
3365					telnetmod.ic_len = 0;
3366					telnetmod.ic_dp = NULL;
3367				}
3368				if (ioctl(net, I_STR, &telnetmod) < 0)
3369					fatal(net, "ioctl TEL_IOC_ENABLE \
3370						failed\n");
3371
3372				telmod_init_done = B_TRUE;
3373
3374				netip = netibuf;
3375				(void) memset(netibuf, 0, netibufsize);
3376
3377				ncc = 0;
3378			}
3379		} else {
3380			/*
3381			 * state not changed to TS_DATA and hence, more to read
3382			 * send ioctl to get one more message block.
3383			 */
3384			telnetmod.ic_cmd = TEL_IOC_GETBLK;
3385			telnetmod.ic_timout = -1;
3386			telnetmod.ic_len = 0;
3387			telnetmod.ic_dp = NULL;
3388
3389			if (ioctl(net, I_STR, &telnetmod) < 0)
3390				fatal(net, "ioctl TEL_IOC_GETBLK failed\n");
3391		}
3392
3393		if ((c = select(max(net, master) + 1, &ibits, &obits, &xbits,
3394		    (struct timeval *)0)) < 1) {
3395			if (c == -1) {
3396				if (errno == EINTR) {
3397					continue;
3398				}
3399			}
3400			(void) sleep(5);
3401			continue;
3402		}
3403
3404		/*
3405		 * Any urgent data?
3406		 */
3407		if (FD_ISSET(net, &xbits)) {
3408			SYNCHing = 1;
3409		}
3410
3411		/*
3412		 * Something to read from the network...
3413		 */
3414		if (FD_ISSET(net, &ibits)) {
3415		    ncc = read(net, netibuf, netibufsize);
3416		    if (ncc < 0 && errno == EWOULDBLOCK)
3417			ncc = 0;
3418		    else {
3419			if (ncc <= 0) {
3420			    break;
3421			}
3422			netip = netibuf;
3423		    }
3424		}
3425
3426		if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
3427			netflush();
3428		if (ncc > 0)
3429			telrcv();
3430		if (FD_ISSET(master, &obits) && (pfrontp - pbackp) > 0)
3431			ptyflush();
3432	}
3433	cleanup(0);
3434}
3435
3436static void
3437telrcv(void)
3438{
3439	int c;
3440
3441	while (ncc > 0) {
3442		if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
3443			return;
3444		c = *netip & 0377;
3445		/*
3446		 * Once we hit data, we want to transition back to
3447		 * in-kernel processing.  However, this code is shared
3448		 * by getterminaltype()/ttloop() which run before the
3449		 * in-kernel plumbing is available.  So if we are still
3450		 * processing the initial option negotiation, even TS_DATA
3451		 * must be processed here.
3452		 */
3453		if (c != IAC && state == TS_DATA && init_neg_done) {
3454			break;
3455		}
3456		netip++;
3457		ncc--;
3458		switch (state) {
3459
3460		case TS_CR:
3461			state = TS_DATA;
3462			/* Strip off \n or \0 after a \r */
3463			if ((c == 0) || (c == '\n')) {
3464				break;
3465			}
3466			/* FALLTHRU */
3467
3468		case TS_DATA:
3469			if (c == IAC) {
3470				state = TS_IAC;
3471				break;
3472			}
3473			if (inter > 0)
3474				break;
3475			/*
3476			 * We map \r\n ==> \r, since
3477			 * We now map \r\n ==> \r for pragmatic reasons.
3478			 * Many client implementations send \r\n when
3479			 * the user hits the CarriageReturn key.
3480			 *
3481			 * We USED to map \r\n ==> \n, since \r\n says
3482			 * that we want to be in column 1 of the next
3483			 * line.
3484			 */
3485			if (c == '\r' && (myopts[TELOPT_BINARY] == OPT_NO)) {
3486				state = TS_CR;
3487			}
3488			*pfrontp++ = c;
3489			break;
3490
3491		case TS_IAC:
3492			switch (c) {
3493
3494			/*
3495			 * Send the process on the pty side an
3496			 * interrupt.  Do this with a NULL or
3497			 * interrupt char; depending on the tty mode.
3498			 */
3499			case IP:
3500				interrupt();
3501				break;
3502
3503			case BREAK:
3504				sendbrk();
3505				break;
3506
3507			/*
3508			 * Are You There?
3509			 */
3510			case AYT:
3511				write_data_len("\r\n[Yes]\r\n", 9);
3512				break;
3513
3514			/*
3515			 * Abort Output
3516			 */
3517			case AO: {
3518					struct ltchars tmpltc;
3519
3520					ptyflush();	/* half-hearted */
3521					if (ioctl(pty, TIOCGLTC, &tmpltc) == -1)
3522						syslog(LOG_INFO,
3523						    "ioctl TIOCGLTC: %m\n");
3524					if (tmpltc.t_flushc != '\377') {
3525						*pfrontp++ = tmpltc.t_flushc;
3526					}
3527					netclear();	/* clear buffer back */
3528					write_data("%c%c", (uchar_t)IAC,
3529						(uchar_t)DM);
3530
3531					neturg = nfrontp-1; /* off by one XXX */
3532					netflush();
3533					netflush(); /* XXX.sparker */
3534					break;
3535				}
3536
3537			/*
3538			 * Erase Character and
3539			 * Erase Line
3540			 */
3541			case EC:
3542			case EL: {
3543					struct sgttyb b;
3544					char ch;
3545
3546					ptyflush();	/* half-hearted */
3547					if (ioctl(pty, TIOCGETP, &b) == -1)
3548						syslog(LOG_INFO,
3549						    "ioctl TIOCGETP: %m\n");
3550					ch = (c == EC) ?
3551						b.sg_erase : b.sg_kill;
3552					if (ch != '\377') {
3553						*pfrontp++ = ch;
3554					}
3555					break;
3556				}
3557
3558			/*
3559			 * Check for urgent data...
3560			 */
3561			case DM:
3562				break;
3563
3564			/*
3565			 * Begin option subnegotiation...
3566			 */
3567			case SB:
3568				state = TS_SB;
3569				SB_CLEAR();
3570				continue;
3571
3572			case WILL:
3573				state = TS_WILL;
3574				continue;
3575
3576			case WONT:
3577				state = TS_WONT;
3578				continue;
3579
3580			case DO:
3581				state = TS_DO;
3582				continue;
3583
3584			case DONT:
3585				state = TS_DONT;
3586				continue;
3587
3588			case IAC:
3589				*pfrontp++ = c;
3590				break;
3591			}
3592			state = TS_DATA;
3593			break;
3594		case TS_SB:
3595			if (c == IAC) {
3596				state = TS_SE;
3597			} else {
3598				SB_ACCUM(c);
3599			}
3600			break;
3601		case TS_SE:
3602			if (c != SE) {
3603				if (c != IAC) {
3604					SB_ACCUM((uchar_t)IAC);
3605				}
3606				SB_ACCUM(c);
3607				state = TS_SB;
3608
3609			} else {
3610				SB_TERM();
3611				suboption();	/* handle sub-option */
3612				state = TS_DATA;
3613			}
3614			break;
3615
3616		case TS_WILL:
3617			if (remopts[c] != OPT_YES)
3618				willoption(c);
3619			state = TS_DATA;
3620			continue;
3621
3622		case TS_WONT:
3623			if (remopts[c] != OPT_NO)
3624				wontoption(c);
3625			state = TS_DATA;
3626			continue;
3627
3628		case TS_DO:
3629			if (myopts[c] != OPT_YES)
3630				dooption(c);
3631			state = TS_DATA;
3632			continue;
3633
3634		case TS_DONT:
3635			if (myopts[c] != OPT_NO) {
3636				dontoption(c);
3637			}
3638			state = TS_DATA;
3639			continue;
3640
3641		default:
3642			syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
3643			(void) printf("telnetd: panic state=%d\n", state);
3644			exit(EXIT_FAILURE);
3645		}
3646	}
3647}
3648
3649static void
3650willoption(int option)
3651{
3652	uchar_t *fmt;
3653	boolean_t send_reply = B_TRUE;
3654
3655	switch (option) {
3656	case TELOPT_BINARY:
3657		mode(O_RAW, 0);
3658		fmt = doopt;
3659		break;
3660
3661	case TELOPT_ECHO:
3662		not42 = 0;		/* looks like a 4.2 system */
3663		/*
3664		 * Now, in a 4.2 system, to break them out of ECHOing
3665		 * (to the terminal) mode, we need to send a "WILL ECHO".
3666		 * Kludge upon kludge!
3667		 */
3668		if (myopts[TELOPT_ECHO] == OPT_YES) {
3669			dooption(TELOPT_ECHO);
3670		}
3671		fmt = dont;
3672		break;
3673	case TELOPT_TTYPE:
3674		settimer(ttypeopt);
3675		goto common;
3676
3677	case TELOPT_NAWS:
3678		settimer(nawsopt);
3679		goto common;
3680
3681	case TELOPT_XDISPLOC:
3682		settimer(xdisplocopt);
3683		goto common;
3684
3685	case TELOPT_NEW_ENVIRON:
3686		settimer(environopt);
3687		goto common;
3688
3689	case TELOPT_AUTHENTICATION:
3690		settimer(authopt);
3691		if (remopts[option] == OPT_NO ||
3692		    negotiate_auth_krb5 == 0)
3693			fmt = dont;
3694		else
3695			fmt = doopt;
3696		break;
3697
3698	case TELOPT_OLD_ENVIRON:
3699		settimer(oenvironopt);
3700		goto common;
3701common:
3702		if (remopts[option] == OPT_YES_BUT_ALWAYS_LOOK) {
3703			remopts[option] = OPT_YES;
3704			return;
3705		}
3706		/*FALLTHRU*/
3707	case TELOPT_SGA:
3708		fmt = doopt;
3709		break;
3710
3711	case TELOPT_TM:
3712		fmt = dont;
3713		break;
3714
3715	case TELOPT_ENCRYPT:
3716		settimer(encropt); /* got response to do/dont */
3717		if (enc_debug)
3718			(void) fprintf(stderr,
3719				    "RCVD IAC WILL TELOPT_ENCRYPT\n");
3720		if (krb5_privacy_allowed()) {
3721			fmt = doopt;
3722			if (sent_do_encrypt)
3723				send_reply = B_FALSE;
3724			else
3725				sent_do_encrypt = B_TRUE;
3726		} else {
3727			fmt = dont;
3728		}
3729		break;
3730
3731	default:
3732		fmt = dont;
3733		break;
3734	}
3735	if (fmt == doopt) {
3736		remopts[option] = OPT_YES;
3737	} else {
3738		remopts[option] = OPT_NO;
3739	}
3740	if (send_reply) {
3741		write_data((const char *)fmt, option);
3742		netflush();
3743	}
3744}
3745
3746static void
3747wontoption(int option)
3748{
3749	uchar_t *fmt;
3750	int send_reply = 1;
3751
3752	switch (option) {
3753	case TELOPT_ECHO:
3754		not42 = 1;		/* doesn't seem to be a 4.2 system */
3755		break;
3756
3757	case TELOPT_BINARY:
3758		mode(0, O_RAW);
3759		break;
3760
3761	case TELOPT_TTYPE:
3762		settimer(ttypeopt);
3763		break;
3764
3765	case TELOPT_NAWS:
3766		settimer(nawsopt);
3767		break;
3768
3769	case TELOPT_XDISPLOC:
3770		settimer(xdisplocopt);
3771		break;
3772
3773	case TELOPT_NEW_ENVIRON:
3774		settimer(environopt);
3775		break;
3776
3777	case TELOPT_OLD_ENVIRON:
3778		settimer(oenvironopt);
3779		break;
3780
3781	case TELOPT_AUTHENTICATION:
3782		settimer(authopt);
3783		auth_finished(0, AUTH_REJECT);
3784		if (auth_debug)
3785			(void) fprintf(stderr,
3786				    "RCVD WONT TELOPT_AUTHENTICATE\n");
3787
3788		remopts[option] = OPT_NO;
3789		send_reply = 0;
3790		break;
3791
3792	case TELOPT_ENCRYPT:
3793		if (enc_debug)
3794			(void) fprintf(stderr,
3795				    "RCVD IAC WONT TELOPT_ENCRYPT\n");
3796		settimer(encropt); /* got response to will/wont */
3797		/*
3798		 * Remote side cannot send encryption. No reply necessary
3799		 * Treat this as if "IAC SB ENCRYPT END IAC SE" were
3800		 * received (RFC 2946) and disable crypto.
3801		 */
3802		encrypt_end(TELNET_DIR_DECRYPT);
3803		send_reply = 0;
3804		break;
3805	}
3806
3807	fmt = dont;
3808	remopts[option] = OPT_NO;
3809	if (send_reply) {
3810		write_data((const char *)fmt, option);
3811	}
3812}
3813
3814/*
3815 * We received an "IAC DO ..." message from the client, change our state
3816 * to OPT_YES.
3817 */
3818static void
3819dooption(int option)
3820{
3821	uchar_t *fmt;
3822	boolean_t send_reply = B_TRUE;
3823
3824	switch (option) {
3825
3826	case TELOPT_TM:
3827		fmt = wont;
3828		break;
3829
3830	case TELOPT_ECHO:
3831		mode(O_ECHO|O_CRMOD, 0);
3832		fmt = will;
3833		break;
3834
3835	case TELOPT_BINARY:
3836		mode(O_RAW, 0);
3837		fmt = will;
3838		break;
3839
3840	case TELOPT_SGA:
3841		fmt = will;
3842		break;
3843
3844	case TELOPT_LOGOUT:
3845		/*
3846		 * Options don't get much easier.  Acknowledge the option,
3847		 * and then clean up and exit.
3848		 */
3849		write_data((const char *)will, option);
3850		netflush();
3851		cleanup(0);
3852		/*NOTREACHED*/
3853
3854	case TELOPT_ENCRYPT:
3855		if (enc_debug)
3856			(void) fprintf(stderr, "RCVD DO TELOPT_ENCRYPT\n");
3857		settimer(encropt);
3858		/*
3859		 * We received a "DO".  This indicates that the other side
3860		 * wants us to encrypt our data (pending negotiatoin).
3861		 * reply with "IAC WILL ENCRYPT" if we are able to send
3862		 * encrypted data.
3863		 */
3864		if (krb5_privacy_allowed() && negotiate_encrypt) {
3865			fmt = will;
3866			if (sent_will_encrypt)
3867				send_reply = B_FALSE;
3868			else
3869				sent_will_encrypt = B_TRUE;
3870			/* return if we already sent "WILL ENCRYPT" */
3871			if (myopts[option] == OPT_YES)
3872				return;
3873		} else {
3874			fmt = wont;
3875		}
3876		break;
3877
3878	case TELOPT_AUTHENTICATION:
3879		if (auth_debug) {
3880			(void) fprintf(stderr,
3881				    "RCVD DO TELOPT_AUTHENTICATION\n");
3882		}
3883		/*
3884		 * RFC 2941 - only the server can send
3885		 * "DO TELOPT_AUTHENTICATION".
3886		 * if a server receives this, it must respond with WONT...
3887		 */
3888		fmt = wont;
3889		break;
3890
3891	default:
3892		fmt = wont;
3893		break;
3894	}
3895	if (fmt == will) {
3896		myopts[option] = OPT_YES;
3897	} else {
3898		myopts[option] = OPT_NO;
3899	}
3900	if (send_reply) {
3901		write_data((const char *)fmt, option);
3902		netflush();
3903	}
3904}
3905
3906/*
3907 * We received an "IAC DONT ..." message from client.
3908 * Client does not agree with the option so act accordingly.
3909 */
3910static void
3911dontoption(int option)
3912{
3913	int send_reply = 1;
3914	switch (option) {
3915	case TELOPT_ECHO:
3916		/*
3917		 * we should stop echoing, since the client side will be doing
3918		 * it, but keep mapping CR since CR-LF will be mapped to it.
3919		 */
3920		mode(0, O_ECHO);
3921		break;
3922
3923	case TELOPT_ENCRYPT:
3924		if (enc_debug)
3925			(void) fprintf(stderr, "RCVD IAC DONT ENCRYPT\n");
3926		settimer(encropt);
3927		/*
3928		 * Remote side cannot receive any encrypted data,
3929		 * so dont send any.  No reply necessary.
3930		 */
3931		send_reply = 0;
3932		break;
3933
3934	default:
3935		break;
3936	}
3937
3938	myopts[option] = OPT_NO;
3939
3940	if (send_reply) {
3941		write_data((const char *)wont, option);
3942	}
3943}
3944
3945/*
3946 * suboption()
3947 *
3948 *	Look at the sub-option buffer, and try to be helpful to the other
3949 * side.
3950 *
3951 */
3952static void
3953suboption(void)
3954{
3955	int subchar;
3956
3957	switch (subchar = SB_GET()) {
3958	case TELOPT_TTYPE: {		/* Yaaaay! */
3959		static char terminalname[5+41] = "TERM=";
3960
3961		settimer(ttypesubopt);
3962
3963		if (SB_GET() != TELQUAL_IS) {
3964			return;	/* ??? XXX but, this is the most robust */
3965		}
3966
3967		terminaltype = terminalname+strlen(terminalname);
3968
3969		while (terminaltype < (terminalname + sizeof (terminalname) -
3970		    1) && !SB_EOF()) {
3971			int c;
3972
3973			c = SB_GET();
3974			if (isupper(c)) {
3975				c = tolower(c);
3976			}
3977			*terminaltype++ = c;    /* accumulate name */
3978		}
3979		*terminaltype = 0;
3980		terminaltype = terminalname;
3981		break;
3982	}
3983
3984	case TELOPT_NAWS: {
3985		struct winsize ws;
3986
3987		if (SB_EOF()) {
3988			return;
3989		}
3990		ws.ws_col = SB_GET() << 8;
3991		if (SB_EOF()) {
3992			return;
3993		}
3994		ws.ws_col |= SB_GET();
3995		if (SB_EOF()) {
3996			return;
3997		}
3998		ws.ws_row = SB_GET() << 8;
3999		if (SB_EOF()) {
4000			return;
4001		}
4002		ws.ws_row |= SB_GET();
4003		ws.ws_xpixel = 0; ws.ws_ypixel = 0;
4004		(void) ioctl(pty, TIOCSWINSZ, &ws);
4005		settimer(nawsopt);
4006		break;
4007	}
4008
4009	case TELOPT_XDISPLOC: {
4010		if (SB_EOF() || SB_GET() != TELQUAL_IS) {
4011			return;
4012		}
4013		settimer(xdisplocsubopt);
4014		subpointer[SB_LEN()] = '\0';
4015		if ((new_env("DISPLAY", subpointer)) == 1)
4016			perror("malloc");
4017		break;
4018	}
4019
4020	case TELOPT_NEW_ENVIRON:
4021	case TELOPT_OLD_ENVIRON: {
4022		int c;
4023		char *cp, *varp, *valp;
4024
4025		if (SB_EOF())
4026			return;
4027		c = SB_GET();
4028		if (c == TELQUAL_IS) {
4029			if (subchar == TELOPT_OLD_ENVIRON)
4030				settimer(oenvironsubopt);
4031			else
4032				settimer(environsubopt);
4033		} else if (c != TELQUAL_INFO) {
4034			return;
4035		}
4036
4037		if (subchar == TELOPT_NEW_ENVIRON) {
4038		    while (!SB_EOF()) {
4039			c = SB_GET();
4040			if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR))
4041				break;
4042		    }
4043		} else
4044		{
4045			while (!SB_EOF()) {
4046				c = SB_GET();
4047				if ((c == env_ovar) || (c == ENV_USERVAR))
4048					break;
4049			}
4050		}
4051
4052		if (SB_EOF())
4053			return;
4054
4055		cp = varp = (char *)subpointer;
4056		valp = 0;
4057
4058		while (!SB_EOF()) {
4059			c = SB_GET();
4060			if (subchar == TELOPT_OLD_ENVIRON) {
4061				if (c == env_ovar)
4062					c = NEW_ENV_VAR;
4063				else if (c == env_ovalue)
4064					c = NEW_ENV_VALUE;
4065			}
4066			switch (c) {
4067
4068			case NEW_ENV_VALUE:
4069				*cp = '\0';
4070				cp = valp = (char *)subpointer;
4071				break;
4072
4073			case NEW_ENV_VAR:
4074			case ENV_USERVAR:
4075				*cp = '\0';
4076				if (valp) {
4077					if ((new_env(varp, valp)) == 1) {
4078						perror("malloc");
4079					}
4080				} else {
4081					(void) del_env(varp);
4082				}
4083				cp = varp = (char *)subpointer;
4084				valp = 0;
4085				break;
4086
4087			case ENV_ESC:
4088				if (SB_EOF())
4089					break;
4090				c = SB_GET();
4091				/* FALL THROUGH */
4092			default:
4093				*cp++ = c;
4094				break;
4095			}
4096		}
4097		*cp = '\0';
4098		if (valp) {
4099			if ((new_env(varp, valp)) == 1) {
4100				perror("malloc");
4101			}
4102		} else {
4103			(void) del_env(varp);
4104		}
4105		break;
4106	}  /* end of case TELOPT_NEW_ENVIRON */
4107
4108	case TELOPT_AUTHENTICATION:
4109		if (SB_EOF())
4110			break;
4111		switch (SB_GET()) {
4112		case TELQUAL_SEND:
4113		case TELQUAL_REPLY:
4114			/*
4115			 * These are sent server only and cannot be sent by the
4116			 * client.
4117			 */
4118			break;
4119		case TELQUAL_IS:
4120			if (auth_debug)
4121				(void) fprintf(stderr,
4122					    "RCVD AUTHENTICATION IS "
4123					    "(%d bytes)\n",
4124					    SB_LEN());
4125			if (!auth_negotiated)
4126				auth_is((uchar_t *)subpointer, SB_LEN());
4127			break;
4128		case TELQUAL_NAME:
4129			if (auth_debug)
4130				(void) fprintf(stderr,
4131					    "RCVD AUTHENTICATION NAME "
4132					    "(%d bytes)\n",
4133					    SB_LEN());
4134			if (!auth_negotiated)
4135				auth_name((uchar_t *)subpointer, SB_LEN());
4136			break;
4137		}
4138		break;
4139
4140	case TELOPT_ENCRYPT: {
4141		int c;
4142		if (SB_EOF())
4143			break;
4144		c = SB_GET();
4145#ifdef ENCRYPT_NAMES
4146		if (enc_debug)
4147			(void) fprintf(stderr, "RCVD ENCRYPT %s\n",
4148				    ENCRYPT_NAME(c));
4149#endif /* ENCRYPT_NAMES */
4150		switch (c) {
4151		case ENCRYPT_SUPPORT:
4152			encrypt_support(subpointer, SB_LEN());
4153			break;
4154		case ENCRYPT_IS:
4155			encrypt_is((uchar_t *)subpointer, SB_LEN());
4156			break;
4157		case ENCRYPT_REPLY:
4158			(void) encrypt_reply(subpointer, SB_LEN());
4159			break;
4160		case ENCRYPT_START:
4161			encrypt_start();
4162			break;
4163		case ENCRYPT_END:
4164			encrypt_end(TELNET_DIR_DECRYPT);
4165			break;
4166		case ENCRYPT_REQSTART:
4167			encrypt_request_start();
4168			break;
4169		case ENCRYPT_REQEND:
4170			/*
4171			 * We can always send an REQEND so that we cannot
4172			 * get stuck encrypting.  We should only get this
4173			 * if we have been able to get in the correct mode
4174			 * anyhow.
4175			 */
4176			encrypt_request_end();
4177			break;
4178		case ENCRYPT_ENC_KEYID:
4179			encrypt_enc_keyid(subpointer, SB_LEN());
4180			break;
4181		case ENCRYPT_DEC_KEYID:
4182			encrypt_dec_keyid(subpointer, SB_LEN());
4183			break;
4184		default:
4185			break;
4186		}
4187	}
4188	break;
4189
4190	default:
4191		break;
4192	}
4193}
4194
4195static void
4196mode(int on, int off)
4197{
4198	struct termios  tios;
4199
4200	ptyflush();
4201	if (tcgetattr(pty, &tios) < 0)
4202		syslog(LOG_INFO, "tcgetattr: %m\n");
4203
4204	if (on & O_RAW) {
4205		tios.c_cflag |= CS8;
4206		tios.c_iflag &= ~IUCLC;
4207		tios.c_lflag &= ~(XCASE|IEXTEN);
4208	}
4209	if (off & O_RAW) {
4210		if ((tios.c_cflag & PARENB) != 0)
4211			tios.c_cflag &= ~CS8;
4212		tios.c_lflag |= IEXTEN;
4213	}
4214
4215	if (on & O_ECHO)
4216		tios.c_lflag |= ECHO;
4217	if (off & O_ECHO)
4218		tios.c_lflag &= ~ECHO;
4219
4220	if (on & O_CRMOD) {
4221		tios.c_iflag |= ICRNL;
4222		tios.c_oflag |= ONLCR;
4223	}
4224	/*
4225	 * Because "O_CRMOD" will never be set in "off" we don't have to
4226	 * handle this case here.
4227	 */
4228
4229	if (tcsetattr(pty, TCSANOW, &tios) < 0)
4230		syslog(LOG_INFO, "tcsetattr: %m\n");
4231}
4232
4233/*
4234 * Send interrupt to process on other side of pty.
4235 * If it is in raw mode, just write NULL;
4236 * otherwise, write intr char.
4237 */
4238static void
4239interrupt(void)
4240{
4241	struct sgttyb b;
4242	struct tchars tchars;
4243
4244	ptyflush();	/* half-hearted */
4245	if (ioctl(pty, TIOCGETP, &b) == -1)
4246		syslog(LOG_INFO, "ioctl TIOCGETP: %m\n");
4247	if (b.sg_flags & O_RAW) {
4248		*pfrontp++ = '\0';
4249		return;
4250	}
4251	*pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4252		'\177' : tchars.t_intrc;
4253}
4254
4255/*
4256 * Send quit to process on other side of pty.
4257 * If it is in raw mode, just write NULL;
4258 * otherwise, write quit char.
4259 */
4260static void
4261sendbrk(void)
4262{
4263	struct sgttyb b;
4264	struct tchars tchars;
4265
4266	ptyflush();	/* half-hearted */
4267	(void) ioctl(pty, TIOCGETP, &b);
4268	if (b.sg_flags & O_RAW) {
4269		*pfrontp++ = '\0';
4270		return;
4271	}
4272	*pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
4273		'\034' : tchars.t_quitc;
4274}
4275
4276static void
4277ptyflush(void)
4278{
4279	int n;
4280
4281	if ((n = pfrontp - pbackp) > 0)
4282		n = write(master, pbackp, n);
4283	if (n < 0)
4284		return;
4285	pbackp += n;
4286	if (pbackp == pfrontp)
4287		pbackp = pfrontp = ptyobuf;
4288}
4289
4290/*
4291 * nextitem()
4292 *
4293 *	Return the address of the next "item" in the TELNET data
4294 * stream.  This will be the address of the next character if
4295 * the current address is a user data character, or it will
4296 * be the address of the character following the TELNET command
4297 * if the current address is a TELNET IAC ("I Am a Command")
4298 * character.
4299 */
4300
4301static char *
4302nextitem(char *current)
4303{
4304	if ((*current&0xff) != IAC) {
4305		return (current+1);
4306	}
4307	switch (*(current+1)&0xff) {
4308	case DO:
4309	case DONT:
4310	case WILL:
4311	case WONT:
4312		return (current+3);
4313	case SB:		/* loop forever looking for the SE */
4314	{
4315		char *look = current+2;
4316
4317		for (;;) {
4318			if ((*look++&0xff) == IAC) {
4319				if ((*look++&0xff) == SE) {
4320					return (look);
4321				}
4322			}
4323		}
4324	}
4325	default:
4326		return (current+2);
4327	}
4328}
4329
4330
4331/*
4332 * netclear()
4333 *
4334 *	We are about to do a TELNET SYNCH operation.  Clear
4335 * the path to the network.
4336 *
4337 *	Things are a bit tricky since we may have sent the first
4338 * byte or so of a previous TELNET command into the network.
4339 * So, we have to scan the network buffer from the beginning
4340 * until we are up to where we want to be.
4341 *
4342 *	A side effect of what we do, just to keep things
4343 * simple, is to clear the urgent data pointer.  The principal
4344 * caller should be setting the urgent data pointer AFTER calling
4345 * us in any case.
4346 */
4347static void
4348netclear(void)
4349{
4350	char *thisitem, *next;
4351	char *good;
4352#define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \
4353				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
4354
4355	thisitem = netobuf;
4356
4357	while ((next = nextitem(thisitem)) <= nbackp) {
4358		thisitem = next;
4359	}
4360
4361	/* Now, thisitem is first before/at boundary. */
4362
4363	good = netobuf;	/* where the good bytes go */
4364
4365	while (nfrontp > thisitem) {
4366		if (wewant(thisitem)) {
4367			int length;
4368
4369			next = thisitem;
4370			do {
4371				next = nextitem(next);
4372			} while (wewant(next) && (nfrontp > next));
4373			length = next-thisitem;
4374			(void) memmove(good, thisitem, length);
4375			good += length;
4376			thisitem = next;
4377		} else {
4378			thisitem = nextitem(thisitem);
4379		}
4380	}
4381
4382	nbackp = netobuf;
4383	nfrontp = good;		/* next byte to be sent */
4384	neturg = 0;
4385}
4386
4387
4388/*
4389 *  netflush
4390 *		Send as much data as possible to the network,
4391 *	handling requests for urgent data.
4392 */
4393static void
4394netflush(void)
4395{
4396	int n;
4397
4398	if ((n = nfrontp - nbackp) > 0) {
4399		/*
4400		 * if no urgent data, or if the other side appears to be an
4401		 * old 4.2 client (and thus unable to survive TCP urgent data),
4402		 * write the entire buffer in non-OOB mode.
4403		 */
4404		if ((neturg == 0) || (not42 == 0)) {
4405			n = write(net, nbackp, n);	/* normal write */
4406		} else {
4407			n = neturg - nbackp;
4408			/*
4409			 * In 4.2 (and 4.3) systems, there is some question
4410			 * about what byte in a sendOOB operation is the "OOB"
4411			 * data.  To make ourselves compatible, we only send ONE
4412			 * byte out of band, the one WE THINK should be OOB
4413			 * (though we really have more the TCP philosophy of
4414			 * urgent data rather than the Unix philosophy of OOB
4415			 * data).
4416			 */
4417			if (n > 1) {
4418				/* send URGENT all by itself */
4419				n = write(net, nbackp, n-1);
4420			} else {
4421				/* URGENT data */
4422				n = send_oob(net, nbackp, n);
4423			}
4424		}
4425	}
4426	if (n < 0) {
4427		if (errno == EWOULDBLOCK)
4428			return;
4429		/* should blow this guy away... */
4430		return;
4431	}
4432
4433	nbackp += n;
4434
4435	if (nbackp >= neturg) {
4436		neturg = 0;
4437	}
4438	if (nbackp == nfrontp) {
4439		nbackp = nfrontp = netobuf;
4440	}
4441}
4442
4443/* ARGSUSED */
4444static void
4445cleanup(int signum)
4446{
4447	/*
4448	 * If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
4449	 * handle closing differently.  We close "net" first and then
4450	 * "master" in that order.  We do close(net) first because
4451	 * we have no other way to disconnect forwarding between the network
4452	 * and master.  So by issuing the close()'s we ensure that no further
4453	 * data rises from TCP.  A more complex fix would be adding proper
4454	 * support for throwing a "stop" switch for forwarding data between
4455	 * logindmux peers.  It's possible to block in the close of the tty
4456	 * while the network still receives data and the telmod module is
4457	 * TEL_STOPPED.  A denial-of-service attack generates this case,
4458	 * see 4102102.
4459	 */
4460
4461	if (!telmod_init_done) {
4462		(void) close(net);
4463		(void) close(master);
4464	}
4465	rmut();
4466
4467	exit(EXIT_FAILURE);
4468}
4469
4470static void
4471rmut(void)
4472{
4473	pam_handle_t    *pamh;
4474	struct utmpx *up;
4475	char user[sizeof (up->ut_user) + 1];
4476	char ttyn[sizeof (up->ut_line) + 1];
4477	char rhost[sizeof (up->ut_host) + 1];
4478
4479	/* while cleaning up don't allow disruption */
4480	(void) signal(SIGCHLD, SIG_IGN);
4481
4482	setutxent();
4483	while (up = getutxent()) {
4484		if (up->ut_pid == pid) {
4485			if (up->ut_type == DEAD_PROCESS) {
4486				/*
4487				 * Cleaned up elsewhere.
4488				 */
4489				break;
4490			}
4491
4492			/*
4493			 * call pam_close_session if login changed
4494			 * the utmpx user entry from type LOGIN_PROCESS
4495			 * to type USER_PROCESS, which happens
4496			 * after pam_open_session is called.
4497			 */
4498			if (up->ut_type == USER_PROCESS) {
4499				(void) strlcpy(user, up->ut_user,
4500					    sizeof (user));
4501				(void) strlcpy(ttyn, up->ut_line,
4502					    sizeof (ttyn));
4503				(void) strlcpy(rhost, up->ut_host,
4504					    sizeof (rhost));
4505				if ((pam_start("telnet", user, NULL, &pamh)) ==
4506				    PAM_SUCCESS) {
4507					(void) pam_set_item(pamh, PAM_TTY,
4508							    ttyn);
4509					(void) pam_set_item(pamh, PAM_RHOST,
4510							    rhost);
4511					(void) pam_close_session(pamh, 0);
4512					(void) pam_end(pamh, PAM_SUCCESS);
4513				}
4514			}
4515
4516			up->ut_type = DEAD_PROCESS;
4517			up->ut_exit.e_termination = WTERMSIG(0);
4518			up->ut_exit.e_exit = WEXITSTATUS(0);
4519			(void) time(&up->ut_tv.tv_sec);
4520
4521			if (modutx(up) == NULL) {
4522				/*
4523				 * Since modutx failed we'll
4524				 * write out the new entry
4525				 * ourselves.
4526				 */
4527				(void) pututxline(up);
4528				updwtmpx("wtmpx", up);
4529			}
4530			break;
4531		}
4532	}
4533
4534	endutxent();
4535
4536	(void) signal(SIGCHLD, (void (*)())cleanup);
4537}
4538
4539static int
4540readstream(int fd, char *buf, int offset)
4541{
4542	struct strbuf ctlbuf, datbuf;
4543	union T_primitives tpi;
4544	int	ret = 0;
4545	int	flags = 0;
4546	int	bytes_avail, count;
4547
4548	(void) memset((char *)&ctlbuf, 0, sizeof (ctlbuf));
4549	(void) memset((char *)&datbuf, 0, sizeof (datbuf));
4550
4551	ctlbuf.buf = (char *)&tpi;
4552	ctlbuf.maxlen = sizeof (tpi);
4553
4554	if (ioctl(fd, I_NREAD, &bytes_avail) < 0) {
4555		syslog(LOG_ERR, "I_NREAD returned error %m");
4556		return (-1);
4557	}
4558	if (bytes_avail > netibufsize - offset) {
4559		count = netip - netibuf;
4560		netibuf = (char *)realloc(netibuf,
4561		    (unsigned)netibufsize + bytes_avail);
4562		if (netibuf == NULL) {
4563			fatal(net, "netibuf realloc failed\n");
4564		}
4565		netibufsize += bytes_avail;
4566		netip = netibuf + count;
4567		buf = netibuf;
4568	}
4569	datbuf.buf = buf + offset;
4570	datbuf.maxlen = netibufsize;
4571	ret = getmsg(fd, &ctlbuf, &datbuf, &flags);
4572	if (ret < 0) {
4573		syslog(LOG_ERR, "getmsg returned -1, errno %d\n",
4574			errno);
4575		return (-1);
4576	}
4577	if (ctlbuf.len <= 0) {
4578		return (datbuf.len);
4579	}
4580
4581	if (tpi.type == T_DATA_REQ) {
4582		return (0);
4583	}
4584
4585	if ((tpi.type == T_ORDREL_IND) || (tpi.type == T_DISCON_IND))
4586		cleanup(0);
4587	fatal(fd, "no data or protocol element recognized");
4588	return (0);
4589}
4590
4591static void
4592drainstream(int size)
4593{
4594	int	nbytes;
4595	int	tsize;
4596
4597	tsize = netip - netibuf;
4598
4599	if ((tsize + ncc + size) > netibufsize) {
4600		if (!(netibuf = (char *)realloc(netibuf,
4601		    (unsigned)tsize + ncc + size)))
4602			fatalperror(net, "netibuf realloc failed\n", errno);
4603		netibufsize = tsize + ncc + size;
4604
4605		netip = netibuf + tsize;
4606	}
4607
4608	if ((nbytes = read(net, (char *)netip + ncc, size)) != size)
4609		syslog(LOG_ERR, "read %d bytes\n", nbytes);
4610}
4611
4612/*
4613 * TPI style replacement for socket send() primitive, so we don't require
4614 * sockmod to be on the stream.
4615 */
4616static int
4617send_oob(int fd, char *ptr, int count)
4618{
4619	struct T_exdata_req exd_req;
4620	struct strbuf hdr, dat;
4621	int ret;
4622
4623	exd_req.PRIM_type = T_EXDATA_REQ;
4624	exd_req.MORE_flag = 0;
4625
4626	hdr.buf = (char *)&exd_req;
4627	hdr.len = sizeof (exd_req);
4628
4629	dat.buf = ptr;
4630	dat.len = count;
4631
4632	ret = putmsg(fd, &hdr, &dat, 0);
4633	if (ret == 0) {
4634		ret = count;
4635	}
4636	return (ret);
4637}
4638
4639
4640/*
4641 * local_setenv --
4642 *	Set the value of the environmental variable "name" to be
4643 *	"value".  If rewrite is set, replace any current value.
4644 */
4645static int
4646local_setenv(const char *name, const char *value, int rewrite)
4647{
4648	static int alloced;			/* if allocated space before */
4649	char *c;
4650	int l_value, offset;
4651
4652	/*
4653	 * Do not allow environment variables which begin with LD_ to be
4654	 * inserted into the environment.  While normally the dynamic linker
4655	 * protects the login program, that is based on the assumption hostile
4656	 * invocation of login are from non-root users.  However, since telnetd
4657	 * runs as root, this cannot be utilized.  So instead we simply
4658	 * prevent LD_* from being inserted into the environment.
4659	 * This also applies to other environment variables that
4660	 * are to be ignored in setugid apps.
4661	 * Note that at this point name can contain '='!
4662	 * Also, do not allow TTYPROMPT to be passed along here.
4663	 */
4664	if (strncmp(name, "LD_", 3) == 0 ||
4665	    strncmp(name, "NLSPATH", 7) == 0 ||
4666	    (strncmp(name, "TTYPROMPT", 9) == 0 &&
4667		(name[9] == '\0' || name[9] == '='))) {
4668		return (-1);
4669	}
4670	if (*value == '=')			/* no `=' in value */
4671		++value;
4672	l_value = strlen(value);
4673	if ((c = __findenv(name, &offset))) {	/* find if already exists */
4674		if (!rewrite)
4675			return (0);
4676		if ((int)strlen(c) >= l_value) { /* old larger; copy over */
4677			while (*c++ = *value++)
4678				;
4679			return (0);
4680		}
4681	} else {					/* create new slot */
4682		int cnt;
4683		char **p;
4684
4685		for (p = environ, cnt = 0; *p; ++p, ++cnt)
4686			;
4687		if (alloced) {			/* just increase size */
4688			environ = (char **)realloc((char *)environ,
4689			    (size_t)(sizeof (char *) * (cnt + 2)));
4690			if (!environ)
4691				return (-1);
4692		} else {				/* get new space */
4693			alloced = 1;		/* copy old entries into it */
4694			p = (char **)malloc((size_t)(sizeof (char *)*
4695			    (cnt + 2)));
4696			if (!p)
4697				return (-1);
4698			(void) memcpy(p, environ, cnt * sizeof (char *));
4699			environ = p;
4700		}
4701		environ[cnt + 1] = NULL;
4702		offset = cnt;
4703	}
4704	for (c = (char *)name; *c && *c != '='; ++c)	/* no `=' in name */
4705		;
4706	if (!(environ[offset] =			/* name + `=' + value */
4707	    malloc((size_t)((int)(c - name) + l_value + 2))))
4708		return (-1);
4709	for (c = environ[offset]; ((*c = *name++) != 0) && (*c != '='); ++c)
4710		;
4711	for (*c++ = '='; *c++ = *value++; )
4712		;
4713	return (0);
4714}
4715
4716/*
4717 * local_unsetenv(name) --
4718 *	Delete environmental variable "name".
4719 */
4720static void
4721local_unsetenv(const char *name)
4722{
4723	char **p;
4724	int offset;
4725
4726	while (__findenv(name, &offset))	/* if set multiple times */
4727		for (p = &environ[offset]; ; ++p)
4728			if ((*p = *(p + 1)) == 0)
4729				break;
4730}
4731
4732/*
4733 * __findenv --
4734 *	Returns pointer to value associated with name, if any, else NULL.
4735 *	Sets offset to be the offset of the name/value combination in the
4736 *	environmental array, for use by local_setenv() and local_unsetenv().
4737 *	Explicitly removes '=' in argument name.
4738 */
4739static char *
4740__findenv(const char *name, int *offset)
4741{
4742	extern char **environ;
4743	int len;
4744	const char *np;
4745	char **p, *c;
4746
4747	if (name == NULL || environ == NULL)
4748		return (NULL);
4749	for (np = name; *np && *np != '='; ++np)
4750		continue;
4751	len = np - name;
4752	for (p = environ; (c = *p) != NULL; ++p)
4753		if (strncmp(c, name, len) == 0 && c[len] == '=') {
4754			*offset = p - environ;
4755			return (c + len + 1);
4756		}
4757	return (NULL);
4758}
4759
4760static void
4761showbanner(void)
4762{
4763	char	*cp;
4764	char	evalbuf[BUFSIZ];
4765
4766	if (defopen(defaultfile) == 0) {
4767		int	flags;
4768
4769		/* ignore case */
4770		flags = defcntl(DC_GETFLAGS, 0);
4771		TURNOFF(flags, DC_CASE);
4772		(void) defcntl(DC_SETFLAGS, flags);
4773		if (cp = defread(bannervar)) {
4774			FILE	*fp;
4775
4776			if (strlen(cp) + strlen("eval echo '") + strlen("'\n")
4777			    + 1 < sizeof (evalbuf)) {
4778				(void) strlcpy(evalbuf, "eval echo '",
4779					sizeof (evalbuf));
4780				(void) strlcat(evalbuf, cp, sizeof (evalbuf));
4781				(void) strlcat(evalbuf, "'\n",
4782						sizeof (evalbuf));
4783
4784				if (fp = popen(evalbuf, "r")) {
4785					char	buf[BUFSIZ];
4786					size_t	size;
4787
4788					/*
4789					 * Pipe I/O atomicity guarantees we
4790					 * need only one read.
4791					 */
4792					if ((size = fread(buf, 1,
4793							sizeof (buf) - 1,
4794							fp)) != 0) {
4795						char	*p;
4796						buf[size] = '\0';
4797						p = strrchr(buf, '\n');
4798						if (p != NULL)
4799							*p = '\0';
4800						if (strlen(buf)) {
4801							map_banner(buf);
4802							netflush();
4803						}
4804					}
4805					(void) pclose(fp);
4806					/* close default file */
4807					(void) defopen(NULL);
4808					return;
4809				}
4810			}
4811		}
4812		(void) defopen(NULL);	/* close default file */
4813	}
4814
4815	defbanner();
4816	netflush();
4817}
4818
4819static void
4820map_banner(char *p)
4821{
4822	char	*q;
4823
4824	/*
4825	 *	Map the banner:  "\n" -> "\r\n" and "\r" -> "\r\0"
4826	 */
4827	for (q = nfrontp; p && *p && q < nfrontp + sizeof (netobuf) - 1; )
4828		if (*p == '\n') {
4829			*q++ = '\r';
4830			*q++ = '\n';
4831			p++;
4832		} else if (*p == '\r') {
4833			*q++ = '\r';
4834			*q++ = '\0';
4835			p++;
4836		} else
4837			*q++ = *p++;
4838
4839	nfrontp += q - netobuf;
4840}
4841
4842/*
4843 * Show banner that getty never gave.  By default, this is `uname -sr`.
4844 *
4845 * The banner includes some null's (for TELNET CR disambiguation),
4846 * so we have to be somewhat complicated.
4847 */
4848static void
4849defbanner(void)
4850{
4851	struct utsname u;
4852
4853	/*
4854	 * Dont show this if the '-h' option was present
4855	 */
4856	if (!show_hostinfo)
4857		return;
4858
4859	if (uname(&u) == -1)
4860		return;
4861
4862	write_data_len((const char *) BANNER1, sizeof (BANNER1) - 1);
4863	write_data_len(u.sysname, strlen(u.sysname));
4864	write_data_len(" ", 1);
4865	write_data_len(u.release, strlen(u.release));
4866	write_data_len((const char *)BANNER2, sizeof (BANNER2) - 1);
4867}
4868
4869/*
4870 * Verify that the named module is at the top of the stream
4871 * and then pop it off.
4872 */
4873static int
4874removemod(int f, char *modname)
4875{
4876	char topmodname[BUFSIZ];
4877
4878	if (ioctl(f, I_LOOK, topmodname) < 0)
4879		return (-1);
4880	if (strcmp(modname, topmodname) != 0) {
4881		errno = ENXIO;
4882		return (-1);
4883	}
4884	if (ioctl(f, I_POP, 0) < 0)
4885		return (-1);
4886	return (0);
4887}
4888
4889static void
4890write_data(const char *format, ...)
4891{
4892	va_list args;
4893	int		len;
4894	char	argp[BUFSIZ];
4895
4896	va_start(args, format);
4897
4898	if ((len = vsnprintf(argp, sizeof (argp), format, args)) == -1)
4899		return;
4900
4901	write_data_len(argp, len);
4902	va_end(args);
4903}
4904
4905static void
4906write_data_len(const char *buf, int len)
4907{
4908	int remaining, copied;
4909
4910	remaining = BUFSIZ - (nfrontp - netobuf);
4911	while (len > 0) {
4912		/*
4913		 * If there's not enough space in netobuf then
4914		 * try to make some.
4915		 */
4916	if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
4917			netflush();
4918			remaining = BUFSIZ - (nfrontp - netobuf);
4919		}
4920		/* Copy as much as we can */
4921		copied = remaining > len ? len : remaining;
4922		(void) memmove(nfrontp, buf, copied);
4923		nfrontp += copied;
4924		len -= copied;
4925		remaining -= copied;
4926		buf += copied;
4927	}
4928}
4929