OpenGrok

Cross Reference: in.telnetd.c
xref: /onnv/onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/in.telnetd.c
Home | History | Annotate | Line # | Download | only in usr.sbin
      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 
    115 static char	remopts[MAXOPTLEN];
    116 static char	myopts[MAXOPTLEN];
    117 static uchar_t	doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 };
    118 static uchar_t	dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 };
    119 static uchar_t	will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 };
    120 static uchar_t	wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 };
    121 /*
    122  * I/O data buffers, pointers, and counters.
    123  */
    124 static char	ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
    125 
    126 static char	*netibuf, *netip;
    127 static int	netibufsize;
    128 
    129 #define	NIACCUM(c)	{   *netip++ = c; \
    130 			    ncc++; \
    131 			}
    132 
    133 static char	netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
    134 static char	*neturg = 0;		/* one past last bye of urgent data */
    135 /* the remote system seems to NOT be an old 4.2 */
    136 static int	not42 = 1;
    137 static char	defaultfile[] = "/etc/default/telnetd";
    138 static char	bannervar[] = "BANNER=";
    139 
    140 static char BANNER1[] = "\r\n\r\n";
    141 static 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  */
    147 static 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 
    160 extern uint_t kwarn_add_warning(char *, int);
    161 extern uint_t kwarn_del_warning(char *);
    162 
    163 static boolean_t auth_debug = 0;
    164 static boolean_t negotiate_auth_krb5 = 1;
    165 static boolean_t auth_negotiated = 0;
    166 static int auth_status = 0;
    167 static int auth_level = 0;
    168 static char	*AuthenticatingUser = NULL;
    169 static char	*krb5_name = NULL;
    170 
    171 static krb5_address rsaddr = { 0, 0, 0, NULL };
    172 static krb5_address rsport = { 0, 0, 0, NULL };
    173 
    174 static krb5_context telnet_context = 0;
    175 static krb5_auth_context auth_context = 0;
    176 
    177 /* telnetd gets session key from here */
    178 static krb5_ticket *ticket = NULL;
    179 static krb5_keyblock *session_key = NULL;
    180 static char *telnet_srvtab = NULL;
    181 
    182 typedef struct {
    183 	uchar_t AuthName;
    184 	uchar_t AuthHow;
    185 	char  *AuthString;
    186 } AuthInfo;
    187 
    188 static 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 
    198 static AuthInfo NoAuth = {0, 0, NULL};
    199 
    200 static 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 
    206 static void auth_name(uchar_t *, int);
    207 static 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 
    214 static telnet_enc_data_t  encr_data;
    215 static boolean_t negotiate_encrypt = B_TRUE;
    216 static boolean_t sent_encrypt_support = B_FALSE;
    217 static boolean_t sent_will_encrypt = B_FALSE;
    218 static boolean_t sent_do_encrypt = B_FALSE;
    219 static boolean_t enc_debug = 0;
    220 
    221 static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo);
    222 static int  encrypt_send_encrypt_is();
    223 
    224 extern void mit_des_fixup_key_parity(Block);
    225 extern int krb5_setenv(const char *, const char *, int);
    226 /* need to know what FD to use to talk to the crypto module */
    227 static 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 
    244 static int	ncc;
    245 static int	master;		/* master side of pty */
    246 static int	pty;		/* side of pty that gets ioctls */
    247 static int	net;
    248 static int	inter;
    249 extern char **environ;
    250 static char	*line;
    251 static int	SYNCHing = 0;		/* we are in TELNET SYNCH mode */
    252 static int	state = TS_DATA;
    253 
    254 static int env_ovar = -1;	/* XXX.sparker */
    255 static int env_ovalue = -1;	/* XXX.sparker */
    256 static char pam_svc_name[64];
    257 static boolean_t	telmod_init_done = B_FALSE;
    258 
    259 static void	doit(int, struct sockaddr_storage *);
    260 static void	willoption(int);
    261 static void	wontoption(int);
    262 static void	dooption(int);
    263 static void	dontoption(int);
    264 static void	fatal(int, char *);
    265 static void	fatalperror(int, char *, int);
    266 static void	mode(int, int);
    267 static void	interrupt(void);
    268 static void	drainstream(int);
    269 static int	readstream(int, char *, int);
    270 static int	send_oob(int fd, char *ptr, int count);
    271 static int	local_setenv(const char *name, const char *value, int rewrite);
    272 static void	local_unsetenv(const char *name);
    273 static void	suboption(void);
    274 static int	removemod(int f, char *modname);
    275 static void	willoption(int option);
    276 static void	wontoption(int option);
    277 static void	dooption(int option);
    278 static void	dontoption(int option);
    279 static void	write_data(const char *, ...);
    280 static void	write_data_len(const char *, int);
    281 static void	rmut(void);
    282 static void	cleanup(int);
    283 static void	telnet(int, int);
    284 static void	telrcv(void);
    285 static void	sendbrk(void);
    286 static void	ptyflush(void);
    287 static void	netclear(void);
    288 static void	netflush(void);
    289 static void	showbanner(void);
    290 static void	map_banner(char *);
    291 static void	defbanner(void);
    292 static 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 
    303 struct envlist {
    304 	struct envlist	*next;
    305 	char		*name;
    306 	char		*value;
    307 	int		delete;
    308 };
    309 
    310 static 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 
    317 static 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 
    345 static int init_neg_done = 0;
    346 static boolean_t resolve_hostname = 0;
    347 static boolean_t show_hostinfo = 1;
    348 
    349 #define	settimer(x)	(clocks.x = ++clocks.system)
    350 #define	sequenceIs(x, y)	(clocks.x < clocks.y)
    351 
    352 static void send_will(int);
    353 static void send_wont(int);
    354 static void send_do(int);
    355 static char *__findenv(const char *name, int *offset);
    356 
    357 /* ARGSUSED */
    358 static void
    359 auth_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 
    407 static void
    408 reply_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) &&\
    445 defined(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. */
    460 static krb5_error_code
    461 rd_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 
    525 cleanup:
    526 	krb5_free_creds(context, *creds);
    527 	return (retval);
    528 }
    529 
    530 static void
    531 kerberos5_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 
    853 errout:
    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 
    867 static int
    868 krb5_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 
    883 static void
    884 auth_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 
    909 static void
    910 auth_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 != NULL &&
    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 
    939 static int
    940 krb5_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  */
    971 static int
    972 getrandom(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  */
    997 static void
    998 encrypt_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  */
   1013 static void
   1014 encrypt_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  */
   1050 static void
   1051 encrypt_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 = NULL;
   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  */
   1175 static int
   1176 encrypt_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  */
   1296 static void
   1297 stop_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  */
   1321 static void
   1322 start_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  */
   1342 static void
   1343 encrypt_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  */
   1469 static void
   1470 encrypt_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  */
   1487 static void
   1488 encrypt_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  */
   1530 static void
   1531 encrypt_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  */
   1559 static void
   1560 encrypt_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  */
   1581 static void
   1582 encrypt_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  */
   1714 static void
   1715 encrypt_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  */
   1783 static void
   1784 encrypt_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  */
   1836 static void
   1837 encrypt_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 
   1910 static void
   1911 encrypt_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  */
   1966 static void
   1967 encrypt_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  */
   2044 static void
   2045 encrypt_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  */
   2060 static void
   2061 encrypt_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  */
   2072 static void
   2073 encrypt_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  */
   2109 static int
   2110 new_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  */
   2139 static int
   2140 del_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 
   2153 static int
   2154 issock(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  */
   2168 static int
   2169 audit_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 */
   2188 int
   2189 main(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 
   2405 static 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  */
   2415 static void
   2416 ttloop(void)
   2417 {
   2418 	if (nfrontp-nbackp) {
   2419 		netflush();
   2420 	}
   2421 read_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 
   2441 static void
   2442 send_do(int option)
   2443 {
   2444 	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option);
   2445 }
   2446 
   2447 static void
   2448 send_will(int option)
   2449 {
   2450 	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option);
   2451 }
   2452 
   2453 static void
   2454 send_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  */
   2465 static int
   2466 getauthtype(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 
   2555 static void
   2556 getencrtype(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  */
   2621 static void
   2622 getterminaltype(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 
   2731 pid_t pid;
   2732 
   2733 /*
   2734  * Get a pty, scan input lines.
   2735  */
   2736 static void
   2737 doit(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") == '\0' && 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 
   3227 static void
   3228 fatal(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 
   3238 static void
   3239 fatalperror(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  */
   3256 static void
   3257 telnet(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 
   3436 static void
   3437 telrcv(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 
   3649 static void
   3650 willoption(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;
   3701 common:
   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 
   3746 static void
   3747 wontoption(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  */
   3818 static void
   3819 dooption(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  */
   3910 static void
   3911 dontoption(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  */
   3952 static void
   3953 suboption(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 
   4195 static void
   4196 mode(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  */
   4238 static void
   4239 interrupt(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  */
   4260 static void
   4261 sendbrk(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 
   4276 static void
   4277 ptyflush(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 
   4301 static char *
   4302 nextitem(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  */
   4347 static void
   4348 netclear(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  */
   4393 static void
   4394 netflush(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 */
   4444 static void
   4445 cleanup(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 
   4470 static void
   4471 rmut(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 
   4539 static int
   4540 readstream(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 
   4591 static void
   4592 drainstream(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  */
   4616 static int
   4617 send_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  */
   4645 static int
   4646 local_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  */
   4720 static void
   4721 local_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  */
   4739 static 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 
   4760 static void
   4761 showbanner(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 
   4819 static void
   4820 map_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  */
   4848 static void
   4849 defbanner(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  */
   4873 static int
   4874 removemod(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 
   4889 static void
   4890 write_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 
   4905 static void
   4906 write_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