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