Home | History | Annotate | Download | only in usr.sbin
      1     0    stevel /*
      2     0    stevel  * CDDL HEADER START
      3     0    stevel  *
      4     0    stevel  * The contents of this file are subject to the terms of the
      5  2923       raf  * Common Development and Distribution License (the "License").
      6  2923       raf  * You may not use this file except in compliance with the License.
      7     0    stevel  *
      8     0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0    stevel  * or http://www.opensolaris.org/os/licensing.
     10     0    stevel  * See the License for the specific language governing permissions
     11     0    stevel  * and limitations under the License.
     12     0    stevel  *
     13     0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0    stevel  *
     19     0    stevel  * CDDL HEADER END
     20  2923       raf  */
     21  2923       raf 
     22  2923       raf /*
     23  6536       gtb  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24     0    stevel  * Use is subject to license terms.
     25     0    stevel  */
     26     0    stevel 
     27     0    stevel /*
     28     0    stevel  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
     29     0    stevel  * All Rights Reserved.
     30     0    stevel  */
     31     0    stevel 
     32     0    stevel /*
     33     0    stevel  * University Copyright- Copyright (c) 1982, 1986, 1988
     34     0    stevel  * The Regents of the University of California.
     35     0    stevel  * All Rights Reserved.
     36     0    stevel  *
     37     0    stevel  * University Acknowledgment- Portions of this document are derived from
     38     0    stevel  * software developed by the University of California, Berkeley, and its
     39     0    stevel  * contributors.
     40     0    stevel  */
     41     0    stevel 
     42     0    stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     43     0    stevel 
     44     0    stevel /*
     45     0    stevel  * Telnet server.
     46     0    stevel  */
     47     0    stevel #include <sys/types.h>
     48     0    stevel #include <sys/param.h>
     49     0    stevel #include <sys/socket.h>
     50     0    stevel #include <sys/wait.h>
     51     0    stevel #include <sys/file.h>
     52     0    stevel #include <sys/stat.h>
     53     0    stevel #include <sys/filio.h>
     54     0    stevel #include <sys/time.h>
     55     0    stevel #include <sys/stropts.h>
     56     0    stevel #include <sys/stream.h>
     57     0    stevel #include <sys/tihdr.h>
     58     0    stevel #include <sys/utsname.h>
     59     0    stevel #include <unistd.h>
     60     0    stevel 
     61     0    stevel #include <netinet/in.h>
     62     0    stevel 
     63     0    stevel #define	AUTHWHO_STR
     64     0    stevel #define	AUTHTYPE_NAMES
     65     0    stevel #define	AUTHHOW_NAMES
     66     0    stevel #define	AUTHRSP_NAMES
     67     0    stevel #define	ENCRYPT_NAMES
     68     0    stevel 
     69     0    stevel #include <arpa/telnet.h>
     70     0    stevel #include <arpa/inet.h>
     71     0    stevel #include <stdio.h>
     72     0    stevel #include <stdarg.h>
     73     0    stevel #include <signal.h>
     74     0    stevel #include <errno.h>
     75     0    stevel #include <netdb.h>
     76     0    stevel #include <syslog.h>
     77     0    stevel #include <ctype.h>
     78     0    stevel #include <fcntl.h>
     79     0    stevel #include <sac.h>	/* for SC_WILDC */
     80     0    stevel #include <utmpx.h>
     81     0    stevel #include <sys/ttold.h>
     82     0    stevel #include <malloc.h>
     83     0    stevel #include <string.h>
     84     0    stevel #include <security/pam_appl.h>
     85     0    stevel #include <sys/tihdr.h>
     86     0    stevel #include <sys/logindmux.h>
     87     0    stevel #include <sys/telioctl.h>
     88     0    stevel #include <deflt.h>
     89     0    stevel #include <stdlib.h>
     90     0    stevel #include <string.h>
     91     0    stevel #include <stropts.h>
     92     0    stevel #include <termios.h>
     93     0    stevel 
     94     0    stevel #include <com_err.h>
     95     0    stevel #include <krb5.h>
     96     0    stevel #include <krb5_repository.h>
     97     0    stevel #include <des/des.h>
     98     0    stevel #include <rpc/des_crypt.h>
     99     0    stevel #include <sys/cryptmod.h>
    100     0    stevel #include <bsm/adt.h>
    101     0    stevel 
    102     0    stevel #define	TELNETD_OPTS "Ss:a:dEXUhR:M:"
    103     0    stevel #ifdef DEBUG
    104     0    stevel #define	DEBUG_OPTS "p:e"
    105     0    stevel #else
    106     0    stevel #define	DEBUG_OPTS ""
    107     0    stevel #endif /* DEBUG */
    108     0    stevel 
    109     0    stevel #define	OPT_NO			0		/* won't do this option */
    110     0    stevel #define	OPT_YES			1		/* will do this option */
    111     0    stevel #define	OPT_YES_BUT_ALWAYS_LOOK	2
    112     0    stevel #define	OPT_NO_BUT_ALWAYS_LOOK	3
    113     0    stevel 
    114     0    stevel #define	MAXOPTLEN 256
    115     0    stevel #define	MAXUSERNAMELEN 256
    116     0    stevel 
    117     0    stevel static char	remopts[MAXOPTLEN];
    118     0    stevel static char	myopts[MAXOPTLEN];
    119     0    stevel static uchar_t	doopt[] = { (uchar_t)IAC, (uchar_t)DO, '%', 'c', 0 };
    120     0    stevel static uchar_t	dont[] = { (uchar_t)IAC, (uchar_t)DONT, '%', 'c', 0 };
    121     0    stevel static uchar_t	will[] = { (uchar_t)IAC, (uchar_t)WILL, '%', 'c', 0 };
    122     0    stevel static uchar_t	wont[] = { (uchar_t)IAC, (uchar_t)WONT, '%', 'c', 0 };
    123     0    stevel /*
    124     0    stevel  * I/O data buffers, pointers, and counters.
    125     0    stevel  */
    126     0    stevel static char	ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
    127     0    stevel 
    128     0    stevel static char	*netibuf, *netip;
    129     0    stevel static int	netibufsize;
    130     0    stevel 
    131     0    stevel #define	NIACCUM(c)	{   *netip++ = c; \
    132     0    stevel 			    ncc++; \
    133     0    stevel 			}
    134     0    stevel 
    135     0    stevel static char	netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
    136     0    stevel static char	*neturg = 0;		/* one past last bye of urgent data */
    137     0    stevel /* the remote system seems to NOT be an old 4.2 */
    138     0    stevel static int	not42 = 1;
    139     0    stevel static char	defaultfile[] = "/etc/default/telnetd";
    140     0    stevel static char	bannervar[] = "BANNER=";
    141     0    stevel 
    142     0    stevel static char BANNER1[] = "\r\n\r\n";
    143     0    stevel static char BANNER2[] = "\r\n\r\0\r\n\r\0";
    144     0    stevel 
    145     0    stevel /*
    146     0    stevel  * buffer for sub-options - enlarged to 4096 to handle credentials
    147     0    stevel  * from AUTH options
    148     0    stevel  */
    149     0    stevel static char	subbuffer[4096], *subpointer = subbuffer, *subend = subbuffer;
    150     0    stevel #define	SB_CLEAR()	subpointer = subbuffer;
    151     0    stevel #define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
    152     0    stevel #define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof (subbuffer))) { \
    153     0    stevel 				*subpointer++ = (c); \
    154     0    stevel 			}
    155     0    stevel #define	SB_GET()	((*subpointer++)&0xff)
    156     0    stevel #define	SB_EOF()	(subpointer >= subend)
    157     0    stevel #define	SB_LEN()	(subend - subpointer)
    158     0    stevel 
    159     0    stevel #define	MAXERRSTRLEN 1024
    160     0    stevel #define	MAXPRINCLEN 256
    161  6536       gtb 
    162  6536       gtb extern uint_t kwarn_add_warning(char *, int);
    163  6536       gtb extern uint_t kwarn_del_warning(char *);
    164     0    stevel 
    165     0    stevel static boolean_t auth_debug = 0;
    166     0    stevel static boolean_t negotiate_auth_krb5 = 1;
    167     0    stevel static boolean_t auth_negotiated = 0;
    168     0    stevel static int auth_status = 0;
    169     0    stevel static int auth_level = 0;
    170     0    stevel static char	*AuthenticatingUser = NULL;
    171     0    stevel static char	*krb5_name = NULL;
    172     0    stevel 
    173     0    stevel static krb5_address rsaddr = { 0, 0, 0, NULL };
    174     0    stevel static krb5_address rsport = { 0, 0, 0, NULL };
    175     0    stevel 
    176     0    stevel static krb5_context telnet_context = 0;
    177     0    stevel static krb5_auth_context auth_context = 0;
    178     0    stevel 
    179     0    stevel /* telnetd gets session key from here */
    180     0    stevel static krb5_ticket *ticket = NULL;
    181     0    stevel static krb5_keyblock *session_key = NULL;
    182     0    stevel static char *telnet_srvtab = NULL;
    183     0    stevel 
    184     0    stevel typedef struct {
    185     0    stevel 	uchar_t AuthName;
    186     0    stevel 	uchar_t AuthHow;
    187     0    stevel 	char  *AuthString;
    188     0    stevel } AuthInfo;
    189     0    stevel 
    190     0    stevel static AuthInfo auth_list[] = {
    191     0    stevel 	{AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL |
    192     0    stevel 	AUTH_ENCRYPT_ON, "KRB5 MUTUAL CRYPTO"},
    193     0    stevel 	{AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT | AUTH_HOW_MUTUAL,
    194     0    stevel 	"KRB5 MUTUAL" },
    195     0    stevel 	{AUTHTYPE_KERBEROS_V5,	AUTH_WHO_CLIENT | AUTH_HOW_ONE_WAY,
    196     0    stevel 	"KRB5 1-WAY" },
    197     0    stevel 	{0, 0, "NONE"}
    198     0    stevel };
    199     0    stevel 
    200     0    stevel static AuthInfo NoAuth = {0, 0, NULL};
    201     0    stevel 
    202     0    stevel static AuthInfo *authenticated = NULL;
    203     0    stevel 
    204     0    stevel #define	PREAMBLE_SIZE		5	/* for auth_reply_str allocation */
    205     0    stevel #define	POSTAMBLE_SIZE		5
    206     0    stevel #define	STR_DATA_LEN(len)	((len) * 2 + PREAMBLE_SIZE + POSTAMBLE_SIZE)
    207     0    stevel 
    208     0    stevel static void auth_name(uchar_t *, int);
    209     0    stevel static void auth_is(uchar_t *, int);
    210     0    stevel 
    211     0    stevel #define	NO_ENCRYPTION   0x00
    212     0    stevel #define	SEND_ENCRYPTED  0x01
    213     0    stevel #define	RECV_ENCRYPTED  0x02
    214     0    stevel #define	ENCRYPT_BOTH_WAYS    (SEND_ENCRYPTED | RECV_ENCRYPTED)
    215     0    stevel 
    216     0    stevel static telnet_enc_data_t  encr_data;
    217     0    stevel static boolean_t negotiate_encrypt = B_TRUE;
    218     0    stevel static boolean_t sent_encrypt_support = B_FALSE;
    219     0    stevel static boolean_t sent_will_encrypt = B_FALSE;
    220     0    stevel static boolean_t sent_do_encrypt = B_FALSE;
    221     0    stevel static boolean_t enc_debug = 0;
    222     0    stevel 
    223     0    stevel static void encrypt_session_key(Session_Key *key, cipher_info_t *cinfo);
    224     0    stevel static int  encrypt_send_encrypt_is();
    225     0    stevel 
    226     0    stevel extern void mit_des_fixup_key_parity(Block);
    227     0    stevel extern int krb5_setenv(const char *, const char *, int);
    228     0    stevel /* need to know what FD to use to talk to the crypto module */
    229     0    stevel static int cryptmod_fd = -1;
    230     0    stevel 
    231     0    stevel #define	LOGIN_PROGRAM "/bin/login"
    232     0    stevel 
    233     0    stevel /*
    234     0    stevel  * State for recv fsm
    235     0    stevel  */
    236     0    stevel #define	TS_DATA		0	/* base state */
    237     0    stevel #define	TS_IAC		1	/* look for double IAC's */
    238     0    stevel #define	TS_CR		2	/* CR-LF ->'s CR */
    239     0    stevel #define	TS_SB		3	/* throw away begin's... */
    240     0    stevel #define	TS_SE		4	/* ...end's (suboption negotiation) */
    241     0    stevel #define	TS_WILL		5	/* will option negotiation */
    242     0    stevel #define	TS_WONT		6	/* wont " */
    243     0    stevel #define	TS_DO		7	/* do " */
    244     0    stevel #define	TS_DONT		8	/* dont " */
    245     0    stevel 
    246     0    stevel static int	ncc;
    247     0    stevel static int	master;		/* master side of pty */
    248     0    stevel static int	pty;		/* side of pty that gets ioctls */
    249     0    stevel static int	net;
    250     0    stevel static int	inter;
    251     0    stevel extern char **environ;
    252     0    stevel static char	*line;
    253     0    stevel static int	SYNCHing = 0;		/* we are in TELNET SYNCH mode */
    254     0    stevel static int	state = TS_DATA;
    255     0    stevel 
    256     0    stevel static int env_ovar = -1;	/* XXX.sparker */
    257     0    stevel static int env_ovalue = -1;	/* XXX.sparker */
    258     0    stevel static char pam_svc_name[64];
    259     0    stevel static boolean_t	telmod_init_done = B_FALSE;
    260     0    stevel 
    261     0    stevel static void	doit(int, struct sockaddr_storage *);
    262     0    stevel static void	willoption(int);
    263     0    stevel static void	wontoption(int);
    264     0    stevel static void	dooption(int);
    265     0    stevel static void	dontoption(int);
    266     0    stevel static void	fatal(int, char *);
    267     0    stevel static void	fatalperror(int, char *, int);
    268     0    stevel static void	mode(int, int);
    269     0    stevel static void	interrupt(void);
    270     0    stevel static void	drainstream(int);
    271     0    stevel static int	readstream(int, char *, int);
    272     0    stevel static int	send_oob(int fd, char *ptr, int count);
    273     0    stevel static int	local_setenv(const char *name, const char *value, int rewrite);
    274     0    stevel static void	local_unsetenv(const char *name);
    275     0    stevel static void	suboption(void);
    276     0    stevel static int	removemod(int f, char *modname);
    277     0    stevel static void	willoption(int option);
    278     0    stevel static void	wontoption(int option);
    279     0    stevel static void	dooption(int option);
    280     0    stevel static void	dontoption(int option);
    281     0    stevel static void	write_data(const char *, ...);
    282     0    stevel static void	write_data_len(const char *, int);
    283     0    stevel static void	rmut(void);
    284     0    stevel static void	cleanup(int);
    285     0    stevel static void	telnet(int, int);
    286     0    stevel static void	telrcv(void);
    287     0    stevel static void	sendbrk(void);
    288     0    stevel static void	ptyflush(void);
    289     0    stevel static void	netclear(void);
    290     0    stevel static void	netflush(void);
    291     0    stevel static void	showbanner(void);
    292     0    stevel static void	map_banner(char *);
    293     0    stevel static void	defbanner(void);
    294     0    stevel static void ttloop(void);
    295     0    stevel 
    296     0    stevel /*
    297     0    stevel  * The env_list linked list is used to store the environment variables
    298     0    stevel  * until the final exec of login.  A malevolent client might try to
    299     0    stevel  * send an environment variable intended to affect the telnet daemon's
    300     0    stevel  * execution.  Right now the BANNER expansion is the only instance.
    301     0    stevel  * Note that it is okay to pass the environment variables to login
    302     0    stevel  * because login protects itself against environment variables mischief.
    303     0    stevel  */
    304     0    stevel 
    305     0    stevel struct envlist {
    306     0    stevel 	struct envlist	*next;
    307     0    stevel 	char		*name;
    308     0    stevel 	char		*value;
    309     0    stevel 	int		delete;
    310     0    stevel };
    311     0    stevel 
    312     0    stevel static struct envlist *envlist_head = NULL;
    313     0    stevel 
    314     0    stevel /*
    315     0    stevel  * The following are some clocks used to decide how to interpret
    316     0    stevel  * the relationship between various variables.
    317     0    stevel  */
    318     0    stevel 
    319     0    stevel static struct {
    320     0    stevel 	int
    321     0    stevel 	system,			/* what the current time is */
    322     0    stevel 	echotoggle,		/* last time user entered echo character */
    323     0    stevel 	modenegotiated,		/* last time operating mode negotiated */
    324     0    stevel 	didnetreceive,		/* last time we read data from network */
    325     0    stevel 	ttypeopt,		/* ttype will/won't received */
    326     0    stevel 	ttypesubopt,		/* ttype subopt is received */
    327     0    stevel 	getterminal,		/* time started to get terminal information */
    328     0    stevel 	xdisplocopt,		/* xdisploc will/wont received */
    329     0    stevel 	xdisplocsubopt,		/* xdisploc suboption received */
    330     0    stevel 	nawsopt,		/* window size will/wont received */
    331     0    stevel 	nawssubopt,		/* window size received */
    332     0    stevel 	environopt,		/* environment option will/wont received */
    333     0    stevel 	oenvironopt,		/* "old" environ option will/wont received */
    334     0    stevel 	environsubopt,		/* environment option suboption received */
    335     0    stevel 	oenvironsubopt,		/* "old environ option suboption received */
    336     0    stevel 	gotDM;			/* when did we last see a data mark */
    337     0    stevel 
    338     0    stevel 	int getauth;
    339     0    stevel 	int authopt;	/* Authentication option negotiated */
    340     0    stevel 	int authdone;
    341     0    stevel 
    342     0    stevel 	int getencr;
    343     0    stevel 	int encropt;
    344     0    stevel 	int encr_support;
    345     0    stevel } clocks;
    346     0    stevel 
    347     0    stevel static int init_neg_done = 0;
    348     0    stevel static boolean_t resolve_hostname = 0;
    349     0    stevel static boolean_t show_hostinfo = 1;
    350     0    stevel 
    351     0    stevel #define	settimer(x)	(clocks.x = ++clocks.system)
    352     0    stevel #define	sequenceIs(x, y)	(clocks.x < clocks.y)
    353     0    stevel 
    354     0    stevel static void send_will(int);
    355     0    stevel static void send_wont(int);
    356     0    stevel static void send_do(int);
    357     0    stevel static char *__findenv(const char *name, int *offset);
    358     0    stevel 
    359     0    stevel /* ARGSUSED */
    360     0    stevel static void
    361     0    stevel auth_finished(AuthInfo *ap, int result)
    362     0    stevel {
    363     0    stevel 	if ((authenticated = ap) == NULL) {
    364     0    stevel 		authenticated = &NoAuth;
    365     0    stevel 		if (myopts[TELOPT_ENCRYPT] == OPT_YES)
    366     0    stevel 			send_wont(TELOPT_ENCRYPT);
    367     0    stevel 		myopts[TELOPT_ENCRYPT] = remopts[TELOPT_ENCRYPT] = OPT_NO;
    368     0    stevel 		encr_data.encrypt.autoflag = 0;
    369     0    stevel 	} else if (result != AUTH_REJECT &&
    370     0    stevel 		myopts[TELOPT_ENCRYPT] == OPT_YES &&
    371     0    stevel 		remopts[TELOPT_ENCRYPT] == OPT_YES) {
    372     0    stevel 
    373     0    stevel 		/*
    374     0    stevel 		 * Authentication successful, so we have a session key, and
    375     0    stevel 		 * we're willing to do ENCRYPT, so send our ENCRYPT SUPPORT.
    376     0    stevel 		 *
    377     0    stevel 		 * Can't have sent ENCRYPT SUPPORT yet!  And if we're sending it
    378     0    stevel 		 * now it's really only because we did the DO ENCRYPT/WILL
    379     0    stevel 		 * ENCRYPT dance before authentication, which is ok, but not too
    380     0    stevel 		 * bright since we have to do the DONT ENCRYPT/WONT ENCRYPT
    381     0    stevel 		 * dance if authentication fails, though clients typically just
    382     0    stevel 		 * don't care.
    383     0    stevel 		 */
    384     0    stevel 		write_data("%c%c%c%c%c%c%c",
    385     0    stevel 			(uchar_t)IAC,
    386     0    stevel 			(uchar_t)SB,
    387     0    stevel 			(uchar_t)TELOPT_ENCRYPT,
    388     0    stevel 			(uchar_t)ENCRYPT_SUPPORT,
    389     0    stevel 			(uchar_t)TELOPT_ENCTYPE_DES_CFB64,
    390     0    stevel 			(uchar_t)IAC,
    391     0    stevel 			(uchar_t)SE);
    392     0    stevel 
    393     0    stevel 		netflush();
    394     0    stevel 
    395     0    stevel 		sent_encrypt_support = B_TRUE;
    396     0    stevel 
    397     0    stevel 		if (enc_debug)
    398     0    stevel 			(void) fprintf(stderr,
    399     0    stevel 			"SENT ENCRYPT SUPPORT\n");
    400     0    stevel 
    401     0    stevel 		(void) encrypt_send_encrypt_is();
    402     0    stevel 	}
    403     0    stevel 
    404     0    stevel 	auth_status = result;
    405     0    stevel 
    406     0    stevel 	settimer(authdone);
    407     0    stevel }
    408     0    stevel 
    409     0    stevel static void
    410     0    stevel reply_to_client(AuthInfo *ap, int type, void *data, int len)
    411     0    stevel {
    412     0    stevel 	uchar_t reply[BUFSIZ];
    413     0    stevel 	uchar_t *p = reply;
    414     0    stevel 	uchar_t *cd = (uchar_t *)data;
    415     0    stevel 
    416     0    stevel 	if (len == -1 && data != NULL)
    417     0    stevel 		len = strlen((char *)data);
    418     0    stevel 	else if (len > (sizeof (reply) - 9)) {
    419     0    stevel 		syslog(LOG_ERR,
    420     0    stevel 		    "krb5 auth reply length too large (%d)", len);
    421     0    stevel 		if (auth_debug)
    422     0    stevel 			(void) fprintf(stderr,
    423     0    stevel 				    "krb5 auth reply length too large (%d)\n",
    424     0    stevel 				    len);
    425     0    stevel 		return;
    426     0    stevel 	} else if (data == NULL)
    427     0    stevel 		len = 0;
    428     0    stevel 
    429     0    stevel 	*p++ = IAC;
    430     0    stevel 	*p++ = SB;
    431     0    stevel 	*p++ = TELOPT_AUTHENTICATION;
    432     0    stevel 	*p++ = AUTHTYPE_KERBEROS_V5;
    433     0    stevel 	*p++ = ap->AuthName;
    434     0    stevel 	*p++ = ap->AuthHow; /* MUTUAL, ONE-WAY, etc */
    435     0    stevel 	*p++ = type;	    /* RESPONSE or ACCEPT */
    436     0    stevel 	while (len-- > 0) {
    437     0    stevel 		if ((*p++ = *cd++) == IAC)
    438     0    stevel 			*p++ = IAC;
    439     0    stevel 	}
    440     0    stevel 	*p++ = IAC;
    441     0    stevel 	*p++ = SE;
    442     0    stevel 
    443     0    stevel 	/* queue the data to be sent */
    444     0    stevel 	write_data_len((const char *)reply, p-reply);
    445     0    stevel 
    446     0    stevel #if defined(AUTHTYPE_NAMES) && defined(AUTHWHO_STR) &&\
    447     0    stevel defined(AUTHHOW_NAMES) && defined(AUTHRSP_NAMES)
    448     0    stevel 	if (auth_debug) {
    449     0    stevel 		(void) fprintf(stderr, "SENT TELOPT_AUTHENTICATION REPLY "
    450     0    stevel 			    "%s %s|%s %s\n",
    451     0    stevel 			    AUTHTYPE_NAME(ap->AuthName),
    452     0    stevel 			    AUTHWHO_NAME(ap->AuthHow & AUTH_WHO_MASK),
    453     0    stevel 			    AUTHHOW_NAME(ap->AuthHow & AUTH_HOW_MASK),
    454     0    stevel 			    AUTHRSP_NAME(type));
    455     0    stevel 	}
    456     0    stevel #endif /* AUTHTYPE_NAMES && AUTHWHO_NAMES && AUTHHOW_NAMES && AUTHRSP_NAMES */
    457     0    stevel 
    458     0    stevel 	netflush();
    459     0    stevel }
    460     0    stevel 
    461     0    stevel /* Decode, decrypt and store the forwarded creds in the local ccache. */
    462     0    stevel static krb5_error_code
    463     0    stevel rd_and_store_forwarded_creds(krb5_context context,
    464     0    stevel 			    krb5_auth_context auth_context,
    465     0    stevel 			    krb5_data *inbuf, krb5_ticket *ticket,
    466     0    stevel 			    char *username)
    467     0    stevel {
    468     0    stevel 	krb5_creds **creds;
    469     0    stevel 	krb5_error_code retval;
    470  6536       gtb 	char ccname[MAXPATHLEN];
    471     0    stevel 	krb5_ccache ccache = NULL;
    472  6536       gtb 	char *client_name = NULL;
    473     0    stevel 
    474     0    stevel 	if (retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))
    475     0    stevel 		return (retval);
    476     0    stevel 
    477     0    stevel 	(void) sprintf(ccname, "FILE:/tmp/krb5cc_p%ld", getpid());
    478     0    stevel 	(void) krb5_setenv("KRB5CCNAME", ccname, 1);
    479     0    stevel 
    480     0    stevel 	if ((retval = krb5_cc_default(context, &ccache)))
    481     0    stevel 		goto cleanup;
    482     0    stevel 
    483     0    stevel 	if ((retval = krb5_cc_initialize(context, ccache,
    484     0    stevel 					ticket->enc_part2->client)) != 0)
    485     0    stevel 		goto cleanup;
    486     0    stevel 
    487     0    stevel 	if ((retval = krb5_cc_store_cred(context, ccache, *creds)) != 0)
    488     0    stevel 		goto cleanup;
    489     0    stevel 
    490     0    stevel 	if ((retval = krb5_cc_close(context, ccache)) != 0)
    491     0    stevel 		goto cleanup;
    492  6536       gtb 
    493  6536       gtb 	/* Register with ktkt_warnd(1M) */
    494  6536       gtb 	if ((retval = krb5_unparse_name(context, (*creds)->client,
    495  6536       gtb 					&client_name)) != 0)
    496  6536       gtb 		goto cleanup;
    497  6536       gtb 	(void) kwarn_del_warning(client_name);
    498  6536       gtb 	if (kwarn_add_warning(client_name, (*creds)->times.endtime) != 0) {
    499  6536       gtb 		syslog(LOG_AUTH|LOG_NOTICE,
    500  6536       gtb 		    "rd_and_store_forwarded_creds: kwarn_add_warning"
    501  6536       gtb 		    " failed: ktkt_warnd(1M) down? ");
    502  6536       gtb 		if (auth_debug)
    503  6536       gtb 			(void) fprintf(stderr,
    504  6536       gtb 				    "kwarn_add_warning failed:"
    505  6536       gtb 				    " ktkt_warnd(1M) down?\n");
    506  6536       gtb 	}
    507  6536       gtb 	free(client_name);
    508  6536       gtb 	client_name = NULL;
    509     0    stevel 
    510     0    stevel 	if (username != NULL) {
    511     0    stevel 		/*
    512     0    stevel 		 * This verifies that the user is valid on the local system,
    513     0    stevel 		 * maps the username from KerberosV5 to unix,
    514     0    stevel 		 * and moves the KRB5CCNAME file to the correct place
    515     0    stevel 		 *  /tmp/krb5cc_[uid] with correct ownership (0600 uid gid).
    516     0    stevel 		 *
    517     0    stevel 		 * NOTE: the user must be in the gsscred table in order to map
    518     0    stevel 		 * from KRB5 to Unix.
    519     0    stevel 		 */
    520     0    stevel 		(void) krb5_kuserok(context, ticket->enc_part2->client,
    521     0    stevel 				username);
    522     0    stevel 	}
    523     0    stevel 	if (auth_debug)
    524     0    stevel 		(void) fprintf(stderr,
    525     0    stevel 			    "Successfully stored forwarded creds\n");
    526     0    stevel 
    527     0    stevel cleanup:
    528     0    stevel 	krb5_free_creds(context, *creds);
    529     0    stevel 	return (retval);
    530     0    stevel }
    531     0    stevel 
    532     0    stevel static void
    533     0    stevel kerberos5_is(AuthInfo *ap, uchar_t *data, int cnt)
    534     0    stevel {
    535     0    stevel 	krb5_error_code err = 0;
    536     0    stevel 	krb5_principal server;
    537     0    stevel 	krb5_keyblock *newkey = NULL;
    538     0    stevel 	krb5_keytab keytabid = 0;
    539     0    stevel 	krb5_data outbuf;
    540     0    stevel 	krb5_data inbuf;
    541     0    stevel 	krb5_authenticator *authenticator;
    542     0    stevel 	char errbuf[MAXERRSTRLEN];
    543     0    stevel 	char *name;
    544     0    stevel 	krb5_data auth;
    545     0    stevel 
    546     0    stevel 	Session_Key skey;
    547     0    stevel 
    548     0    stevel 	if (cnt-- < 1)
    549     0    stevel 		return;
    550     0    stevel 	switch (*data++) {
    551     0    stevel 	case KRB_AUTH:
    552     0    stevel 		auth.data = (char *)data;
    553     0    stevel 		auth.length = cnt;
    554     0    stevel 
    555     0    stevel 		if (auth_context == NULL) {
    556     0    stevel 			err = krb5_auth_con_init(telnet_context, &auth_context);
    557     0    stevel 			if (err)
    558     0    stevel 				syslog(LOG_ERR,
    559     0    stevel 				    "Error getting krb5 auth "
    560     0    stevel 				    "context: %s", error_message(err));
    561     0    stevel 		}
    562     0    stevel 		if (!err) {
    563     0    stevel 			krb5_rcache rcache;
    564     0    stevel 
    565     0    stevel 			err = krb5_auth_con_getrcache(telnet_context,
    566     0    stevel 						    auth_context,
    567     0    stevel 						    &rcache);
    568     0    stevel 			if (!err && !rcache) {
    569     0    stevel 				err = krb5_sname_to_principal(telnet_context,
    570     0    stevel 							    0, 0,
    571     0    stevel 							    KRB5_NT_SRV_HST,
    572     0    stevel 							    &server);
    573     0    stevel 				if (!err) {
    574     0    stevel 					err = krb5_get_server_rcache(
    575     0    stevel 						telnet_context,
    576     0    stevel 						krb5_princ_component(
    577     0    stevel 							telnet_context,
    578     0    stevel 							server, 0),
    579     0    stevel 						&rcache);
    580     0    stevel 
    581     0    stevel 					krb5_free_principal(telnet_context,
    582     0    stevel 							    server);
    583     0    stevel 				}
    584     0    stevel 			}
    585     0    stevel 			if (err)
    586     0    stevel 				syslog(LOG_ERR,
    587     0    stevel 				    "Error allocating krb5 replay cache: %s",
    588     0    stevel 				    error_message(err));
    589     0    stevel 			else {
    590     0    stevel 				err = krb5_auth_con_setrcache(telnet_context,
    591     0    stevel 							    auth_context,
    592     0    stevel 							    rcache);
    593     0    stevel 				if (err)
    594     0    stevel 					syslog(LOG_ERR,
    595     0    stevel 					    "Error creating krb5 "
    596     0    stevel 					    "replay cache: %s",
    597     0    stevel 					    error_message(err));
    598     0    stevel 			}
    599     0    stevel 		}
    600     0    stevel 		if (!err && telnet_srvtab != NULL)
    601     0    stevel 			err = krb5_kt_resolve(telnet_context,
    602     0    stevel 					    telnet_srvtab, &keytabid);
    603     0    stevel 		if (!err)
    604     0    stevel 			err = krb5_rd_req(telnet_context, &auth_context, &auth,
    605     0    stevel 					NULL, keytabid, NULL, &ticket);
    606     0    stevel 		if (err) {
    607     0    stevel 			(void) snprintf(errbuf, sizeof (errbuf),
    608     0    stevel 				"Error reading krb5 auth information:"
    609     0    stevel 				" %s", error_message(err));
    610     0    stevel 			goto errout;
    611     0    stevel 		}
    612     0    stevel 
    613     0    stevel 		/*
    614     0    stevel 		 * Verify that the correct principal was used
    615     0    stevel 		 */
    616     0    stevel 		if (krb5_princ_component(telnet_context,
    617     0    stevel 				ticket->server, 0)->length < MAXPRINCLEN) {
    618     0    stevel 			char princ[MAXPRINCLEN];
    619     0    stevel 			(void) strncpy(princ,
    620     0    stevel 				    krb5_princ_component(telnet_context,
    621     0    stevel 						ticket->server, 0)->data,
    622     0    stevel 				    krb5_princ_component(telnet_context,
    623     0    stevel 					    ticket->server, 0)->length);
    624     0    stevel 			princ[krb5_princ_component(telnet_context,
    625     0    stevel 					ticket->server, 0)->length] = '\0';
    626     0    stevel 			if (strcmp("host", princ)) {
    627     0    stevel 				if (strlen(princ) < sizeof (errbuf) - 39) {
    628     0    stevel 				    (void) snprintf(errbuf, sizeof (errbuf),
    629     0    stevel 						"incorrect service "
    630     0    stevel 						    "name: \"%s\" != "
    631     0    stevel 						    "\"host\"",
    632     0    stevel 						    princ);
    633     0    stevel 			    } else {
    634     0    stevel 				    (void) strncpy(errbuf,
    635     0    stevel 						"incorrect service "
    636     0    stevel 						"name: principal != "
    637     0    stevel 						"\"host\"",
    638     0    stevel 						sizeof (errbuf));
    639     0    stevel 			    }
    640     0    stevel 			    goto errout;
    641     0    stevel 			}
    642     0    stevel 		} else {
    643     0    stevel 			(void) strlcpy(errbuf, "service name too long",
    644     0    stevel 					sizeof (errbuf));
    645     0    stevel 			goto errout;
    646     0    stevel 		}
    647     0    stevel 
    648     0    stevel 		err = krb5_auth_con_getauthenticator(telnet_context,
    649     0    stevel 						auth_context,
    650     0    stevel 						&authenticator);
    651     0    stevel 		if (err) {
    652     0    stevel 			(void) snprintf(errbuf, sizeof (errbuf),
    653     0    stevel 				"Failed to get authenticator: %s",
    654     0    stevel 				error_message(err));
    655     0    stevel 			goto errout;
    656     0    stevel 		}
    657     0    stevel 		if ((ap->AuthHow & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
    658     0    stevel 			!authenticator->checksum) {
    659     0    stevel 			(void) strlcpy(errbuf,
    660     0    stevel 				    "authenticator is missing checksum",
    661     0    stevel 				    sizeof (errbuf));
    662     0    stevel 			goto errout;
    663     0    stevel 		}
    664     0    stevel 		if (authenticator->checksum) {
    665     0    stevel 			char type_check[2];
    666     0    stevel 			krb5_checksum *cksum = authenticator->checksum;
    667     0    stevel 			krb5_keyblock *key;
    668     0    stevel 			krb5_data input;
    669     0    stevel 			krb5_boolean valid;
    670     0    stevel 
    671     0    stevel 			type_check[0] = ap->AuthName;
    672     0    stevel 			type_check[1] = ap->AuthHow;
    673     0    stevel 
    674     0    stevel 			err = krb5_auth_con_getkey(telnet_context,
    675     0    stevel 						auth_context, &key);
    676     0    stevel 			if (err) {
    677     0    stevel 				(void) snprintf(errbuf, sizeof (errbuf),
    678     0    stevel 					"Failed to get key from "
    679     0    stevel 					"authenticator: %s",
    680     0    stevel 					error_message(err));
    681     0    stevel 				goto errout;
    682     0    stevel 			}
    683     0    stevel 
    684     0    stevel 			input.data = type_check;
    685     0    stevel 			input.length = 2;
    686     0    stevel 			err = krb5_c_verify_checksum(telnet_context,
    687     0    stevel 							key, 0,
    688     0    stevel 							&input,
    689     0    stevel 							cksum,
    690     0    stevel 							&valid);
    691     0    stevel 			if (!err && !valid)
    692     0    stevel 				err = KRB5KRB_AP_ERR_BAD_INTEGRITY;
    693     0    stevel 
    694     0    stevel 			if (err) {
    695     0    stevel 				(void) snprintf(errbuf, sizeof (errbuf),
    696     0    stevel 						"Kerberos checksum "
    697     0    stevel 						"verification failed: "
    698     0    stevel 						"%s",
    699     0    stevel 						error_message(err));
    700     0    stevel 				goto errout;
    701     0    stevel 			}
    702     0    stevel 			krb5_free_keyblock(telnet_context, key);
    703     0    stevel 		}
    704     0    stevel 
    705     0    stevel 		krb5_free_authenticator(telnet_context, authenticator);
    706     0    stevel 		if ((ap->AuthHow & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
    707     0    stevel 			/* do ap_rep stuff here */
    708     0    stevel 			if ((err = krb5_mk_rep(telnet_context, auth_context,
    709     0    stevel 					    &outbuf))) {
    710     0    stevel 				(void) snprintf(errbuf, sizeof (errbuf),
    711     0    stevel 						"Failed to make "
    712     0    stevel 						"Kerberos auth reply: "
    713     0    stevel 						"%s",
    714     0    stevel 						error_message(err));
    715     0    stevel 				goto errout;
    716     0    stevel 			}
    717     0    stevel 			reply_to_client(ap, KRB_RESPONSE, outbuf.data,
    718     0    stevel 					outbuf.length);
    719     0    stevel 		}
    720     0    stevel 		if (krb5_unparse_name(telnet_context,
    721     0    stevel 				    ticket->enc_part2->client,
    722     0    stevel 				    &name))
    723     0    stevel 			name = 0;
    724     0    stevel 		reply_to_client(ap, KRB_ACCEPT, name, name ? -1 : 0);
    725     0    stevel 		if (auth_debug) {
    726     0    stevel 			syslog(LOG_NOTICE,
    727     0    stevel 			    "\tKerberos5 identifies user as ``%s''\r\n",
    728     0    stevel 			    name ? name : "");
    729     0    stevel 		}
    730     0    stevel 		if (name != NULL) {
    731     0    stevel 			krb5_name = (char *)strdup(name);
    732     0    stevel 		}
    733     0    stevel 		auth_finished(ap, AUTH_USER);
    734     0    stevel 
    735     0    stevel 		if (name != NULL)
    736     0    stevel 			free(name);
    737     0    stevel 		krb5_auth_con_getremotesubkey(telnet_context, auth_context,
    738     0    stevel 					    &newkey);
    739     0    stevel 		if (session_key != NULL) {
    740     0    stevel 			krb5_free_keyblock(telnet_context, session_key);
    741     0    stevel 			session_key = 0;
    742     0    stevel 		}
    743     0    stevel 		if (newkey != NULL) {
    744     0    stevel 			krb5_copy_keyblock(telnet_context,
    745     0    stevel 					newkey, &session_key);
    746     0    stevel 			krb5_free_keyblock(telnet_context, newkey);
    747     0    stevel 		} else {
    748     0    stevel 			krb5_copy_keyblock(telnet_context,
    749     0    stevel 				ticket->enc_part2->session,
    750     0    stevel 				&session_key);
    751     0    stevel 		}
    752     0    stevel 
    753     0    stevel 		/*
    754     0    stevel 		 * Initialize encryption stuff.  Currently, we are only
    755     0    stevel 		 * supporting 8 byte keys and blocks. Check for this later.
    756     0    stevel 		 */
    757     0    stevel 		skey.type = SK_DES;
    758     0    stevel 		skey.length = DES_BLOCKSIZE;
    759     0    stevel 		skey.data = session_key->contents;
    760     0    stevel 		encrypt_session_key(&skey, &encr_data.encrypt);
    761     0    stevel 		encrypt_session_key(&skey, &encr_data.decrypt);
    762     0    stevel 		break;
    763     0    stevel 	case KRB_FORWARD:
    764     0    stevel 		inbuf.length = cnt;
    765     0    stevel 		inbuf.data = (char *)data;
    766     0    stevel 		if (auth_debug)
    767     0    stevel 			(void) fprintf(stderr,
    768     0    stevel 				    "RCVD KRB_FORWARD data (%d bytes)\n", cnt);
    769     0    stevel 
    770     0    stevel 		if (auth_context != NULL) {
    771     0    stevel 			krb5_rcache rcache;
    772     0    stevel 
    773     0    stevel 			err = krb5_auth_con_getrcache(telnet_context,
    774     0    stevel 						    auth_context, &rcache);
    775     0    stevel 			if (!err && !rcache) {
    776     0    stevel 				err = krb5_sname_to_principal(telnet_context,
    777     0    stevel 					0, 0, KRB5_NT_SRV_HST, &server);
    778     0    stevel 				if (!err) {
    779     0    stevel 					err = krb5_get_server_rcache(
    780     0    stevel 						telnet_context,
    781     0    stevel 						krb5_princ_component(
    782     0    stevel 							telnet_context,
    783     0    stevel 							server, 0),
    784     0    stevel 						&rcache);
    785     0    stevel 					krb5_free_principal(telnet_context,
    786     0    stevel 								server);
    787     0    stevel 				}
    788     0    stevel 			}
    789     0    stevel 			if (err) {
    790     0    stevel 				syslog(LOG_ERR,
    791     0    stevel 				    "Error allocating krb5 replay cache: %s",
    792     0    stevel 				    error_message(err));
    793     0    stevel 			} else {
    794     0    stevel 				err = krb5_auth_con_setrcache(telnet_context,
    795     0    stevel 					auth_context, rcache);
    796     0    stevel 				if (err)
    797     0    stevel 					syslog(LOG_ERR,
    798     0    stevel 					    "Error creating krb5 replay cache:"
    799     0    stevel 					    " %s",
    800     0    stevel 					    error_message(err));
    801     0    stevel 			}
    802     0    stevel 		}
    803     0    stevel 		/*
    804     0    stevel 		 * Use the 'rsaddr' and 'rsport' (remote service addr/port)
    805     0    stevel 		 * from the original connection.  This data is used to
    806     0    stevel 		 * verify the forwarded credentials.
    807     0    stevel 		 */
    808     0    stevel 		if (!(err = krb5_auth_con_setaddrs(telnet_context, auth_context,
    809     0    stevel 					    NULL, &rsaddr)))
    810     0    stevel 			err = krb5_auth_con_setports(telnet_context,
    811     0    stevel 						auth_context, NULL, &rsport);
    812     0    stevel 
    813     0    stevel 		if (err == 0)
    814     0    stevel 			/*
    815     0    stevel 			 * If all is well, store the forwarded creds in
    816     0    stevel 			 * the users local credential cache.
    817     0    stevel 			 */
    818     0    stevel 			err = rd_and_store_forwarded_creds(telnet_context,
    819     0    stevel 							auth_context, &inbuf,
    820     0    stevel 							ticket,
    821     0    stevel 							AuthenticatingUser);
    822     0    stevel 		if (err) {
    823     0    stevel 			(void) snprintf(errbuf, sizeof (errbuf),
    824     0    stevel 					"Read forwarded creds failed: %s",
    825     0    stevel 					error_message(err));
    826     0    stevel 			syslog(LOG_ERR, "%s", errbuf);
    827     0    stevel 
    828     0    stevel 			reply_to_client(ap, KRB_FORWARD_REJECT, errbuf, -1);
    829     0    stevel 			if (auth_debug)
    830     0    stevel 				(void) fprintf(stderr,
    831     0    stevel 					    "\tCould not read "
    832     0    stevel 					    "forwarded credentials\r\n");
    833     0    stevel 		} else
    834     0    stevel 			reply_to_client(ap, KRB_FORWARD_ACCEPT, (void *) 0, 0);
    835     0    stevel 
    836     0    stevel 		if (rsaddr.contents != NULL)
    837     0    stevel 			free(rsaddr.contents);
    838     0    stevel 
    839     0    stevel 		if (rsport.contents != NULL)
    840     0    stevel 			free(rsport.contents);
    841     0    stevel 
    842     0    stevel 		if (auth_debug)
    843     0    stevel 			(void) fprintf(stderr, "\tForwarded "
    844     0    stevel 						"credentials obtained\r\n");
    845     0    stevel 		break;
    846     0    stevel 	default:
    847     0    stevel 		if (auth_debug)
    848     0    stevel 			(void) fprintf(stderr,
    849     0    stevel 				    "\tUnknown Kerberos option %d\r\n",
    850     0    stevel 				    data[-1]);
    851     0    stevel 		reply_to_client(ap, KRB_REJECT, (void *) 0, 0);
    852     0    stevel 		break;
    853     0    stevel 	}
    854     0    stevel 	return;
    855     0    stevel 
    856     0    stevel errout:
    857     0    stevel 	reply_to_client(ap, KRB_REJECT, errbuf, -1);
    858     0    stevel 
    859     0    stevel 	if (auth_debug)
    860     0    stevel 		(void) fprintf(stderr, "\tKerberos V5 error: %s\r\n", errbuf);
    861     0    stevel 
    862     0    stevel 	syslog(LOG_ERR, "%s", errbuf);
    863     0    stevel 
    864     0    stevel 	if (auth_context != NULL) {
    865     0    stevel 		krb5_auth_con_free(telnet_context, auth_context);
    866     0    stevel 		auth_context = 0;
    867     0    stevel 	}
    868     0    stevel }
    869     0    stevel 
    870     0    stevel static int
    871     0    stevel krb5_init()
    872     0    stevel {
    873     0    stevel 	int code = 0;
    874     0    stevel 
    875     0    stevel 	if (telnet_context == NULL) {
    876     0    stevel 		code = krb5_init_context(&telnet_context);
    877     0    stevel 		if (code != 0 && auth_debug)
    878     0    stevel 			syslog(LOG_NOTICE,
    879     0    stevel 			    "Cannot initialize Kerberos V5: %s",
    880     0    stevel 			    error_message(code));
    881     0    stevel 	}
    882     0    stevel 
    883     0    stevel 	return (code);
    884     0    stevel }
    885     0    stevel 
    886     0    stevel static void
    887     0    stevel auth_name(uchar_t *data, int cnt)
    888     0    stevel {
    889     0    stevel 	char namebuf[MAXPRINCLEN];
    890     0    stevel 
    891     0    stevel 	if (cnt < 1) {
    892     0    stevel 		if (auth_debug)
    893     0    stevel 			(void) fprintf(stderr,
    894     0    stevel 				    "\t(auth_name) Empty NAME in auth "
    895     0    stevel 				    "reply\n");
    896     0    stevel 		return;
    897     0    stevel 	}
    898     0    stevel 	if (cnt > sizeof (namebuf)-1) {
    899     0    stevel 		if (auth_debug)
    900     0    stevel 			(void) fprintf(stderr,
    901     0    stevel 				    "\t(auth_name) NAME exceeds %d bytes\n",
    902     0    stevel 				sizeof (namebuf)-1);
    903     0    stevel 		return;
    904     0    stevel 	}
    905     0    stevel 	(void) memcpy((void *)namebuf, (void *)data, cnt);
    906     0    stevel 	namebuf[cnt] = 0;
    907     0    stevel 	if (auth_debug)
    908     0    stevel 		(void) fprintf(stderr, "\t(auth_name) name [%s]\n", namebuf);
    909     0    stevel 	AuthenticatingUser = (char *)strdup(namebuf);
    910     0    stevel }
    911     0    stevel 
    912     0    stevel static void
    913     0    stevel auth_is(uchar_t *data, int cnt)
    914     0    stevel {
    915     0    stevel 	AuthInfo *aptr = auth_list;
    916     0    stevel 
    917     0    stevel 	if (cnt < 2)
    918     0    stevel 		return;
    919     0    stevel 
    920     0    stevel 	/*
    921     0    stevel 	 * We failed to negoiate secure authentication
    922     0    stevel 	 */
    923     0    stevel 	if (data[0] == AUTHTYPE_NULL) {
    924     0    stevel 		auth_finished(0, AUTH_REJECT);
    925     0    stevel 		return;
    926     0    stevel 	}
    927     0    stevel 
    928     0    stevel 	while (aptr->AuthName != NULL &&
    929     0    stevel 	    (aptr->AuthName != data[0] || aptr->AuthHow != data[1]))
    930     0    stevel 		aptr++;
    931     0    stevel 
    932     0    stevel 	if (aptr != NULL) {
    933     0    stevel 		if (auth_debug)
    934     0    stevel 			(void) fprintf(stderr, "\t(auth_is) auth type is %s "
    935     0    stevel 				"(%d bytes)\n",	aptr->AuthString, cnt);
    936     0    stevel 
    937     0    stevel 		if (aptr->AuthName == AUTHTYPE_KERBEROS_V5)
    938     0    stevel 			kerberos5_is(aptr, data+2, cnt-2);
    939     0    stevel 	}
    940     0    stevel }
    941     0    stevel 
    942     0    stevel static int
    943     0    stevel krb5_user_status(char *name, int namelen, int level)
    944     0    stevel {
    945     0    stevel 	int retval = AUTH_USER;
    946     0    stevel 
    947     0    stevel 	if (auth_debug)
    948     0    stevel 		(void) fprintf(stderr, "\t(krb5_user_status) level = %d "
    949     0    stevel 			"auth_level = %d  user = %s\n",
    950     0    stevel 			level, auth_level,
    951     0    stevel 			(AuthenticatingUser != NULL ? AuthenticatingUser : ""));
    952     0    stevel 
    953     0    stevel 	if (level < AUTH_USER)
    954     0    stevel 		return (level);
    955     0    stevel 
    956     0    stevel 	if (AuthenticatingUser != NULL &&
    957     0    stevel 	    (retval = krb5_kuserok(telnet_context, ticket->enc_part2->client,
    958     0    stevel 			    AuthenticatingUser))) {
    959     0    stevel 		(void) strncpy(name, AuthenticatingUser, namelen);
    960     0    stevel 		return (AUTH_VALID);
    961     0    stevel 	} else {
    962     0    stevel 		if (!retval)
    963     0    stevel 			syslog(LOG_ERR,
    964     0    stevel 			    "Krb5 principal lacks permission to "
    965     0    stevel 			    "access local account for %s",
    966     0    stevel 			    AuthenticatingUser);
    967     0    stevel 		return (AUTH_USER);
    968     0    stevel 	}
    969     0    stevel }
    970     0    stevel 
    971     0    stevel /*
    972     0    stevel  * Wrapper around /dev/urandom
    973     0    stevel  */
    974     0    stevel static int
    975     0    stevel getrandom(char *buf, int buflen)
    976     0    stevel {
    977     0    stevel 	static int devrandom = -1;
    978     0    stevel 
    979     0    stevel 	if (devrandom == -1 &&
    980     0    stevel 	    (devrandom = open("/dev/urandom", O_RDONLY)) == -1) {
    981     0    stevel 		fatalperror(net, "Unable to open /dev/urandom: ",
    982     0    stevel 			    errno);
    983     0    stevel 		return (-1);
    984     0    stevel 	}
    985     0    stevel 
    986     0    stevel 	if (read(devrandom, buf, buflen) == -1) {
    987     0    stevel 		fatalperror(net, "Unable to read from /dev/urandom: ",
    988     0    stevel 			    errno);
    989     0    stevel 		return (-1);
    990     0    stevel 	}
    991     0    stevel 
    992     0    stevel 	return (0);
    993     0    stevel }
    994     0    stevel 
    995     0    stevel /*
    996     0    stevel  * encrypt_init
    997     0    stevel  *
    998     0    stevel  * Initialize the encryption data structures
    999     0    stevel  */
   1000     0    stevel static void
   1001     0    stevel encrypt_init()
   1002     0    stevel {
   1003     0    stevel 	(void) memset(&encr_data.encrypt, 0, sizeof (cipher_info_t));
   1004     0    stevel 	(void) memset(&encr_data.decrypt, 0, sizeof (cipher_info_t));
   1005     0    stevel 
   1006     0    stevel 	encr_data.encrypt.state = ENCR_STATE_NOT_READY;
   1007     0    stevel 	encr_data.decrypt.state = ENCR_STATE_NOT_READY;
   1008     0    stevel }
   1009     0    stevel 
   1010     0    stevel /*
   1011     0    stevel  * encrypt_send_request_start
   1012     0    stevel  *
   1013     0    stevel  * Request that the remote side automatically start sending
   1014     0    stevel  * encrypted output
   1015     0    stevel  */
   1016     0    stevel static void
   1017     0    stevel encrypt_send_request_start()
   1018     0    stevel {
   1019     0    stevel 	uchar_t buf[6+TELNET_MAXKEYIDLEN], *p;
   1020     0    stevel 
   1021     0    stevel 	p = buf;
   1022     0    stevel 
   1023     0    stevel 	*p++ = IAC;
   1024     0    stevel 	*p++ = SB;
   1025     0    stevel 	*p++ = TELOPT_ENCRYPT;
   1026     0    stevel 	*p++ = ENCRYPT_REQSTART;
   1027     0    stevel 	/*
   1028     0    stevel 	 * We are telling the remote side which
   1029     0    stevel 	 * decrypt key we will use so that it may
   1030     0    stevel 	 * encrypt in the same key.
   1031     0    stevel 	 */
   1032     0    stevel 	(void) memcpy(p, encr_data.decrypt.keyid, encr_data.decrypt.keyidlen);
   1033     0    stevel 	p += encr_data.decrypt.keyidlen;
   1034     0    stevel 
   1035     0    stevel 	*p++ = IAC;
   1036     0    stevel 	*p++ = SE;
   1037     0    stevel 
   1038     0    stevel 	write_data_len((const char *)buf, p-buf);
   1039     0    stevel 	netflush();
   1040     0    stevel 	if (enc_debug)
   1041     0    stevel 		(void) fprintf(stderr,
   1042     0    stevel 			    "SENT TELOPT_ENCRYPT ENCRYPT_REQSTART\n");
   1043     0    stevel }
   1044     0    stevel 
   1045     0    stevel /*
   1046     0    stevel  * encrypt_is
   1047     0    stevel  *
   1048     0    stevel  * When we receive the TELOPT_ENCRYPT ENCRYPT_IS ...
   1049     0    stevel  * message, the client is telling us that it will be sending
   1050     0    stevel  * encrypted data using the indicated cipher.
   1051     0    stevel  * We must initialize the read (decrypt) side of our connection
   1052     0    stevel  */
   1053     0    stevel static void
   1054     0    stevel encrypt_is(uchar_t *data, int cnt)
   1055     0    stevel {
   1056     0    stevel 	register int type;
   1057     0    stevel 	register int iv_status = CFB64_IV_OK;
   1058     0    stevel 	register int lstate = 0;
   1059     0    stevel 
   1060     0    stevel 	uchar_t sbbuf[] = {
   1061     0    stevel 		(uchar_t)IAC,
   1062     0    stevel 		(uchar_t)SB,
   1063     0    stevel 		(uchar_t)TELOPT_ENCRYPT,
   1064     0    stevel 		(uchar_t)ENCRYPT_REPLY,
   1065     0    stevel 		(uchar_t)0,		/* placeholder:  sbbuf[4] */
   1066     0    stevel 		(uchar_t)CFB64_IV_OK,	/* placeholder:  sbbuf[5] */
   1067     0    stevel 		(uchar_t)IAC,
   1068     0    stevel 		(uchar_t)SE,
   1069     0    stevel 	};
   1070     0    stevel 
   1071     0    stevel 	if (--cnt < 0)
   1072     0    stevel 		return;
   1073     0    stevel 
   1074     0    stevel 	type = sbbuf[4] = *data++;
   1075     0    stevel 
   1076     0    stevel 	/*
   1077     0    stevel 	 * Steps to take:
   1078     0    stevel 	 *   1. Create the proper stream Initialization vector
   1079     0    stevel 	 *		- copy the correct 'seed' to IV and output blocks
   1080     0    stevel 	 *		- set the correct key schedule
   1081     0    stevel 	 *   2. Generate reply for the other side:
   1082     0    stevel 	 *		IAC SB TELOPT_ENCRYPT ENCRYPT_REPLY type CFB64_IV_OK
   1083     0    stevel 	 *		[ data ... ] IAC SE
   1084     0    stevel 	 *   3. Tell crypto module:  method, direction, IV
   1085     0    stevel 	 */
   1086     0    stevel 	switch (type) {
   1087     0    stevel 	case TELOPT_ENCTYPE_DES_CFB64:
   1088     0    stevel 		encr_data.decrypt.type = type;
   1089     0    stevel 
   1090     0    stevel 		lstate = encr_data.decrypt.state;
   1091     0    stevel 		if (enc_debug)
   1092     0    stevel 			(void) fprintf(stderr,
   1093     0    stevel 				    "\t(encrypt_is) initial state = %d\n",
   1094     0    stevel 				    lstate);
   1095     0    stevel 		/*
   1096     0    stevel 		 * Before we extract the IV bytes, make sure we got
   1097     0    stevel 		 * enough data.
   1098     0    stevel 		 */
   1099     0    stevel 		if (cnt < sizeof (Block)) {
   1100     0    stevel 			iv_status = CFB64_IV_BAD;
   1101     0    stevel 			if (enc_debug)
   1102     0    stevel 				(void) fprintf(stderr,
   1103     0    stevel 					    "\t(encrypt_is) Not enough "
   1104     0    stevel 					    "IV bytes\n");
   1105     0    stevel 			lstate = ENCR_STATE_NOT_READY;
   1106     0    stevel 		} else {
   1107     0    stevel 			data++; /* skip over the CFB64_IV byte */
   1108     0    stevel 			(void) memcpy(encr_data.decrypt.ivec, data,
   1109     0    stevel 				    sizeof (Block));
   1110     0    stevel 			lstate = ENCR_STATE_IN_PROGRESS;
   1111     0    stevel 		}
   1112     0    stevel 		break;
   1113     0    stevel 	case TELOPT_ENCTYPE_NULL:
   1114     0    stevel 		encr_data.decrypt.type = type;
   1115     0    stevel 		lstate &= ~ENCR_STATE_NO_RECV_IV;
   1116     0    stevel 		lstate &= ~ENCR_STATE_NO_SEND_IV;
   1117     0    stevel 		if (enc_debug)
   1118     0    stevel 			(void) fprintf(stderr,
   1119     0    stevel 				"\t(encrypt_is) We accept NULL encr\n");
   1120     0    stevel 		break;
   1121     0    stevel 	default:
   1122     0    stevel 		iv_status = CFB64_IV_BAD;
   1123     0    stevel 		encr_data.decrypt.type = NULL;
   1124     0    stevel 		if (enc_debug)
   1125     0    stevel 			(void) fprintf(stderr,
   1126     0    stevel 				    "\t(encrypt_is) Can't find type (%d) "
   1127     0    stevel 				    "for initial negotiation\r\n",
   1128     0    stevel 				    type);
   1129     0    stevel 		lstate = ENCR_STATE_NOT_READY;
   1130     0    stevel 		break;
   1131     0    stevel 	}
   1132     0    stevel 
   1133     0    stevel 	sbbuf[5] = (uchar_t)iv_status; /* either CFB64_IV_OK or BAD */
   1134     0    stevel 
   1135     0    stevel 	if (iv_status == CFB64_IV_OK) {
   1136     0    stevel 		/*
   1137     0    stevel 		 * send IV to crypto module and indicate it is for
   1138     0    stevel 		 * decrypt only
   1139     0    stevel 		 */
   1140     0    stevel 		lstate &= ~ENCR_STATE_NO_RECV_IV;  /* we received an OK IV */
   1141     0    stevel 		lstate &= ~ENCR_STATE_NO_SEND_IV;  /* we dont send an IV */
   1142     0    stevel 	} else {
   1143     0    stevel 		/* tell crypto module to disable crypto on "read" stream */
   1144     0    stevel 		lstate = ENCR_STATE_NOT_READY;
   1145     0    stevel 	}
   1146     0    stevel 
   1147     0    stevel 	write_data_len((const char *)sbbuf, sizeof (sbbuf));
   1148     0    stevel 	netflush();
   1149     0    stevel #ifdef ENCRYPT_NAMES
   1150     0    stevel 	if (enc_debug)
   1151     0    stevel 		(void) fprintf(stderr,
   1152     0    stevel 			    "SENT TELOPT_ENCRYPT ENCRYPT_REPLY %s %s\n",
   1153     0    stevel 			    ENCTYPE_NAME(type),
   1154     0    stevel 			    (iv_status == CFB64_IV_OK ? "CFB64_IV_OK" :
   1155     0    stevel 			    "CFB64_IV_BAD"));
   1156     0    stevel #endif /* ENCRYPT_NAMES */
   1157     0    stevel 	/* Update the state of the decryption negotiation */
   1158     0    stevel 	encr_data.decrypt.state = lstate;
   1159     0    stevel 
   1160     0    stevel 	if (lstate == ENCR_STATE_NOT_READY)
   1161     0    stevel 		encr_data.decrypt.autoflag = 0;
   1162     0    stevel 	else {
   1163     0    stevel 		if (lstate == ENCR_STATE_OK && encr_data.decrypt.autoflag)
   1164     0    stevel 			encrypt_send_request_start();
   1165     0    stevel 	}
   1166     0    stevel 	if (enc_debug)
   1167     0    stevel 		(void) fprintf(stderr,
   1168     0    stevel 			    "\t(encrypt_is) final DECRYPT state = %d\n",
   1169     0    stevel 			    encr_data.decrypt.state);
   1170     0    stevel }
   1171     0    stevel 
   1172     0    stevel /*
   1173     0    stevel  * encrypt_send_encrypt_is
   1174     0    stevel  *
   1175     0    stevel  * Tell the client what encryption we will use
   1176     0    stevel  * and what our IV will be.
   1177     0    stevel  */
   1178     0    stevel static int
   1179     0    stevel encrypt_send_encrypt_is()
   1180     0    stevel {
   1181     0    stevel 	register int lstate;
   1182     0    stevel 	krb5_error_code kret;
   1183     0    stevel 	uchar_t sbbuf[MAXOPTLEN], *p;
   1184     0    stevel 	int i;
   1185     0    stevel 
   1186     0    stevel 	lstate = encr_data.encrypt.state;
   1187     0    stevel 
   1188     0    stevel 	if (encr_data.encrypt.type == ENCTYPE_NULL) {
   1189     0    stevel 		/*
   1190     0    stevel 		 * Haven't received ENCRYPT SUPPORT yet or we couldn't agree
   1191     0    stevel 		 * on a cipher.
   1192     0    stevel 		 */
   1193     0    stevel 		return (lstate);
   1194     0    stevel 	}
   1195     0    stevel 
   1196     0    stevel 	/*
   1197     0    stevel 	 * - Create a random DES key
   1198     0    stevel 	 *
   1199     0    stevel 	 * - DES ECB encrypt
   1200     0    stevel 	 *   encrypt the IV using itself as the key.
   1201     0    stevel 	 *
   1202     0    stevel 	 * - Send response
   1203     0    stevel 	 *   IAC SB TELOPT_ENCRYPT ENCRYPT_IS CFB64 FB64_IV [ feed block ]
   1204     0    stevel 	 *   IAC SE
   1205     0    stevel 	 *
   1206     0    stevel 	 */
   1207     0    stevel 	if (lstate == ENCR_STATE_NOT_READY)
   1208     0    stevel 		lstate = ENCR_STATE_IN_PROGRESS;
   1209     0    stevel 	else if ((lstate & ENCR_STATE_NO_SEND_IV) == 0) {
   1210     0    stevel 		if (enc_debug)
   1211     0    stevel 			(void) fprintf(stderr,
   1212     0    stevel 				"\t(encrypt_send_is) IV already sent,"
   1213     0    stevel 				" state = %d\n", lstate);
   1214     0    stevel 		return (lstate);
   1215     0    stevel 	}
   1216     0    stevel 
   1217     0    stevel 	if (!VALIDKEY(encr_data.encrypt.krbdes_key)) {
   1218     0    stevel 		/*
   1219     0    stevel 		 * Invalid key, set flag so we try again later
   1220     0    stevel 		 * when we get a good one
   1221     0    stevel 		 */
   1222     0    stevel 		encr_data.encrypt.need_start = 1;
   1223     0    stevel 		if (enc_debug)
   1224     0    stevel 			(void) fprintf(stderr,
   1225     0    stevel 				"\t(encrypt_send_is) No Key, cannot "
   1226     0    stevel 				"start encryption yet\n");
   1227     0    stevel 		return (lstate);
   1228     0    stevel 	}
   1229     0    stevel 	if (enc_debug)
   1230     0    stevel 		(void) fprintf(stderr,
   1231     0    stevel 			    "\t(encrypt_send_is) Creating new feed\n");
   1232     0    stevel 
   1233     0    stevel 	/*
   1234     0    stevel 	 * Create a random feed and send it over.
   1235     0    stevel 	 *
   1236     0    stevel 	 * Use the /dev/[u]random interface to generate
   1237     0    stevel 	 * our encryption IV.
   1238     0    stevel 	 */
   1239     0    stevel 	kret = getrandom((char *)encr_data.encrypt.ivec, sizeof (Block));
   1240     0    stevel 
   1241     0    stevel 	if (kret) {
   1242     0    stevel 		if (enc_debug)
   1243     0    stevel 			(void) fprintf(stderr,
   1244     0    stevel 				    "\t(encrypt_send_is) error from "
   1245     0    stevel 				    "getrandom: %d\n", kret);
   1246     0    stevel 		syslog(LOG_ERR, "Failed to create encryption key (err %d)\n");
   1247     0    stevel 		encr_data.encrypt.type = ENCTYPE_NULL;
   1248     0    stevel 	} else {
   1249     0    stevel 		mit_des_fixup_key_parity(encr_data.encrypt.ivec);
   1250     0    stevel 	}
   1251     0    stevel 
   1252     0    stevel 	p = sbbuf;
   1253     0    stevel 	*p++ = IAC;
   1254     0    stevel 	*p++ = SB;
   1255     0    stevel 	*p++ = TELOPT_ENCRYPT;
   1256     0    stevel 	*p++ = ENCRYPT_IS;
   1257     0    stevel 	*p++ = encr_data.encrypt.type;
   1258     0    stevel 	*p++ = CFB64_IV;
   1259     0    stevel 
   1260     0    stevel 	/*
   1261     0    stevel 	 * Copy the IV bytes individually so that when a
   1262     0    stevel 	 * 255 (telnet IAC) is used, it can be "escaped" by
   1263     0    stevel 	 * adding it twice (telnet RFC 854).
   1264     0    stevel 	 */
   1265     0    stevel 	for (i = 0; i < sizeof (Block); i++)
   1266     0    stevel 		if ((*p++ = encr_data.encrypt.ivec[i]) == IAC)
   1267     0    stevel 			*p++ = IAC;
   1268     0    stevel 
   1269     0    stevel 	*p++ = IAC;
   1270     0    stevel 	*p++ = SE;
   1271     0    stevel 	write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
   1272     0    stevel 	netflush();
   1273     0    stevel 
   1274     0    stevel 	if (!kret) {
   1275     0    stevel 		lstate &= ~ENCR_STATE_NO_SEND_IV; /* we sent our IV */
   1276     0    stevel 		lstate &= ~ENCR_STATE_NO_SEND_IV; /* dont need decrypt IV */
   1277     0    stevel 	}
   1278     0    stevel 	encr_data.encrypt.state = lstate;
   1279     0    stevel 
   1280     0    stevel 	if (enc_debug) {
   1281     0    stevel 		int i;
   1282     0    stevel 		(void) fprintf(stderr,
   1283     0    stevel 			    "SENT TELOPT_ENCRYPT ENCRYPT_IS %d CFB64_IV ",
   1284     0    stevel 			    encr_data.encrypt.type);
   1285     0    stevel 		for (i = 0; i < (p-sbbuf); i++)
   1286     0    stevel 			(void) fprintf(stderr, "%d ", (int)sbbuf[i]);
   1287     0    stevel 		(void) fprintf(stderr, "\n");
   1288     0    stevel 	}
   1289     0    stevel 
   1290     0    stevel 	return (lstate);
   1291     0    stevel }
   1292     0    stevel 
   1293     0    stevel /*
   1294     0    stevel  * stop_stream
   1295     0    stevel  *
   1296     0    stevel  * Utility routine to send a CRIOCSTOP ioctl to the
   1297     0    stevel  * crypto module (cryptmod).
   1298     0    stevel  */
   1299     0    stevel static void
   1300     0    stevel stop_stream(int fd, int dir)
   1301     0    stevel {
   1302     0    stevel 	struct strioctl  crioc;
   1303     0    stevel 	uint32_t stopdir = dir;
   1304     0    stevel 
   1305     0    stevel 	crioc.ic_cmd = CRYPTIOCSTOP;
   1306     0    stevel 	crioc.ic_timout = -1;
   1307     0    stevel 	crioc.ic_len = sizeof (stopdir);
   1308     0    stevel 	crioc.ic_dp = (char *)&stopdir;
   1309     0    stevel 
   1310     0    stevel 	if (ioctl(fd, I_STR, &crioc)) {
   1311     0    stevel 		syslog(LOG_ERR, "Error sending CRYPTIOCSTOP ioctl: %m");
   1312     0    stevel 	}
   1313     0    stevel }
   1314     0    stevel 
   1315     0    stevel /*
   1316     0    stevel  * start_stream
   1317     0    stevel  *
   1318     0    stevel  * Utility routine to send a CRYPTIOCSTART ioctl to the
   1319     0    stevel  * crypto module (cryptmod).  This routine may contain optional
   1320     0    stevel  * payload data that the cryptmod will interpret as bytes that
   1321     0    stevel  * need to be decrypted and sent back up to the application
   1322     0    stevel  * via the data stream.
   1323     0    stevel  */
   1324     0    stevel static void
   1325     0    stevel start_stream(int fd, int dir, int datalen, char *data)
   1326     0    stevel {
   1327     0    stevel 	struct strioctl crioc;
   1328     0    stevel 
   1329     0    stevel 	crioc.ic_cmd = (dir == CRYPT_ENCRYPT ? CRYPTIOCSTARTENC :
   1330     0    stevel 			CRYPTIOCSTARTDEC);
   1331     0    stevel 	crioc.ic_timout = -1;
   1332     0    stevel 	crioc.ic_len = datalen;
   1333     0    stevel 	crioc.ic_dp = data;
   1334     0    stevel 
   1335     0    stevel 	if (ioctl(fd, I_STR, &crioc)) {
   1336     0    stevel 		syslog(LOG_ERR, "Error sending CRYPTIOCSTART ioctl: %m");
   1337     0    stevel 	}
   1338     0    stevel }
   1339     0    stevel 
   1340     0    stevel /*
   1341     0    stevel  * encrypt_start_output
   1342     0    stevel  *
   1343     0    stevel  * Tell the other side to start encrypting its data
   1344     0    stevel  */
   1345     0    stevel static void
   1346     0    stevel encrypt_start_output()
   1347     0    stevel {
   1348     0    stevel 	int lstate;
   1349     0    stevel 	uchar_t *p;
   1350     0    stevel 	uchar_t sbbuf[MAXOPTLEN];
   1351     0    stevel 	struct strioctl crioc;
   1352     0    stevel 	struct cr_info_t cki;
   1353     0    stevel 
   1354     0    stevel 	/*
   1355     0    stevel 	 * Initialize crypto and send the ENCRYPT_IS msg
   1356     0    stevel 	 */
   1357     0    stevel 	lstate = encrypt_send_encrypt_is();
   1358     0    stevel 
   1359     0    stevel 	if (lstate != ENCR_STATE_OK) {
   1360     0    stevel 		if (enc_debug)
   1361     0    stevel 			(void) fprintf(stderr,
   1362     0    stevel 				"\t(encrypt_start_output) ENCRYPT state "
   1363     0    stevel 				"= %d\n", lstate);
   1364     0    stevel 		return;
   1365     0    stevel 	}
   1366     0    stevel 
   1367     0    stevel 	p = sbbuf;
   1368     0    stevel 
   1369     0    stevel 	*p++ = IAC;
   1370     0    stevel 	*p++ = SB;
   1371     0    stevel 	*p++ = TELOPT_ENCRYPT;
   1372     0    stevel 	*p++ = ENCRYPT_START;
   1373     0    stevel 
   1374     0    stevel 	(void) memcpy(p, encr_data.encrypt.keyid, encr_data.encrypt.keyidlen);
   1375     0    stevel 	p += encr_data.encrypt.keyidlen;
   1376     0    stevel 
   1377     0    stevel 	*p++ = IAC;
   1378     0    stevel 	*p++ = SE;
   1379     0    stevel 
   1380     0    stevel 	/* Flush this data out before we start encrypting */
   1381     0    stevel 	write_data_len((const char *)sbbuf, (int)(p-sbbuf));
   1382     0    stevel 	netflush();
   1383     0    stevel 
   1384     0    stevel 	if (enc_debug)
   1385     0    stevel 		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_START %d "
   1386     0    stevel 			"(lstate = %d) data waiting = %d\n",
   1387     0    stevel 			(int)encr_data.encrypt.keyid[0],
   1388     0    stevel 			lstate, nfrontp-nbackp);
   1389     0    stevel 
   1390     0    stevel 	encr_data.encrypt.state = lstate;
   1391     0    stevel 
   1392     0    stevel 	/*
   1393     0    stevel 	 * tell crypto module what key to use for encrypting
   1394     0    stevel 	 * Note that the ENCRYPT has not yet been enabled, but we
   1395     0    stevel 	 * need to first set the crypto key to use.
   1396     0    stevel 	 */
   1397     0    stevel 	cki.direction_mask = CRYPT_ENCRYPT;
   1398     0    stevel 
   1399     0    stevel 	if (encr_data.encrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
   1400     0    stevel 		cki.crypto_method = CRYPT_METHOD_DES_CFB;
   1401     0    stevel 	} else {
   1402     0    stevel 		if (enc_debug)
   1403     0    stevel 			(void) fprintf(stderr,
   1404     0    stevel 				"\t(encrypt_start_output) - unknown "
   1405     0    stevel 				"crypto_method %d\n",
   1406     0    stevel 				encr_data.encrypt.type);
   1407     0    stevel 		syslog(LOG_ERR, "unrecognized crypto encrypt method: %d",
   1408     0    stevel 				encr_data.encrypt.type);
   1409     0    stevel 
   1410     0    stevel 		return;
   1411     0    stevel 	}
   1412     0    stevel 
   1413     0    stevel 	/*
   1414     0    stevel 	 * If we previously configured this crypto method, we dont want to
   1415     0    stevel 	 * overwrite the key or ivec information already given to the crypto
   1416     0    stevel 	 * module as it will cause the cipher data between the client and server
   1417     0    stevel 	 * to become out of synch and impossible to decipher.
   1418     0    stevel 	 */
   1419     0    stevel 	if (encr_data.encrypt.setup == cki.crypto_method) {
   1420     0    stevel 		cki.keylen = 0;
   1421     0    stevel 		cki.iveclen = 0;
   1422     0    stevel 	} else {
   1423     0    stevel 		cki.keylen = DES_BLOCKSIZE;
   1424     0    stevel 		(void) memcpy(cki.key, (void *)encr_data.encrypt.krbdes_key,
   1425     0    stevel 		    DES_BLOCKSIZE);
   1426     0    stevel 
   1427     0    stevel 		cki.iveclen = DES_BLOCKSIZE;
   1428     0    stevel 		(void) memcpy(cki.ivec, (void *)encr_data.encrypt.ivec,
   1429     0    stevel 		    DES_BLOCKSIZE);
   1430     0    stevel 
   1431     0    stevel 		cki.ivec_usage = IVEC_ONETIME;
   1432     0    stevel 	}
   1433     0    stevel 
   1434     0    stevel 	cki.option_mask = 0;
   1435     0    stevel 
   1436     0    stevel 	/* Stop encrypt side prior to setup so we dont lose data */
   1437     0    stevel 	stop_stream(cryptmod_fd, CRYPT_ENCRYPT);
   1438     0    stevel 
   1439     0    stevel 	crioc.ic_cmd = CRYPTIOCSETUP;
   1440     0    stevel 	crioc.ic_timout = -1;
   1441     0    stevel 	crioc.ic_len = sizeof (struct cr_info_t);
   1442     0    stevel 	crioc.ic_dp = (char *)&cki;
   1443     0    stevel 
   1444     0    stevel 	if (ioctl(cryptmod_fd, I_STR, &crioc)) {
   1445     0    stevel 		perror("ioctl(CRYPTIOCSETUP) [encrypt_start_output] error");
   1446     0    stevel 	} else {
   1447     0    stevel 		/* Setup completed OK */
   1448     0    stevel 		encr_data.encrypt.setup = cki.crypto_method;
   1449     0    stevel 	}
   1450     0    stevel 
   1451     0    stevel 	/*
   1452     0    stevel 	 * We do not check for "stuck" data when setting up the
   1453     0    stevel 	 * outbound "encrypt" channel.  Any data queued prior to
   1454     0    stevel 	 * this IOCTL will get processed correctly without our help.
   1455     0    stevel 	 */
   1456     0    stevel 	start_stream(cryptmod_fd, CRYPT_ENCRYPT, 0, NULL);
   1457     0    stevel 
   1458     0    stevel 	/*
   1459     0    stevel 	 * tell crypto module to start encrypting
   1460     0    stevel 	 */
   1461     0    stevel 	if (enc_debug)
   1462     0    stevel 		(void) fprintf(stderr,
   1463     0    stevel 			"\t(encrypt_start_output) Encrypting output\n");
   1464     0    stevel }
   1465     0    stevel 
   1466     0    stevel /*
   1467     0    stevel  * encrypt_request_start
   1468     0    stevel  *
   1469     0    stevel  * The client requests that we start encryption immediately after
   1470     0    stevel  * successful negotiation
   1471     0    stevel  */
   1472     0    stevel static void
   1473     0    stevel encrypt_request_start(void)
   1474     0    stevel {
   1475     0    stevel 	if (encr_data.encrypt.type == ENCTYPE_NULL) {
   1476     0    stevel 		encr_data.encrypt.autoflag = 1;
   1477     0    stevel 		if (enc_debug)
   1478     0    stevel 			(void) fprintf(stderr, "\t(encrypt_request_start) "
   1479     0    stevel 				"autoencrypt = ON\n");
   1480     0    stevel 	} else {
   1481     0    stevel 		encrypt_start_output();
   1482     0    stevel 	}
   1483     0    stevel }
   1484     0    stevel 
   1485     0    stevel /*
   1486     0    stevel  * encrypt_end
   1487     0    stevel  *
   1488     0    stevel  * ENCRYPT END received, stop decrypting the read stream
   1489     0    stevel  */
   1490     0    stevel static void
   1491     0    stevel encrypt_end(int direction)
   1492     0    stevel {
   1493     0    stevel 	struct cr_info_t cki;
   1494     0    stevel 	struct strioctl  crioc;
   1495     0    stevel 	uint32_t stopdir;
   1496     0    stevel 
   1497     0    stevel 	stopdir = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
   1498     0    stevel 		CRYPT_ENCRYPT);
   1499     0    stevel 
   1500     0    stevel 	stop_stream(cryptmod_fd, stopdir);
   1501     0    stevel 
   1502     0    stevel 	/*
   1503     0    stevel 	 * Call this function when we wish to disable crypto in
   1504     0    stevel 	 * either direction (ENCRYPT or DECRYPT)
   1505     0    stevel 	 */
   1506     0    stevel 	cki.direction_mask = (direction == TELNET_DIR_DECRYPT ? CRYPT_DECRYPT :
   1507     0    stevel 			    CRYPT_ENCRYPT);
   1508     0    stevel 	cki.crypto_method = CRYPT_METHOD_NONE;
   1509     0    stevel 	cki.option_mask = 0;
   1510     0    stevel 
   1511     0    stevel 	cki.keylen = 0;
   1512     0    stevel 	cki.iveclen = 0;
   1513    93  ethindra 	cki.ivec_usage = IVEC_ONETIME;
   1514     0    stevel 
   1515     0    stevel 	crioc.ic_cmd = CRYPTIOCSETUP;
   1516     0    stevel 	crioc.ic_timout = -1;
   1517     0    stevel 	crioc.ic_len = sizeof (cki);
   1518     0    stevel 	crioc.ic_dp = (char *)&cki;
   1519     0    stevel 
   1520     0    stevel 	if (ioctl(cryptmod_fd, I_STR, &crioc)) {
   1521     0    stevel 		perror("ioctl(CRYPTIOCSETUP) [encrypt_end] error");
   1522     0    stevel 	}
   1523     0    stevel 
   1524     0    stevel 	start_stream(cryptmod_fd, stopdir, 0, NULL);
   1525     0    stevel }
   1526     0    stevel 
   1527     0    stevel /*
   1528     0    stevel  * encrypt_request_end
   1529     0    stevel  *
   1530     0    stevel  * When we receive a REQEND from the client, it means
   1531     0    stevel  * that we are supposed to stop encrypting
   1532     0    stevel  */
   1533     0    stevel static void
   1534     0    stevel encrypt_request_end()
   1535     0    stevel {
   1536     0    stevel 	/*
   1537     0    stevel 	 * Tell the other side we are done encrypting
   1538     0    stevel 	 */
   1539     0    stevel 
   1540     0    stevel 	write_data("%c%c%c%c%c%c",
   1541     0    stevel 		(uchar_t)IAC,
   1542     0    stevel 		(uchar_t)SB,
   1543     0    stevel 		(uchar_t)TELOPT_ENCRYPT,
   1544     0    stevel 		(uchar_t)ENCRYPT_END,
   1545     0    stevel 		(uchar_t)IAC,
   1546     0    stevel 		(uchar_t)SE);
   1547     0    stevel 	netflush();
   1548     0    stevel 	if (enc_debug)
   1549     0    stevel 		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_END\n");
   1550     0    stevel 
   1551     0    stevel 	/*
   1552     0    stevel 	 * Turn off encryption of the write stream
   1553     0    stevel 	 */
   1554     0    stevel 	encrypt_end(TELNET_DIR_ENCRYPT);
   1555     0    stevel }
   1556     0    stevel 
   1557     0    stevel /*
   1558     0    stevel  * encrypt_send_request_end
   1559     0    stevel  *
   1560     0    stevel  * We stop encrypting the write stream and tell the other side about it.
   1561     0    stevel  */
   1562     0    stevel static void
   1563     0    stevel encrypt_send_request_end()
   1564     0    stevel {
   1565     0    stevel 	write_data("%c%c%c%c%c%c",
   1566     0    stevel 		(uchar_t)IAC,
   1567     0    stevel 		(uchar_t)SB,
   1568     0    stevel 		(uchar_t)TELOPT_ENCRYPT,
   1569     0    stevel 		(uchar_t)ENCRYPT_REQEND,
   1570     0    stevel 		(uchar_t)IAC,
   1571     0    stevel 		(uchar_t)SE);
   1572     0    stevel 	netflush();
   1573     0    stevel 	if (enc_debug)
   1574     0    stevel 		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT ENCRYPT_REQEND\n");
   1575     0    stevel }
   1576     0    stevel 
   1577     0    stevel /*
   1578     0    stevel  * encrypt_start
   1579     0    stevel  *
   1580     0    stevel  * The client is going to start sending encrypted data
   1581     0    stevel  * using the previously negotiated cipher (see what we set
   1582     0    stevel  * when we did the REPLY in encrypt_is).
   1583     0    stevel  */
   1584     0    stevel static void
   1585     0    stevel encrypt_start(void)
   1586     0    stevel {
   1587     0    stevel 	struct cr_info_t cki;
   1588     0    stevel 	struct strioctl  crioc;
   1589     0    stevel 	int bytes = 0;
   1590     0    stevel 	char *dataptr = NULL;
   1591     0    stevel 
   1592     0    stevel 	if (encr_data.decrypt.type == ENCTYPE_NULL) {
   1593     0    stevel 		if (enc_debug)
   1594     0    stevel 			(void) fprintf(stderr,
   1595     0    stevel 				"\t(encrypt_start) No DECRYPT method "
   1596     0    stevel 				"defined yet\n");
   1597     0    stevel 		encrypt_send_request_end();
   1598     0    stevel 		return;
   1599     0    stevel 	}
   1600     0    stevel 
   1601     0    stevel 	cki.direction_mask = CRYPT_DECRYPT;
   1602     0    stevel 
   1603     0    stevel 	if (encr_data.decrypt.type == TELOPT_ENCTYPE_DES_CFB64) {
   1604     0    stevel 		cki.crypto_method = CRYPT_METHOD_DES_CFB;
   1605     0    stevel 	} else {
   1606     0    stevel 		if (enc_debug)
   1607     0    stevel 			(void) fprintf(stderr,
   1608     0    stevel 				"\t(encrypt_start) - unknown "
   1609     0    stevel 				"crypto_method %d\n", encr_data.decrypt.type);
   1610     0    stevel 
   1611     0    stevel 		syslog(LOG_ERR, "unrecognized crypto decrypt method: %d",
   1612     0    stevel 				encr_data.decrypt.type);
   1613     0    stevel 
   1614     0    stevel 		return;
   1615     0    stevel 	}
   1616     0    stevel 
   1617     0    stevel 	/*
   1618     0    stevel 	 * Don't overwrite previously configured key and ivec info
   1619     0    stevel 	 */
   1620     0    stevel 	if (encr_data.decrypt.setup != cki.crypto_method) {
   1621     0    stevel 		(void) memcpy(cki.key, (void *)encr_data.decrypt.krbdes_key,
   1622     0    stevel 		    DES_BLOCKSIZE);
   1623     0    stevel 		(void) memcpy(cki.ivec, (void *)encr_data.decrypt.ivec,
   1624     0    stevel 		    DES_BLOCKSIZE);
   1625     0    stevel 
   1626     0    stevel 		cki.keylen = DES_BLOCKSIZE;
   1627     0    stevel 		cki.iveclen = DES_BLOCKSIZE;
   1628     0    stevel 		cki.ivec_usage = IVEC_ONETIME;
   1629     0    stevel 	} else {
   1630     0    stevel 		cki.keylen = 0;
   1631     0    stevel 		cki.iveclen = 0;
   1632     0    stevel 	}
   1633     0    stevel 	cki.option_mask = 0;
   1634     0    stevel 
   1635     0    stevel 	stop_stream(cryptmod_fd, CRYPT_DECRYPT);
   1636     0    stevel 
   1637     0    stevel 	crioc.ic_cmd = CRYPTIOCSETUP;
   1638     0    stevel 	crioc.ic_timout = -1;
   1639     0    stevel 	crioc.ic_len = sizeof (struct cr_info_t);
   1640     0    stevel 	crioc.ic_dp = (char *)&cki;
   1641     0    stevel 
   1642     0    stevel 	if (ioctl(cryptmod_fd, I_STR, &crioc)) {
   1643     0    stevel 		syslog(LOG_ERR, "ioctl(CRYPTIOCSETUP) [encrypt_start] "
   1644     0    stevel 		    "error: %m");
   1645     0    stevel 	} else {
   1646     0    stevel 		encr_data.decrypt.setup = cki.crypto_method;
   1647     0    stevel 	}
   1648     0    stevel 	if (enc_debug)
   1649     0    stevel 		(void) fprintf(stderr,
   1650     0    stevel 			    "\t(encrypt_start) called CRYPTIOCSETUP for "
   1651     0    stevel 			    "decrypt side\n");
   1652     0    stevel 
   1653     0    stevel 	/*
   1654     0    stevel 	 * Read any data stuck between the cryptmod and the application
   1655     0    stevel 	 * so we can pass it back down to be properly decrypted after
   1656     0    stevel 	 * this operation finishes.
   1657     0    stevel 	 */
   1658     0    stevel 	if (ioctl(cryptmod_fd, I_NREAD, &bytes) < 0) {
   1659     0    stevel 		syslog(LOG_ERR, "I_NREAD returned error %m");
   1660     0    stevel 		bytes = 0;
   1661     0    stevel 	}
   1662     0    stevel 
   1663     0    stevel 	/*
   1664     0    stevel 	 * Any data which was read AFTER the ENCRYPT START message
   1665     0    stevel 	 * must be sent back down to be decrypted properly.
   1666     0    stevel 	 *
   1667     0    stevel 	 * 'ncc' is the number of bytes that have been read but
   1668     0    stevel 	 * not yet processed by the telnet state machine.
   1669     0    stevel 	 *
   1670     0    stevel 	 * 'bytes' is the number of bytes waiting to be read from
   1671     0    stevel 	 * the stream.
   1672     0    stevel 	 *
   1673     0    stevel 	 * If either one is a positive value, then those bytes
   1674     0    stevel 	 * must be pulled up and sent back down to be decrypted.
   1675     0    stevel 	 */
   1676     0    stevel 	if (ncc || bytes) {
   1677     0    stevel 		drainstream(bytes);
   1678     0    stevel 		if (enc_debug)
   1679     0    stevel 			(void) fprintf(stderr,
   1680     0    stevel 				"\t(encrypt_start) after drainstream, "
   1681     0    stevel 				"ncc=%d bytes = %d\n", ncc, bytes);
   1682     0    stevel 		bytes += ncc;
   1683     0    stevel 		dataptr = netip;
   1684     0    stevel 	}
   1685     0    stevel 
   1686     0    stevel 	start_stream(cryptmod_fd, CRYPT_DECRYPT, bytes, dataptr);
   1687     0    stevel 
   1688     0    stevel 	/*
   1689     0    stevel 	 * The bytes putback into the stream are no longer
   1690     0    stevel 	 * available to be read by the server, so adjust the
   1691     0    stevel 	 * counter accordingly.
   1692     0    stevel 	 */
   1693     0    stevel 	ncc = 0;
   1694     0    stevel 	netip = netibuf;
   1695     0    stevel 	(void) memset(netip, 0, netibufsize);
   1696     0    stevel 
   1697     0    stevel #ifdef ENCRYPT_NAMES
   1698     0    stevel 	if (enc_debug) {
   1699     0    stevel 		(void) fprintf(stderr,
   1700     0    stevel 			    "\t(encrypt_start) Start DECRYPT using %s\n",
   1701     0    stevel 			    ENCTYPE_NAME(encr_data.decrypt.type));
   1702     0    stevel 	}
   1703     0    stevel #endif /* ENCRYPT_NAMES */
   1704     0    stevel }
   1705     0    stevel 
   1706     0    stevel /*
   1707     0    stevel  * encrypt_support
   1708     0    stevel  *
   1709     0    stevel  * Called when we recieve the TELOPT_ENCRYPT SUPPORT [ encr type list ]
   1710     0    stevel  * message from a client.
   1711     0    stevel  *
   1712     0    stevel  * Choose an agreeable method (DES_CFB64) and
   1713     0    stevel  * respond with  TELOPT_ENCRYPT ENCRYPT_IS [ desired crypto method ]
   1714     0    stevel  *
   1715     0    stevel  * from: RFC 2946
   1716     0    stevel  */
   1717     0    stevel static void
   1718     0    stevel encrypt_support(char *data, int cnt)
   1719     0    stevel {
   1720     0    stevel 	int lstate = ENCR_STATE_NOT_READY;
   1721     0    stevel 	int type, use_type = 0;
   1722     0    stevel 
   1723     0    stevel 	while (cnt-- > 0 && use_type == 0) {
   1724     0    stevel 		type = *data++;
   1725     0    stevel #ifdef ENCRYPT_NAMES
   1726     0    stevel 		if (enc_debug)
   1727     0    stevel 			(void) fprintf(stderr,
   1728     0    stevel 				    "RCVD ENCRYPT SUPPORT %s\n",
   1729     0    stevel 				    ENCTYPE_NAME(type));
   1730     0    stevel #endif /* ENCRYPT_NAMES */
   1731     0    stevel 		/*
   1732     0    stevel 		 * Prefer CFB64
   1733     0    stevel 		 */
   1734     0    stevel 		if (type == TELOPT_ENCTYPE_DES_CFB64) {
   1735     0    stevel 			use_type = type;
   1736     0    stevel 		}
   1737     0    stevel 	}
   1738     0    stevel 	encr_data.encrypt.type = use_type;
   1739     0    stevel 
   1740     0    stevel 	if (use_type != TELOPT_ENCTYPE_NULL &&
   1741     0    stevel 	    authenticated != NULL && authenticated != &NoAuth &&
   1742     0    stevel 	    auth_status != AUTH_REJECT) {
   1743     0    stevel 
   1744     0    stevel 		/* Authenticated -> have session key -> send ENCRYPT IS */
   1745     0    stevel 		lstate = encrypt_send_encrypt_is();
   1746     0    stevel 		if (lstate == ENCR_STATE_OK)
   1747     0    stevel 			encrypt_start_output();
   1748     0    stevel 	} else if (use_type == TELOPT_ENCTYPE_NULL) {
   1749     0    stevel 		if (enc_debug)
   1750     0    stevel 			(void) fprintf(stderr,
   1751     0    stevel 				    "\t(encrypt_support) Cannot agree "
   1752     0    stevel 				    "on crypto algorithm, output encryption "
   1753     0    stevel 				    "disabled.\n");
   1754     0    stevel 
   1755     0    stevel 		/*
   1756     0    stevel 		 * Cannot agree on crypto algorithm
   1757     0    stevel 		 * RFC 2946 sez:
   1758     0    stevel 		 *    send "IAC SB ENCRYPT IS NULL IAC SE"
   1759     0    stevel 		 *    optionally, also send IAC WONT ENCRYPT
   1760     0    stevel 		 */
   1761     0    stevel 		write_data("%c%c%c%c%c%c%c",
   1762     0    stevel 			(uchar_t)IAC,
   1763     0    stevel 			(uchar_t)SB,
   1764     0    stevel 			(uchar_t)TELOPT_ENCRYPT,
   1765     0    stevel 			(uchar_t)ENCRYPT_IS,
   1766     0    stevel 			(uchar_t)TELOPT_ENCTYPE_NULL,
   1767     0    stevel 			(uchar_t)IAC,
   1768     0    stevel 			(uchar_t)SE);
   1769     0    stevel 		send_wont(TELOPT_ENCRYPT);
   1770     0    stevel 		netflush();
   1771     0    stevel 		if (enc_debug)
   1772     0    stevel 			(void) fprintf(stderr,
   1773     0    stevel 				    "SENT TELOPT_ENCRYPT ENCRYPT_IS "
   1774     0    stevel 				    "[NULL]\n");
   1775     0    stevel 
   1776     0    stevel 		remopts[TELOPT_ENCRYPT] = OPT_NO;
   1777     0    stevel 	}
   1778     0    stevel 	settimer(encr_support);
   1779     0    stevel }
   1780     0    stevel 
   1781     0    stevel /*
   1782     0    stevel  * encrypt_send_keyid
   1783     0    stevel  *
   1784     0    stevel  * Sent the key id we will use to the client
   1785     0    stevel  */
   1786     0    stevel static void
   1787     0    stevel encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, boolean_t saveit)
   1788     0    stevel {
   1789     0    stevel 	uchar_t sbbuf[128], *p;
   1790     0    stevel 
   1791     0    stevel 	p = sbbuf;
   1792     0    stevel 
   1793     0    stevel 	*p++ = IAC;
   1794     0    stevel 	*p++ = SB;
   1795     0    stevel 	*p++ = TELOPT_ENCRYPT;
   1796     0    stevel 	*p++ = (dir == TELNET_DIR_ENCRYPT ? ENCRYPT_ENC_KEYID :
   1797     0    stevel 		ENCRYPT_DEC_KEYID);
   1798     0    stevel 	if (saveit) {
   1799     0    stevel 		if (enc_debug)
   1800     0    stevel 			(void) fprintf(stderr,
   1801     0    stevel 				"\t(send_keyid) store %d byte %s keyid\n",
   1802     0    stevel 				keylen,
   1803     0    stevel 				(dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
   1804     0    stevel 				"DECRYPT"));
   1805     0    stevel 
   1806     0    stevel 		if (dir == TELNET_DIR_ENCRYPT) {
   1807     0    stevel 			(void) memcpy(encr_data.encrypt.keyid, keyid, keylen);
   1808     0    stevel 			encr_data.encrypt.keyidlen = keylen;
   1809     0    stevel 		} else {
   1810     0    stevel 			(void) memcpy(encr_data.decrypt.keyid, keyid, keylen);
   1811     0    stevel 			encr_data.decrypt.keyidlen = keylen;
   1812     0    stevel 		}
   1813     0    stevel 	}
   1814     0    stevel 	(void) memcpy(p, keyid, keylen);
   1815     0    stevel 	p += keylen;
   1816     0    stevel 
   1817     0    stevel 	*p++ = IAC;
   1818     0    stevel 	*p++ = SE;
   1819     0    stevel 	write_data_len((const char *)sbbuf, (size_t)(p-sbbuf));
   1820     0    stevel 	netflush();
   1821     0    stevel 
   1822     0    stevel 	if (enc_debug)
   1823     0    stevel 		(void) fprintf(stderr, "SENT TELOPT_ENCRYPT %s %d\n",
   1824     0    stevel 			(dir == TELNET_DIR_ENCRYPT ? "ENC_KEYID" :
   1825     0    stevel 			"DEC_KEYID"), keyid[0]);
   1826     0    stevel }
   1827     0    stevel 
   1828     0    stevel /*
   1829     0    stevel  * encrypt_reply
   1830     0    stevel  *
   1831     0    stevel  * When we receive the TELOPT_ENCRYPT REPLY [crtype] CFB64_IV_OK IAC SE
   1832     0    stevel  * message, process it accordingly.
   1833     0    stevel  * If the vector is acceptable, tell client we are encrypting and
   1834     0    stevel  * enable encryption on our write stream.
   1835     0    stevel  *
   1836     0    stevel  * Negotiate the KEYID next..
   1837     0    stevel  * RFC 2946, 2952
   1838     0    stevel  */
   1839     0    stevel static void
   1840     0    stevel encrypt_reply(char *data, int len)
   1841     0    stevel {
   1842     0    stevel 	uchar_t type = (uchar_t)(*data++);
   1843     0    stevel 	uchar_t result = (uchar_t)(*data);
   1844     0    stevel 	int lstate;
   1845     0    stevel 
   1846     0    stevel #ifdef ENCRYPT_NAMES
   1847     0    stevel 	if (enc_debug)
   1848     0    stevel 		(void) fprintf(stderr,
   1849     0    stevel 			"\t(encrypt_reply) ENCRYPT REPLY %s %s [len=%d]\n",
   1850     0    stevel 			ENCRYPT_NAME(type),
   1851     0    stevel 			(result == CFB64_IV_OK ? "CFB64_IV_OK" :
   1852     0    stevel 			"CFB64_IV_BAD"), len);
   1853     0    stevel #endif /* ENCRYPT_NAMES */
   1854     0    stevel 
   1855     0    stevel 	lstate = encr_data.encrypt.state;
   1856     0    stevel 	if (enc_debug)
   1857     0    stevel 		(void) fprintf(stderr,
   1858     0    stevel 			"\t(encrypt_reply) initial ENCRYPT state = %d\n",
   1859     0    stevel 			lstate);
   1860     0    stevel 	switch (result) {
   1861     0    stevel 	case CFB64_IV_OK:
   1862     0    stevel 		if (lstate == ENCR_STATE_NOT_READY)
   1863     0    stevel 			lstate = ENCR_STATE_IN_PROGRESS;
   1864     0    stevel 		lstate &= ~ENCR_STATE_NO_RECV_IV; /* we got the IV */
   1865     0    stevel 		lstate &= ~ENCR_STATE_NO_SEND_IV; /* we dont need to send IV */
   1866     0    stevel 
   1867     0    stevel 		/*
   1868     0    stevel 		 * The correct response here is to send the encryption key id
   1869     0    stevel 		 * RFC 2752.
   1870     0    stevel 		 *
   1871     0    stevel 		 * Send keyid 0 to indicate that we will just use default
   1872     0    stevel 		 * keys.
   1873     0    stevel 		 */
   1874     0    stevel 		encrypt_send_keyid(TELNET_DIR_ENCRYPT, (uchar_t *)"\0", 1, 1);
   1875     0    stevel 
   1876     0    stevel 		break;
   1877     0    stevel 	case CFB64_IV_BAD:
   1878     0    stevel 		/*
   1879     0    stevel 		 * Clear the ivec
   1880     0    stevel 		 */
   1881     0    stevel 		(void) memset(encr_data.encrypt.ivec, 0, sizeof (Block));
   1882     0    stevel 		lstate = ENCR_STATE_NOT_READY;
   1883     0    stevel 		break;
   1884     0    stevel 	default:
   1885     0    stevel 		if (enc_debug)
   1886     0    stevel 			(void) fprintf(stderr,
   1887     0    stevel 				"\t(encrypt_reply) Got unknown IV value in "
   1888     0    stevel 				"REPLY message\n");
   1889     0    stevel 		lstate = ENCR_STATE_NOT_READY;
   1890     0    stevel 		break;
   1891     0    stevel 	}
   1892     0    stevel 
   1893     0    stevel 	encr_data.encrypt.state = lstate;
   1894     0    stevel 	if (lstate == ENCR_STATE_NOT_READY) {
   1895     0    stevel 		encr_data.encrypt.autoflag = 0;
   1896     0    stevel 		encr_data.encrypt.type = ENCTYPE_NULL;
   1897     0    stevel 		if (enc_debug)
   1898     0    stevel 			(void) fprintf(stderr,
   1899     0    stevel 				    "\t(encrypt_reply) encrypt.autoflag = "
   1900     0    stevel 				    "OFF\n");
   1901     0    stevel 	} else {
   1902     0    stevel 		encr_data.encrypt.type = type;
   1903     0    stevel 		if ((lstate == ENCR_STATE_OK) && encr_data.encrypt.autoflag)
   1904     0    stevel 			encrypt_start_output();
   1905     0    stevel 	}
   1906     0    stevel 
   1907     0    stevel 	if (enc_debug)
   1908     0    stevel 		(void) fprintf(stderr,
   1909     0    stevel 			    "\t(encrypt_reply) ENCRYPT final state = %d\n",
   1910     0    stevel 			    lstate);
   1911     0    stevel }
   1912     0    stevel 
   1913     0    stevel static void
   1914     0    stevel encrypt_set_keyid_state(uchar_t *keyid, int *keyidlen, int dir)
   1915     0    stevel {
   1916     0    stevel 	int lstate;
   1917     0    stevel 
   1918     0    stevel 	lstate = (dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state :
   1919     0    stevel 		encr_data.decrypt.state);
   1920     0    stevel 
   1921     0    stevel 	if (enc_debug)
   1922     0    stevel 		(void) fprintf(stderr,
   1923     0    stevel 			    "\t(set_keyid_state) %s initial state = %d\n",
   1924     0    stevel 			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
   1925     0    stevel 			    "DECRYPT"), lstate);
   1926     0    stevel 
   1927     0    stevel 	/*
   1928     0    stevel 	 * Currently, we only support using the default keyid,
   1929     0    stevel 	 * so it should be an error if the len > 1 or the keyid != 0.
   1930     0    stevel 	 */
   1931     0    stevel 	if (*keyidlen != 1 || (*keyid != '\0')) {
   1932     0    stevel 		if (enc_debug)
   1933     0    stevel 			(void) fprintf(stderr,
   1934     0    stevel 				    "\t(set_keyid_state) unexpected keyid: "
   1935     0    stevel 				    "len=%d value=%d\n", *keyidlen, *keyid);
   1936     0    stevel 		*keyidlen = 0;
   1937     0    stevel 		syslog(LOG_ERR, "rcvd unexpected keyid %d  - only keyid of 0 "
   1938     0    stevel 		    "is supported",  *keyid);
   1939     0    stevel 	} else {
   1940     0    stevel 		/*
   1941     0    stevel 		 * We move to the "IN_PROGRESS" state.
   1942     0    stevel 		 */
   1943     0    stevel 		if (lstate == ENCR_STATE_NOT_READY)
   1944     0    stevel 			lstate = ENCR_STATE_IN_PROGRESS;
   1945     0    stevel 		/*
   1946     0    stevel 		 * Clear the NO_KEYID bit because we now have a valid keyid
   1947     0    stevel 		 */
   1948     0    stevel 		lstate &= ~ENCR_STATE_NO_KEYID;
   1949     0    stevel 	}
   1950     0    stevel 
   1951     0    stevel 	if (enc_debug)
   1952     0    stevel 		(void) fprintf(stderr,
   1953     0    stevel 			    "\t(set_keyid_state) %s final state = %d\n",
   1954     0    stevel 			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
   1955     0    stevel 			    "DECRYPT"), lstate);
   1956     0    stevel 
   1957     0    stevel 	if (dir == TELNET_DIR_ENCRYPT)
   1958     0    stevel 		encr_data.encrypt.state = lstate;
   1959     0    stevel 	else
   1960     0    stevel 		encr_data.decrypt.state = lstate;
   1961     0    stevel }
   1962     0    stevel 
   1963     0    stevel /*
   1964     0    stevel  * encrypt_keyid
   1965     0    stevel  *
   1966     0    stevel  * Set the keyid value in the key_info structure.
   1967     0    stevel  * if necessary send a response to the sender
   1968     0    stevel  */
   1969     0    stevel static void
   1970     0    stevel encrypt_keyid(uchar_t *newkeyid, int *keyidlen, uchar_t *keyid,
   1971     0    stevel 	int len, int dir)
   1972     0    stevel {
   1973     0    stevel 	if (len > TELNET_MAXNUMKEYS) {
   1974     0    stevel 		if (enc_debug)
   1975     0    stevel 			(void) fprintf(stderr,
   1976     0    stevel 				    "\t(keyid) keylen too big (%d)\n", len);
   1977     0    stevel 		return;
   1978     0    stevel 	}
   1979     0    stevel 
   1980     0    stevel 	if (enc_debug) {
   1981     0    stevel 		(void) fprintf(stderr, "\t(keyid) set KEYID for %s len = %d\n",
   1982     0    stevel 			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
   1983     0    stevel 			    "DECRYPT"), len);
   1984     0    stevel 	}
   1985     0    stevel 
   1986     0    stevel 	if (len == 0) {
   1987     0    stevel 		if (*keyidlen == 0) {
   1988     0    stevel 			if (enc_debug)
   1989     0    stevel 				(void) fprintf(stderr,
   1990     0    stevel 					    "\t(keyid) Got 0 length keyid - "
   1991     0    stevel 					    "failure\n");
   1992     0    stevel 			return;
   1993     0    stevel 		}
   1994     0    stevel 		*keyidlen = 0;
   1995     0    stevel 		encrypt_set_keyid_state(newkeyid, keyidlen, dir);
   1996     0    stevel 
   1997     0    stevel 	} else if (len != *keyidlen || memcmp(keyid, newkeyid, len)) {
   1998     0    stevel 		if (enc_debug)
   1999     0    stevel 			(void) fprintf(stderr,
   2000     0    stevel 				    "\t(keyid) Setting new key (%d bytes)\n",
   2001     0    stevel 				    len);
   2002     0    stevel 
   2003     0    stevel 		*keyidlen = len;
   2004     0    stevel 		(void) memcpy(newkeyid, keyid, len);
   2005     0    stevel 
   2006     0    stevel 		encrypt_set_keyid_state(newkeyid, keyidlen, dir);
   2007     0    stevel 	} else {
   2008     0    stevel 		encrypt_set_keyid_state(newkeyid, keyidlen, dir);
   2009     0    stevel 
   2010     0    stevel 		if (enc_debug)
   2011     0    stevel 			(void) fprintf(stderr,
   2012     0    stevel 				    "\t(keyid) %s Key already in place,"
   2013     0    stevel 				    "state = %d autoflag=%d\n",
   2014     0    stevel 			(dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" : "DECRYPT"),
   2015     0    stevel 			(dir == TELNET_DIR_ENCRYPT ? encr_data.encrypt.state:
   2016     0    stevel 			encr_data.decrypt.state),
   2017     0    stevel 			(dir == TELNET_DIR_ENCRYPT ?
   2018     0    stevel 				encr_data.encrypt.autoflag:
   2019     0    stevel 				encr_data.decrypt.autoflag));
   2020     0    stevel 
   2021     0    stevel 		/* key already in place */
   2022     0    stevel 		if ((encr_data.encrypt.state == ENCR_STATE_OK) &&
   2023     0    stevel 		    dir == TELNET_DIR_ENCRYPT && encr_data.encrypt.autoflag) {
   2024     0    stevel 			encrypt_start_output();
   2025     0    stevel 		}
   2026     0    stevel 		return;
   2027     0    stevel 	}
   2028     0    stevel 
   2029     0    stevel 	if (enc_debug)
   2030     0    stevel 		(void) fprintf(stderr, "\t(keyid) %s final state = %d\n",
   2031     0    stevel 			    (dir == TELNET_DIR_ENCRYPT ? "ENCRYPT" :
   2032     0    stevel 			    "DECRYPT"),
   2033     0    stevel 			    (dir == TELNET_DIR_ENCRYPT ?
   2034     0    stevel 			    encr_data.encrypt.state :
   2035     0    stevel 			    encr_data.decrypt.state));
   2036     0    stevel 
   2037     0    stevel 	encrypt_send_keyid(dir, newkeyid, *keyidlen, 0);
   2038     0    stevel }
   2039     0    stevel 
   2040     0    stevel /*
   2041     0    stevel  * encrypt_enc_keyid
   2042     0    stevel  *
   2043     0    stevel  * We received the ENC_KEYID message from a client indicating that
   2044     0    stevel  * the client wishes to verify that the indicated keyid maps to a
   2045     0    stevel  * valid key.
   2046     0    stevel  */
   2047     0    stevel static void
   2048     0    stevel encrypt_enc_keyid(char *data, int cnt)
   2049     0    stevel {
   2050     0    stevel 	/*
   2051     0    stevel 	 * Verify the decrypt keyid is valid
   2052     0    stevel 	 */
   2053     0    stevel 	encrypt_keyid(encr_data.decrypt.keyid, &encr_data.decrypt.keyidlen,
   2054     0    stevel 		    (uchar_t *)data, cnt, TELNET_DIR_DECRYPT);
   2055     0    stevel }
   2056     0    stevel 
   2057     0    stevel /*
   2058     0    stevel  * encrypt_dec_keyid
   2059     0    stevel  *
   2060     0    stevel  * We received the DEC_KEYID message from a client indicating that
   2061     0    stevel  * the client wants to verify that the indicated keyid maps to a valid key.
   2062     0    stevel  */
   2063     0    stevel static void
   2064     0    stevel encrypt_dec_keyid(char *data, int cnt)
   2065     0    stevel {
   2066     0    stevel 	encrypt_keyid(encr_data.encrypt.keyid, &encr_data.encrypt.keyidlen,
   2067     0    stevel 		    (uchar_t *)data, cnt, TELNET_DIR_ENCRYPT);
   2068     0    stevel }
   2069     0    stevel 
   2070     0    stevel /*
   2071     0    stevel  * encrypt_session_key
   2072     0    stevel  *
   2073     0    stevel  * Store the session key in the encryption data record
   2074     0    stevel  */
   2075     0    stevel static void
   2076     0    stevel encrypt_session_key(Session_Key *key, cipher_info_t *cinfo)
   2077     0    stevel {
   2078     0    stevel 	if (key == NULL || key->type != SK_DES) {
   2079     0    stevel 		if (enc_debug)
   2080     0    stevel 			(void) fprintf(stderr,
   2081     0    stevel 				    "\t(session_key) Cannot set krb5 "
   2082     0    stevel 				    "session key (unknown type = %d)\n",
   2083     0    stevel 				    key ? key->type : -1);
   2084     0    stevel 	}
   2085     0    stevel 	if (enc_debug)
   2086     0    stevel 		(void) fprintf(stderr,
   2087     0    stevel 			    "\t(session_key) Settting session key "
   2088     0    stevel 			    "for server\n");
   2089     0    stevel 
   2090     0    stevel 	/* store the key in the cipher info data struct */
   2091     0    stevel 	(void) memcpy(cinfo->krbdes_key, (void *)key->data, sizeof (Block));
   2092     0    stevel 
   2093     0    stevel 	/*
   2094     0    stevel 	 * Now look to see if we still need to send the key and start
   2095     0    stevel 	 * encrypting.
   2096     0    stevel 	 *
   2097     0    stevel 	 * If so, go ahead an call it now that we have the key.
   2098     0    stevel 	 */
   2099     0    stevel 	if (cinfo->need_start) {
   2100     0    stevel 		if (encrypt_send_encrypt_is() == ENCR_STATE_OK) {
   2101     0    stevel 			cinfo->need_start = 0;
   2102     0    stevel 		}
   2103     0    stevel 	}
   2104     0    stevel }
   2105     0    stevel 
   2106     0    stevel /*
   2107     0    stevel  * new_env
   2108     0    stevel  *
   2109     0    stevel  * Used to add an environment variable and value to the
   2110     0    stevel  * linked list structure.
   2111     0    stevel  */
   2112     0    stevel static int
   2113     0    stevel new_env(const char *name, const char *value)
   2114     0    stevel {
   2115     0    stevel 	struct envlist *env;
   2116     0    stevel 
   2117     0    stevel 	env = malloc(sizeof (struct envlist));
   2118     0    stevel 	if (env == NULL)
   2119     0    stevel 		return (1);
   2120     0    stevel 	if ((env->name = strdup(name)) == NULL) {
   2121     0    stevel 		free(env);
   2122     0    stevel 		return (1);
   2123     0    stevel 	}
   2124     0    stevel 	if ((env->value = strdup(value)) == NULL) {
   2125     0    stevel 		free(env->name);
   2126     0    stevel 		free(env);
   2127     0    stevel 		return (1);
   2128     0    stevel 	}
   2129     0    stevel 	env->delete = 0;
   2130     0    stevel 	env->next = envlist_head;
   2131     0    stevel 	envlist_head = env;
   2132     0    stevel 	return (0);
   2133     0    stevel }
   2134     0    stevel 
   2135     0    stevel /*
   2136     0    stevel  * del_env
   2137     0    stevel  *
   2138     0    stevel  * Used to delete an environment variable from the linked list
   2139     0    stevel  * structure.  We just set a flag because we will delete the list
   2140     0    stevel  * anyway before we exec login.
   2141     0    stevel  */
   2142     0    stevel static int
   2143     0    stevel del_env(const char *name)
   2144     0    stevel {
   2145     0    stevel 	struct envlist *env;
   2146     0    stevel 
   2147     0    stevel 	for (env = envlist_head; env; env = env->next) {
   2148     0    stevel 		if (strcmp(env->name, name) == 0) {
   2149     0    stevel 			env->delete = 1;
   2150     0    stevel 			break;
   2151     0    stevel 		}
   2152     0    stevel 	}
   2153     0    stevel 	return (0);
   2154     0    stevel }
   2155     0    stevel 
   2156     0    stevel static int
   2157     0    stevel issock(int fd)
   2158     0    stevel {
   2159     0    stevel 	struct stat stats;
   2160     0    stevel 
   2161     0    stevel 	if (fstat(fd, &stats) == -1)
   2162     0    stevel 		return (0);
   2163     0    stevel 	return (S_ISSOCK(stats.st_mode));
   2164     0    stevel }
   2165     0    stevel 
   2166     0    stevel /*
   2167     0    stevel  * audit_telnet_settid stores the terminal id while it is still
   2168     0    stevel  * available.  Subsequent calls to adt_load_hostname() return
   2169     0    stevel  * the id which is stored here.
   2170     0    stevel  */
   2171     0    stevel static int
   2172     0    stevel audit_telnet_settid(int sock) {
   2173     0    stevel 	adt_session_data_t	*ah;
   2174     0    stevel 	adt_termid_t		*termid;
   2175     0    stevel 	int			rc;
   2176     0    stevel 
   2177     0    stevel 	if ((rc = adt_start_session(&ah, NULL, 0)) == 0) {
   2178     0    stevel 		if ((rc = adt_load_termid(sock, &termid)) == 0) {
   2179     0    stevel 			if ((rc = adt_set_user(ah, ADT_NO_AUDIT,
   2180     0    stevel 			    ADT_NO_AUDIT, 0, ADT_NO_AUDIT,
   2181     0    stevel 			    termid, ADT_SETTID)) == 0)
   2182     0    stevel 				(void) adt_set_proc(ah);
   2183     0    stevel 			free(termid);
   2184     0    stevel 		}
   2185     0    stevel 		(void) adt_end_session(ah);
   2186     0    stevel 	}
   2187     0    stevel 	return (rc);
   2188     0    stevel }
   2189     0    stevel 
   2190     0    stevel /* ARGSUSED */
   2191     0    stevel int
   2192     0    stevel main(int argc, char *argv[])
   2193     0    stevel {
   2194     0    stevel 	struct sockaddr_storage from;
   2195     0    stevel 	int on = 1;
   2196     0    stevel 	socklen_t fromlen;
   2197     0    stevel 	int issocket;
   2198     0    stevel #if	defined(DEBUG)
   2199     0    stevel 	ushort_t porttouse = 0;
   2200     0    stevel 	boolean_t standalone = 0;
   2201     0    stevel #endif /* defined(DEBUG) */
   2202     0    stevel 	extern char *optarg;
   2203     0    stevel 	char c;
   2204     0    stevel 	int tos = -1;
   2205     0    stevel 
   2206     0    stevel 	while ((c = getopt(argc, argv, TELNETD_OPTS DEBUG_OPTS)) != -1) {
   2207     0    stevel 		switch (c) {
   2208     0    stevel #if defined(DEBUG)
   2209     0    stevel 		case 'p':
   2210     0    stevel 			/*
   2211     0    stevel 			 * note: alternative port number only used in
   2212     0    stevel 			 * standalone mode.
   2213     0    stevel 			 */
   2214     0    stevel 			porttouse = atoi(optarg);
   2215     0    stevel 			standalone = 1;
   2216     0    stevel 			break;
   2217     0    stevel 		case 'e':
   2218     0    stevel 			enc_debug = 1;
   2219     0    stevel 			break;
   2220     0    stevel #endif /* DEBUG */
   2221     0    stevel 		case 'a':
   2222     0    stevel 			if (strcasecmp(optarg, "none") == 0) {
   2223     0    stevel 				auth_level = 0;
   2224     0    stevel 			} else if (strcasecmp(optarg, "user") == 0) {
   2225     0    stevel 				auth_level = AUTH_USER;
   2226     0    stevel 			} else if (strcasecmp(optarg, "valid") == 0) {
   2227     0    stevel 				auth_level = AUTH_VALID;
   2228     0    stevel 			} else if (strcasecmp(optarg, "off") == 0) {
   2229     0    stevel 				auth_level = -1;
   2230     0    stevel 				negotiate_auth_krb5 = 0;
   2231     0    stevel 			} else if (strcasecmp(optarg, "debug") == 0) {
   2232     0    stevel 				auth_debug = 1;
   2233     0    stevel 			} else {
   2234     0    stevel 				syslog(LOG_ERR,
   2235     0    stevel 				    "unknown authentication level specified "
   2236     0    stevel 				    "with \'-a\' option (%s)", optarg);
   2237     0    stevel 				auth_level = AUTH_USER;
   2238     0    stevel 			}
   2239     0    stevel 			break;
   2240     0    stevel 		case 'X':
   2241     0    stevel 			/* disable authentication negotiation */
   2242     0    stevel 			negotiate_auth_krb5 = 0;
   2243     0    stevel 			break;
   2244     0    stevel 		case 'R':
   2245     0    stevel 		case 'M':
   2246     0    stevel 			if (optarg != NULL) {
   2247     0    stevel 				int ret = krb5_init();
   2248     0    stevel 				if (ret) {
   2249     0    stevel 					syslog(LOG_ERR,
   2250     0    stevel 						"Unable to use Kerberos V5 as "
   2251     0    stevel 						"requested, exiting");
   2252     0    stevel 					exit(1);
   2253     0    stevel 				}
   2254     0    stevel 				krb5_set_default_realm(telnet_context, optarg);
   2255     0    stevel 				syslog(LOG_NOTICE,
   2256     0    stevel 				    "using %s as default KRB5 realm", optarg);
   2257     0    stevel 			}
   2258     0    stevel 			break;
   2259     0    stevel 		case 'S':
   2260     0    stevel 			telnet_srvtab = (char *)strdup(optarg);
   2261     0    stevel 			break;
   2262     0    stevel 		case 'E': /* disable automatic encryption */
   2263     0    stevel 			negotiate_encrypt = B_FALSE;
   2264     0    stevel 			break;
   2265     0    stevel 		case 'U':
   2266     0    stevel 			resolve_hostname = 1;
   2267     0    stevel 			break;
   2268     0    stevel 		case 's':
   2269     0    stevel 			if (optarg == NULL || (tos = atoi(optarg)) < 0 ||
   2270     0    stevel 			    tos > 255) {
   2271     0    stevel 				syslog(LOG_ERR, "telnetd: illegal tos value: "
   2272     0    stevel 				    "%s\n", optarg);
   2273     0    stevel 			} else {
   2274     0    stevel 				if (tos < 0)
   2275     0    stevel 					tos = 020;
   2276     0    stevel 			}
   2277     0    stevel 			break;
   2278     0    stevel 		case 'h':
   2279     0    stevel 			show_hostinfo = 0;
   2280     0    stevel 			break;
   2281     0    stevel 		default:
   2282     0    stevel 			syslog(LOG_ERR, "telnetd: illegal cmd line option %c",
   2283     0    stevel 			    c);
   2284     0    stevel 			break;
   2285     0    stevel 		}
   2286     0    stevel 	}
   2287     0    stevel 
   2288     0    stevel 	netibufsize = BUFSIZ;
   2289     0    stevel 	if (!(netibuf = (char *)malloc(netibufsize)))
   2290     0    stevel 		syslog(LOG_ERR, "netibuf malloc failed\n");
   2291     0    stevel 	(void) memset(netibuf, 0, netibufsize);
   2292     0    stevel 	netip = netibuf;
   2293     0    stevel 
   2294     0    stevel #if	defined(DEBUG)
   2295     0    stevel 	if (standalone) {
   2296     0    stevel 		int s, ns, foo;
   2297     0    stevel 		struct servent *sp;
   2298     0    stevel 		static struct sockaddr_in6 sin6 = { AF_INET6 };
   2299     0    stevel 		int option = 1;
   2300     0    stevel 
   2301     0    stevel 		if (porttouse) {
   2302     0    stevel 			sin6.sin6_port = htons(porttouse);
   2303     0    stevel 		} else {
   2304     0    stevel 			sp = getservbyname("telnet", "tcp");
   2305     0    stevel 			if (sp == 0) {
   2306     0    stevel 				(void) fprintf(stderr,
   2307     0    stevel 					    "telnetd: tcp/telnet: "
   2308     0    stevel 					    "unknown service\n");
   2309     0    stevel 				exit(EXIT_FAILURE);
   2310     0    stevel 			}
   2311     0    stevel 			sin6.sin6_port = sp->s_port;
   2312     0    stevel 		}
   2313     0    stevel 
   2314     0    stevel 		s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
   2315     0    stevel 		if (s < 0) {
   2316     0    stevel 			perror("telnetd: socket");
   2317     0    stevel 			exit(EXIT_FAILURE);
   2318     0    stevel 		}
   2319     0    stevel 		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&option,
   2320     0    stevel 		    sizeof (option)) == -1)
   2321     0    stevel 			perror("setsockopt SO_REUSEADDR");
   2322     0    stevel 		if (bind(s, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) {
   2323     0    stevel 			perror("bind");
   2324     0    stevel 			exit(EXIT_FAILURE);
   2325     0    stevel 		}
   2326     0    stevel 		if (listen(s, 32) < 0) {
   2327     0    stevel 			perror("listen");
   2328     0    stevel 			exit(EXIT_FAILURE);
   2329     0    stevel 		}
   2330     0    stevel 
   2331     0    stevel 		/* automatically reap all child processes */
   2332     0    stevel 		(void) signal(SIGCHLD, SIG_IGN);
   2333     0    stevel 
   2334     0    stevel 		for (;;) {
   2335     0    stevel 			pid_t pid;
   2336     0    stevel 
   2337     0    stevel 			foo = sizeof (sin6);
   2338     0    stevel 			ns = accept(s, (struct sockaddr *)&sin6, &foo);
   2339     0    stevel 			if (ns < 0) {
   2340     0    stevel 				perror("accept");
   2341     0    stevel 				exit(EXIT_FAILURE);
   2342     0    stevel 			}
   2343     0    stevel 			pid = fork();
   2344     0    stevel 			if (pid == -1) {
   2345     0    stevel 				perror("fork");
   2346     0    stevel 				exit(EXIT_FAILURE);
   2347     0    stevel 			}
   2348     0    stevel 			if (pid == 0) {
   2349     0    stevel 				(void) dup2(ns, 0);
   2350     0    stevel 				(void) close(s);
   2351     0    stevel 				(void) signal(SIGCHLD, SIG_DFL);
   2352     0    stevel 				break;
   2353     0    stevel 			}
   2354     0    stevel 			(void) close(ns);
   2355     0    stevel 		}
   2356     0    stevel 	}
   2357     0    stevel #endif /* defined(DEBUG) */
   2358     0    stevel 
   2359     0    stevel 	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
   2360     0    stevel 
   2361     0    stevel 	issocket = issock(0);
   2362     0    stevel 	if (!issocket)
   2363     0    stevel 		fatal(0, "stdin is not a socket file descriptor");
   2364     0    stevel 
   2365     0    stevel 	fromlen = (socklen_t)sizeof (from);
   2366     0    stevel 	(void) memset((char *)&from, 0, sizeof (from));
   2367     0    stevel 	if (getpeername(0, (struct sockaddr *)&from, &fromlen)
   2368     0    stevel 	    < 0) {
   2369     0    stevel 		(void) fprintf(stderr, "%s: ", argv[0]);
   2370     0    stevel 		perror("getpeername");
   2371     0    stevel 		_exit(EXIT_FAILURE);
   2372     0    stevel 	}
   2373     0    stevel 
   2374     0    stevel 	if (audit_telnet_settid(0)) {	/* set terminal ID */
   2375     0    stevel 		(void) fprintf(stderr, "%s: ", argv[0]);
   2376     0    stevel 		perror("audit");
   2377     0    stevel 		exit(EXIT_FAILURE);
   2378     0    stevel 	}
   2379     0    stevel 
   2380     0    stevel 	if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on,
   2381     0    stevel 						sizeof (on)) < 0) {
   2382     0    stevel 		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
   2383     0    stevel 	}
   2384     0    stevel 
   2385     0    stevel 	/*
   2386     0    stevel 	 * Set the TOS value
   2387     0    stevel 	 */
   2388     0    stevel 	if (tos != -1 &&
   2389     0    stevel 	    setsockopt(0, IPPROTO_IP, IP_TOS,
   2390     0    stevel 		    (char *)&tos, sizeof (tos)) < 0 &&
   2391     0    stevel 		errno != ENOPROTOOPT) {
   2392     0    stevel 		syslog(LOG_ERR, "setsockopt (IP_TOS %d): %m", tos);
   2393     0    stevel 	}
   2394     0    stevel 
   2395     0    stevel 	if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
   2396     0    stevel 	    sizeof (on)) < 0) {
   2397     0    stevel 		syslog(LOG_WARNING, "setsockopt (SO_OOBINLINE): %m");
   2398     0    stevel 	}
   2399     0    stevel 
   2400     0    stevel 	/* set the default PAM service name */
   2401     0    stevel 	(void) strcpy(pam_svc_name, "telnet");
   2402     0    stevel 
   2403     0    stevel 	doit(0, &from);
   2404     0    stevel 	return (EXIT_SUCCESS);
   2405     0    stevel }
   2406     0    stevel 
   2407     0    stevel static char	*terminaltype = 0;
   2408     0    stevel 
   2409     0    stevel /*
   2410     0    stevel  * ttloop
   2411     0    stevel  *
   2412     0    stevel  *	A small subroutine to flush the network output buffer, get some data
   2413     0    stevel  * from the network, and pass it through the telnet state machine.  We
   2414     0    stevel  * also flush the pty input buffer (by dropping its data) if it becomes
   2415     0    stevel  * too full.
   2416     0    stevel  */
   2417     0    stevel static void
   2418     0    stevel ttloop(void)
   2419     0    stevel {
   2420     0    stevel 	if (nfrontp-nbackp) {
   2421     0    stevel 		netflush();
   2422     0    stevel 	}
   2423     0    stevel read_again:
   2424     0    stevel 	ncc = read(net, netibuf, netibufsize);
   2425     0    stevel 	if (ncc < 0) {
   2426     0    stevel 		if (errno == EINTR)
   2427     0    stevel 			goto read_again;
   2428     0    stevel 		syslog(LOG_INFO, "ttloop:  read: %m");
   2429     0    stevel 		exit(EXIT_FAILURE);
   2430     0    stevel 	} else if (ncc == 0) {
   2431     0    stevel 		syslog(LOG_INFO, "ttloop:  peer closed connection\n");
   2432     0    stevel 		exit(EXIT_FAILURE);
   2433     0    stevel 	}
   2434     0    stevel 
   2435     0    stevel 	netip = netibuf;
   2436     0    stevel 	telrcv();		/* state machine */
   2437     0    stevel 	if (ncc > 0) {
   2438     0    stevel 		pfrontp = pbackp = ptyobuf;
   2439     0    stevel 		telrcv();
   2440     0    stevel 	}
   2441     0    stevel }
   2442     0    stevel 
   2443     0    stevel static void
   2444     0    stevel send_do(int option)
   2445     0    stevel {
   2446     0    stevel 	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)DO, (uchar_t)option);
   2447     0    stevel }
   2448     0    stevel 
   2449     0    stevel static void
   2450     0    stevel send_will(int option)
   2451     0    stevel {
   2452     0    stevel 	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WILL, (uchar_t)option);
   2453     0    stevel }
   2454     0    stevel 
   2455     0    stevel static void
   2456     0    stevel send_wont(int option)
   2457     0    stevel {
   2458     0    stevel 	write_data("%c%c%c", (uchar_t)IAC, (uchar_t)WONT, (uchar_t)option);
   2459     0    stevel }
   2460     0    stevel 
   2461     0    stevel 
   2462     0    stevel /*
   2463     0    stevel  * getauthtype
   2464     0    stevel  *
   2465     0    stevel  * Negotiate automatic authentication, is possible.
   2466     0    stevel  */
   2467     0    stevel static int
   2468     0    stevel getauthtype(char *username, int *len)
   2469     0    stevel {
   2470     0    stevel 	int init_status = -1;
   2471     0    stevel 
   2472     0    stevel 	init_status = krb5_init();
   2473     0    stevel 
   2474     0    stevel 	if (auth_level == -1 || init_status != 0) {
   2475     0    stevel 		remopts[TELOPT_AUTHENTICATION] = OPT_NO;
   2476     0    stevel 		myopts[TELOPT_AUTHENTICATION] = OPT_NO;
   2477     0    stevel 		negotiate_auth_krb5 = B_FALSE;
   2478     0    stevel 		negotiate_encrypt = B_FALSE;
   2479     0    stevel 		return (AUTH_REJECT);
   2480     0    stevel 	}
   2481     0    stevel 
   2482     0    stevel 	if (init_status == 0 && auth_level != -1) {
   2483     0    stevel 		if (negotiate_auth_krb5) {
   2484     0    stevel 			/*
   2485     0    stevel 			 * Negotiate Authentication FIRST
   2486     0    stevel 			 */
   2487     0    stevel 			send_do(TELOPT_AUTHENTICATION);
   2488     0    stevel 			remopts[TELOPT_AUTHENTICATION] =
   2489     0    stevel 				OPT_YES_BUT_ALWAYS_LOOK;
   2490     0    stevel 		}
   2491     0    stevel 		while (sequenceIs(authopt, getauth))
   2492     0    stevel 			ttloop();
   2493     0    stevel 
   2494     0    stevel 		if (remopts[TELOPT_AUTHENTICATION] == OPT_YES) {
   2495     0    stevel 			/*
   2496     0    stevel 			 * Request KRB5 Mutual authentication and if that fails,
   2497     0    stevel 			 * KRB5 1-way client authentication
   2498     0    stevel 			 */
   2499     0    stevel 			uchar_t sbbuf[MAXOPTLEN], *p;
   2500     0    stevel 			p = sbbuf;
   2501     0    stevel 			*p++ = (uchar_t)IAC;
   2502     0    stevel 			*p++ = (uchar_t)SB;
   2503     0    stevel 			*p++ = (uchar_t)TELOPT_AUTHENTICATION;
   2504     0    stevel 			*p++ = (uchar_t)TELQUAL_SEND;
   2505     0    stevel 			if (negotiate_auth_krb5) {
   2506     0    stevel 				*p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
   2507     0    stevel 				*p++ = (uchar_t)(AUTH_WHO_CLIENT |
   2508     0    stevel 						AUTH_HOW_MUTUAL |
   2509     0    stevel 						AUTH_ENCRYPT_ON);
   2510     0    stevel 				*p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
   2511     0    stevel 				*p++ = (uchar_t)(AUTH_WHO_CLIENT |
   2512     0    stevel 						AUTH_HOW_MUTUAL);
   2513     0    stevel 				*p++ = (uchar_t)AUTHTYPE_KERBEROS_V5;
   2514     0    stevel 				*p++ = (uchar_t)(AUTH_WHO_CLIENT|
   2515     0    stevel 						AUTH_HOW_ONE_WAY);
   2516     0    stevel 			} else {
   2517     0    stevel 				*p++ = (uchar_t)AUTHTYPE_NULL;
   2518     0    stevel 			}
   2519     0    stevel 			*p++ = (uchar_t)IAC;
   2520     0    stevel 			*p++ = (uchar_t)SE;
   2521     0    stevel 
   2522     0    stevel 			write_data_len((const char *)sbbuf,
   2523     0    stevel 				    (size_t)(p - sbbuf));
   2524     0    stevel 			netflush();
   2525     0    stevel 			if (auth_debug)
   2526     0    stevel 				(void) fprintf(stderr,
   2527     0    stevel 					    "SENT TELOPT_AUTHENTICATION "
   2528     0    stevel 					    "[data]\n");
   2529     0    stevel 
   2530     0    stevel 			/* auth_wait returns the authentication level */
   2531     0    stevel 			/* status = auth_wait(username, len); */
   2532     0    stevel 			while (sequenceIs(authdone, getauth))
   2533     0    stevel 				ttloop();
   2534     0    stevel 			/*
   2535     0    stevel 			 * Now check to see if the user is valid or not
   2536     0    stevel 			 */
   2537     0    stevel 			if (authenticated == NULL || authenticated == &NoAuth)
   2538     0    stevel 				auth_status = AUTH_REJECT;
   2539     0    stevel 			else {
   2540     0    stevel 				/*
   2541     0    stevel 				 * We cant be VALID until the user status is
   2542     0    stevel 				 * checked.
   2543     0    stevel 				 */
   2544     0    stevel 				if (auth_status == AUTH_VALID)
   2545     0    stevel 					auth_status = AUTH_USER;
   2546     0    stevel 
   2547     0    stevel 				if (authenticated->AuthName ==
   2548     0    stevel 					AUTHTYPE_KERBEROS_V5)
   2549     0    stevel 					auth_status = krb5_user_status(
   2550     0    stevel 						username, *len, auth_status);
   2551     0    stevel 			}
   2552     0    stevel 		}
   2553     0    stevel 	}
   2554     0    stevel 	return (auth_status);
   2555     0    stevel }
   2556     0    stevel 
   2557     0    stevel static void
   2558     0    stevel getencrtype(void)
   2559     0    stevel {
   2560     0    stevel 	if (krb5_privacy_allowed() && negotiate_encrypt) {
   2561     0    stevel 		if (myopts[TELOPT_ENCRYPT] != OPT_YES) {
   2562     0    stevel 			if (!sent_will_encrypt) {
   2563     0    stevel 				send_will(TELOPT_ENCRYPT);
   2564     0    stevel 				sent_will_encrypt = B_TRUE;
   2565     0    stevel 			}
   2566     0    stevel 			if (enc_debug)
   2567     0    stevel 				(void) fprintf(stderr, "SENT WILL ENCRYPT\n");
   2568     0    stevel 		}
   2569     0    stevel 		if (remopts[TELOPT_ENCRYPT] != OPT_YES) {
   2570     0    stevel 			if (!sent_do_encrypt) {
   2571     0    stevel 				send_do(TELOPT_ENCRYPT);
   2572     0    stevel 				sent_do_encrypt = B_TRUE;
   2573    93  ethindra 				remopts[TELOPT_ENCRYPT] =
   2574    93  ethindra 				    OPT_YES_BUT_ALWAYS_LOOK;
   2575     0    stevel 			}
   2576     0    stevel 			if (enc_debug)
   2577     0    stevel 				(void) fprintf(stderr, "SENT DO ENCRYPT\n");
   2578     0    stevel 		}
   2579     0    stevel 		myopts[TELOPT_ENCRYPT] = OPT_YES;
   2580     0    stevel 
   2581     0    stevel 		while (sequenceIs(encropt, getencr))
   2582     0    stevel 		    ttloop();
   2583     0    stevel 
   2584     0    stevel 		if (auth_status != AUTH_REJECT &&
   2585     0    stevel 		    remopts[TELOPT_ENCRYPT] == OPT_YES &&
   2586     0    stevel 		    myopts[TELOPT_ENCRYPT] == OPT_YES) {
   2587     0    stevel 
   2588     0    stevel 			if (sent_encrypt_support == B_FALSE) {
   2589     0    stevel 				write_data("%c%c%c%c%c%c%c",
   2590     0    stevel 					(uchar_t)IAC,
   2591     0    stevel 					(uchar_t)SB,
   2592     0    stevel 					(uchar_t)TELOPT_ENCRYPT,
   2593     0    stevel 					(uchar_t)ENCRYPT_SUPPORT,
   2594     0    stevel 					(uchar_t)TELOPT_ENCTYPE_DES_CFB64,
   2595     0    stevel 					(uchar_t)IAC,
   2596     0    stevel 					(uchar_t)SE);
   2597     0    stevel 
   2598     0    stevel 				netflush();
   2599     0    stevel 			}
   2600     0    stevel 			/*
   2601     0    stevel 			 * Now wait for a response to these messages before
   2602     0    stevel 			 * continuing...
   2603     0    stevel 			 * Look for TELOPT_ENCRYPT suboptions
   2604     0    stevel 			 */
   2605     0    stevel 			while (sequenceIs(encr_support, getencr))
   2606     0    stevel 				ttloop();
   2607     0    stevel 		}
   2608     0    stevel 	} else {
   2609     0    stevel 		/* Dont need responses to these, so dont wait for them */
   2610     0    stevel 		settimer(encropt);
   2611     0    stevel 		remopts[TELOPT_ENCRYPT] = OPT_NO;
   2612     0    stevel 		myopts[TELOPT_ENCRYPT] = OPT_NO;
   2613     0    stevel 	}
   2614     0    stevel 
   2615     0    stevel }
   2616     0    stevel 
   2617     0    stevel /*
   2618     0    stevel  * getterminaltype
   2619     0    stevel  *
   2620     0    stevel  * Ask the other end to send along its terminal type.
   2621     0    stevel  * Output is the variable terminaltype filled in.
   2622     0    stevel  */
   2623     0    stevel static void
   2624     0    stevel getterminaltype(void)
   2625     0    stevel {
   2626     0    stevel 	/*
   2627     0    stevel 	 * The remote side may have already sent this info, so
   2628     0    stevel 	 * dont ask for these options if the other side already
   2629     0    stevel 	 * sent the information.
   2630     0    stevel 	 */
   2631     0    stevel 	if (sequenceIs(ttypeopt, getterminal)) {
   2632     0    stevel 		send_do(TELOPT_TTYPE);
   2633     0    stevel 		remopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK;
   2634     0    stevel 	}
   2635     0    stevel 
   2636     0    stevel 	if (sequenceIs(nawsopt, getterminal)) {
   2637     0    stevel 		send_do(TELOPT_NAWS);
   2638     0    stevel 		remopts[TELOPT_NAWS] = OPT_YES_BUT_ALWAYS_LOOK;
   2639     0    stevel 	}
   2640     0    stevel 
   2641     0    stevel 	if (sequenceIs(xdisplocopt, getterminal)) {
   2642     0    stevel 		send_do(TELOPT_XDISPLOC);
   2643     0    stevel 		remopts[TELOPT_XDISPLOC] = OPT_YES_BUT_ALWAYS_LOOK;
   2644     0    stevel 	}
   2645     0    stevel 
   2646     0    stevel 	if (sequenceIs(environopt, getterminal)) {
   2647     0    stevel 		send_do(TELOPT_NEW_ENVIRON);
   2648     0    stevel 		remopts[TELOPT_NEW_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
   2649     0    stevel 	}
   2650     0    stevel 
   2651     0    stevel 	if (sequenceIs(oenvironopt, getterminal)) {
   2652     0    stevel 		send_do(TELOPT_OLD_ENVIRON);
   2653     0    stevel 		remopts[TELOPT_OLD_ENVIRON] = OPT_YES_BUT_ALWAYS_LOOK;
   2654     0    stevel 	}
   2655     0    stevel 
   2656     0    stevel 	/* make sure encryption is started here */
   2657     0    stevel 	while (auth_status != AUTH_REJECT &&
   2658     0    stevel 		authenticated != &NoAuth && authenticated != NULL &&
   2659     0    stevel 		remopts[TELOPT_ENCRYPT] == OPT_YES &&
   2660     0    stevel 		encr_data.encrypt.autoflag &&
   2661     0    stevel 		encr_data.encrypt.state != ENCR_STATE_OK) {
   2662     0    stevel 	    if (enc_debug)
   2663     0    stevel 		(void) fprintf(stderr, "getterminaltype() forcing encrypt\n");
   2664     0    stevel 	    ttloop();
   2665     0    stevel 	}
   2666     0    stevel 
   2667     0    stevel 	if (enc_debug) {
   2668     0    stevel 	    (void) fprintf(stderr, "getterminaltype() encryption %sstarted\n",
   2669     0    stevel 		    encr_data.encrypt.state == ENCR_STATE_OK ? "" : "not ");
   2670     0    stevel 	}
   2671     0    stevel 
   2672     0    stevel 	while (sequenceIs(ttypeopt, getterminal) ||
   2673     0    stevel 	    sequenceIs(nawsopt, getterminal) ||
   2674     0    stevel 	    sequenceIs(xdisplocopt, getterminal) ||
   2675     0    stevel 	    sequenceIs(environopt, getterminal) ||
   2676     0    stevel 	    sequenceIs(oenvironopt, getterminal)) {
   2677     0    stevel 		ttloop();
   2678     0    stevel 	}
   2679     0    stevel 
   2680     0    stevel 
   2681     0    stevel 	if (remopts[TELOPT_TTYPE] == OPT_YES) {
   2682     0    stevel 		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
   2683     0    stevel 		    (uchar_t)TELOPT_TTYPE, (uchar_t)TELQUAL_SEND,
   2684     0    stevel 		    (uchar_t)IAC, (uchar_t)SE };
   2685     0    stevel 
   2686     0    stevel 		write_data_len((const char *)sbbuf, sizeof (sbbuf));
   2687     0    stevel 	}
   2688     0    stevel 	if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
   2689     0    stevel 		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
   2690     0    stevel 		    (uchar_t)TELOPT_XDISPLOC, (uchar_t)TELQUAL_SEND,
   2691     0    stevel 		    (uchar_t)IAC, (uchar_t)SE };
   2692     0    stevel 
   2693     0    stevel 		write_data_len((const char *)sbbuf, sizeof (sbbuf));
   2694     0    stevel 	}
   2695     0    stevel 	if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
   2696     0    stevel 		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
   2697     0    stevel 		    (uchar_t)TELOPT_NEW_ENVIRON, (uchar_t)TELQUAL_SEND,
   2698     0    stevel 		    (uchar_t)IAC, (uchar_t)SE };
   2699     0    stevel 
   2700     0    stevel 		write_data_len((const char *)sbbuf, sizeof (sbbuf));
   2701     0    stevel 	}
   2702     0    stevel 	if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
   2703     0    stevel 		static uchar_t sbbuf[] = { (uchar_t)IAC, (uchar_t)SB,
   2704     0    stevel 		    (uchar_t)TELOPT_OLD_ENVIRON, (uchar_t)TELQUAL_SEND,
   2705     0    stevel 		    (uchar_t)IAC, (uchar_t)SE };
   2706     0    stevel 
   2707     0    stevel 		write_data_len((const char *)sbbuf, sizeof (sbbuf));
   2708     0    stevel 	}
   2709     0    stevel 
   2710     0    stevel 	if (remopts[TELOPT_TTYPE] == OPT_YES) {
   2711     0    stevel 		while (sequenceIs(ttypesubopt, getterminal)) {
   2712     0    stevel 			ttloop();
   2713     0    stevel 		}
   2714     0    stevel 	}
   2715     0    stevel 	if (remopts[TELOPT_XDISPLOC] == OPT_YES) {
   2716     0    stevel 		while (sequenceIs(xdisplocsubopt, getterminal)) {
   2717     0    stevel 			ttloop();
   2718     0    stevel 		}
   2719     0    stevel 	}
   2720     0    stevel 	if (remopts[TELOPT_NEW_ENVIRON] == OPT_YES) {
   2721     0    stevel 		while (sequenceIs(environsubopt, getterminal)) {
   2722     0    stevel 			ttloop();
   2723     0    stevel 		}
   2724     0    stevel 	}
   2725     0    stevel 	if (remopts[TELOPT_OLD_ENVIRON] == OPT_YES) {
   2726     0    stevel 		while (sequenceIs(oenvironsubopt, getterminal)) {
   2727     0    stevel 			ttloop();
   2728     0    stevel 		}
   2729     0    stevel 	}
   2730     0    stevel 	init_neg_done = 1;
   2731     0    stevel }
   2732     0    stevel 
   2733     0    stevel pid_t pid;
   2734     0    stevel 
   2735     0    stevel /*
   2736     0    stevel  * Get a pty, scan input lines.
   2737     0    stevel  */
   2738     0    stevel static void
   2739     0    stevel doit(int f, struct sockaddr_storage *who)
   2740     0    stevel {
   2741     0    stevel 	char *host;
   2742     0    stevel 	char host_name[MAXHOSTNAMELEN];
   2743     0    stevel 	int p, t, tt;
   2744     0    stevel 	struct sgttyb b;
   2745     0    stevel 	int	ptmfd;	/* fd of logindmux connected to pty */
   2746     0    stevel 	int	netfd;	/* fd of logindmux connected to netf */
   2747     0    stevel 	struct	stat	buf;
   2748     0    stevel 	struct	protocol_arg	telnetp;
   2749     0    stevel 	struct	strioctl	telnetmod;
   2750     0    stevel 	struct	envlist	*env, *next;
   2751     0    stevel 	int	nsize = 0;
   2752     0    stevel 	char abuf[INET6_ADDRSTRLEN];
   2753     0    stevel 	struct sockaddr_in *sin;
   2754     0    stevel 	struct sockaddr_in6 *sin6;
   2755     0    stevel 	socklen_t wholen;
   2756     0    stevel 	char username[MAXUSERNAMELEN];
   2757     0    stevel 	int len;
   2758     0    stevel 	uchar_t passthru;
   2759     0    stevel 	char *slavename;
   2760     0    stevel 
   2761     0    stevel 	if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
   2762     0    stevel 		fatalperror(f, "open /dev/ptmx", errno);
   2763     0    stevel 	}
   2764     0    stevel 	if (grantpt(p) == -1)
   2765     0    stevel 		fatal(f, "could not grant slave pty");
   2766     0    stevel 	if (unlockpt(p) == -1)
   2767     0    stevel 		fatal(f, "could not unlock slave pty");
   2768     0    stevel 	if ((slavename = ptsname(p)) == NULL)
   2769     0    stevel 		fatal(f, "could not enable slave pty");
   2770     0    stevel 	(void) dup2(f, 0);
   2771     0    stevel 	if ((t = open(slavename, O_RDWR | O_NOCTTY)) == -1)
   2772     0    stevel 		fatal(f, "could not open slave pty");
   2773     0    stevel 	if (ioctl(t, I_PUSH, "ptem") == -1)
   2774     0    stevel 		fatalperror(f, "ioctl I_PUSH ptem", errno);
   2775     0    stevel 	if (ioctl(t, I_PUSH, "ldterm") == -1)
   2776     0    stevel 		fatalperror(f, "ioctl I_PUSH ldterm", errno);
   2777     0    stevel 	if (ioctl(t, I_PUSH, "ttcompat") == -1)
   2778     0    stevel 		fatalperror(f, "ioctl I_PUSH ttcompat", errno);
   2779     0    stevel 
   2780     0    stevel 	line = slavename;
   2781     0    stevel 
   2782     0    stevel 	pty = t;
   2783     0    stevel 
   2784     0    stevel 	if (ioctl(t, TIOCGETP, &b) == -1)
   2785     0    stevel 		syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
   2786     0    stevel 	b.sg_flags = O_CRMOD|O_XTABS|O_ANYP;
   2787     0    stevel 	/* XXX - ispeed and ospeed must be non-zero */
   2788     0    stevel 	b.sg_ispeed = B38400;
   2789     0    stevel 	b.sg_ospeed = B38400;
   2790     0    stevel 	if (ioctl(t, TIOCSETN, &b) == -1)
   2791     0    stevel 		syslog(LOG_INFO, "ioctl TIOCSETN pty t: %m\n");
   2792     0    stevel 	if (ioctl(pty, TIOCGETP, &b) == -1)
   2793     0    stevel 		syslog(LOG_INFO, "ioctl TIOCGETP pty pty: %m\n");
   2794     0    stevel 	b.sg_flags &= ~O_ECHO;
   2795     0    stevel 	if (ioctl(pty, TIOCSETN, &b) == -1)
   2796     0    stevel 		syslog(LOG_INFO, "ioctl TIOCSETN pty pty: %m\n");
   2797     0    stevel 
   2798     0    stevel 	if (who->ss_family == AF_INET) {
   2799     0    stevel 		char *addrbuf = NULL;
   2800     0    stevel 		char *portbuf = NULL;
   2801     0    stevel 
   2802     0    stevel 		sin = (struct sockaddr_in *)who;
   2803     0    stevel 		wholen = sizeof (struct sockaddr_in);
   2804     0    stevel 
   2805     0    stevel 		addrbuf = (char *)malloc(wholen);
   2806     0    stevel 		if (addrbuf == NULL)
   2807     0    stevel 			fatal(f, "Cannot alloc memory for address info\n");
   2808     0    stevel 		portbuf = (char *)malloc(sizeof (sin->sin_port));
   2809     0    stevel 		if (portbuf == NULL) {
   2810     0    stevel 			free(addrbuf);
   2811     0    stevel 			fatal(f, "Cannot alloc memory for port info\n");
   2812     0    stevel 		}
   2813     0    stevel 
   2814     0    stevel 		(void) memcpy(addrbuf, (const void *)&sin->sin_addr, wholen);
   2815     0    stevel 		(void) memcpy(portbuf, (const void *)&sin->sin_port,
   2816     0    stevel 			    sizeof (sin->sin_port));
   2817     0    stevel 
   2818     0    stevel 		if (rsaddr.contents != NULL)
   2819     0    stevel 			free(rsaddr.contents);
   2820     0    stevel 
   2821     0    stevel 		rsaddr.contents = (krb5_octet *)addrbuf;
   2822     0    stevel 		rsaddr.length = wholen;
   2823     0    stevel 		rsaddr.addrtype = ADDRTYPE_INET;
   2824     0    stevel 
   2825     0    stevel 		if (rsport.contents != NULL)
   2826     0    stevel 			free(rsport.contents);
   2827     0    stevel 
   2828     0    stevel 		rsport.contents = (krb5_octet *)portbuf;
   2829     0    stevel 		rsport.length = sizeof (sin->sin_port);
   2830     0    stevel 		rsport.addrtype = ADDRTYPE_IPPORT;
   2831     0    stevel 	} else if (who->ss_family == AF_INET6) {
   2832     0    stevel 		struct in_addr ipv4_addr;
   2833     0    stevel 		char *addrbuf = NULL;
   2834     0    stevel 		char *portbuf = NULL;
   2835     0    stevel 
   2836     0    stevel 		sin6 = (struct sockaddr_in6 *)who;
   2837     0    stevel 		wholen = sizeof (struct sockaddr_in6);
   2838     0    stevel 
   2839     0    stevel 		IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
   2840     0    stevel 				    &ipv4_addr);
   2841     0    stevel 
   2842     0    stevel 		addrbuf = (char *)malloc(wholen);
   2843     0    stevel 		if (addrbuf == NULL)
   2844     0    stevel 			fatal(f, "Cannot alloc memory for address info\n");
   2845     0    stevel 
   2846     0    stevel 		portbuf = (char *)malloc(sizeof (sin6->sin6_port));
   2847     0    stevel 		if (portbuf == NULL) {
   2848     0    stevel 			free(addrbuf);
   2849     0    stevel 			fatal(f, "Cannot alloc memory for port info\n");
   2850     0    stevel 		}
   2851     0    stevel 
   2852     0    stevel 		(void) memcpy((void *) addrbuf,
   2853     0    stevel 			    (const void *)&ipv4_addr,
   2854     0    stevel 			    wholen);
   2855     0    stevel 		/*
   2856     0    stevel 		 * If we already used rsaddr.contents, free the previous
   2857     0    stevel 		 * buffer.
   2858     0    stevel 		 */
   2859     0    stevel 		if (rsaddr.contents != NULL)
   2860     0    stevel 			free(rsaddr.contents);
   2861     0    stevel 
   2862     0    stevel 		rsaddr.contents = (krb5_octet *)addrbuf;
   2863     0    stevel 		rsaddr.length = sizeof (ipv4_addr);
   2864     0    stevel 		rsaddr.addrtype = ADDRTYPE_INET;
   2865     0    stevel 
   2866     0    stevel 		(void) memcpy((void *) portbuf, (const void *)&sin6->sin6_port,
   2867     0    stevel 			    sizeof (sin6->sin6_port));
   2868     0    stevel 
   2869     0    stevel 		if (rsport.contents != NULL)
   2870     0    stevel 			free(rsport.contents);
   2871     0    stevel 
   2872     0    stevel 		rsport.contents = (krb5_octet *)portbuf;
   2873     0    stevel 		rsport.length = sizeof (sin6->sin6_port);
   2874     0    stevel 		rsport.addrtype = ADDRTYPE_IPPORT;
   2875     0    stevel 	} else {
   2876     0    stevel 		syslog(LOG_ERR, "unknown address family %d\n",
   2877     0    stevel 		    who->ss_family);
   2878     0    stevel 		fatal(f, "getpeername: unknown address family\n");
   2879     0    stevel 	}
   2880     0    stevel 
   2881     0    stevel 	if (getnameinfo((const struct sockaddr *) who, wholen, host_name,
   2882     0    stevel 	    sizeof (host_name), NULL, 0, 0) == 0) {
   2883     0    stevel 		host = host_name;
   2884     0    stevel 	} else {
   2885     0    stevel 		/*
   2886     0    stevel 		 * If the '-U' option was given on the cmd line, we must
   2887     0    stevel 		 * be able to lookup the hostname
   2888     0    stevel 		 */
   2889     0    stevel 		if (resolve_hostname) {
   2890     0    stevel 			fatal(f, "Couldn't resolve your address into a "
   2891     0    stevel 			    "host name.\r\nPlease contact your net "
   2892     0    stevel 			    "administrator");
   2893     0    stevel 		}
   2894     0    stevel 
   2895     0    stevel 		if (who->ss_family == AF_INET6) {
   2896     0    stevel 			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
   2897     0    stevel 				struct in_addr ipv4_addr;
   2898     0    stevel 
   2899     0    stevel 				IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
   2900     0    stevel 				    &ipv4_addr);
   2901     0    stevel 				host = (char *)inet_ntop(AF_INET,
   2902     0    stevel 				    &ipv4_addr, abuf, sizeof (abuf));
   2903     0    stevel 			} else {
   2904     0    stevel 				host = (char *)inet_ntop(AF_INET6,
   2905     0    stevel 				    &sin6->sin6_addr, abuf,
   2906     0    stevel 				    sizeof (abuf));
   2907     0    stevel 			}
   2908     0    stevel 		} else if (who->ss_family == AF_INET) {
   2909     0    stevel 				host = (char *)inet_ntop(AF_INET,
   2910     0    stevel 				    &sin->sin_addr, abuf, sizeof (abuf));
   2911     0    stevel 			}
   2912     0    stevel 	}
   2913     0    stevel 	/*
   2914     0    stevel 	 * Note that sockmod has to be removed since readstream assumes
   2915     0    stevel 	 * a "raw" TPI endpoint (e.g. it uses getmsg).
   2916     0    stevel 	 */
   2917     0    stevel 	if (removemod(f, "sockmod") < 0)
   2918     0    stevel 		fatalperror(f, "couldn't remove sockmod", errno);
   2919     0    stevel 
   2920     0    stevel 	encrypt_init();
   2921     0    stevel 
   2922     0    stevel 	/*
   2923     0    stevel 	 * Push the crypto module on the stream before 'telmod' so it
   2924     0    stevel 	 * can encrypt/decrypt without interfering with telmod functionality
   2925     0    stevel 	 * We must push it now because many of the crypto options negotiated
   2926     0    stevel 	 * initially must be saved in the crypto module (via IOCTL calls).
   2927     0    stevel 	 */
   2928     0    stevel 	if (ioctl(f, I_PUSH, "cryptmod") < 0)
   2929     0    stevel 		fatalperror(f, "ioctl I_PUSH cryptmod", errno);
   2930     0    stevel 
   2931     0    stevel 	cryptmod_fd = f;
   2932     0    stevel 	/*
   2933     0    stevel 	 * gotta set the encryption clock now because it is often negotiated
   2934     0    stevel 	 * immediately by the client, and if we wait till after we negotiate
   2935     0    stevel 	 * auth, it will be out of whack with when the WILL/WONT ENCRYPT
   2936     0    stevel 	 * option is received.
   2937     0    stevel 	 */
   2938     0    stevel 	settimer(getencr);
   2939     0    stevel 
   2940     0    stevel 	/*
   2941     0    stevel 	 * get terminal type.
   2942     0    stevel 	 */
   2943     0    stevel 	username[0] = '\0';
   2944     0    stevel 	len = sizeof (username);
   2945     0    stevel 
   2946     0    stevel 	settimer(getterminal);
   2947     0    stevel 	settimer(getauth);
   2948     0    stevel 	/*
   2949     0    stevel 	 * Exchange TELOPT_AUTHENTICATE options per RFC 2941/2942
   2950     0    stevel 	 */
   2951     0    stevel 	auth_status = getauthtype(username, &len);
   2952     0    stevel 	/*
   2953     0    stevel 	 * Exchange TELOPT_ENCRYPT options per RFC 2946
   2954     0    stevel 	 */
   2955     0    stevel 	getencrtype();
   2956     0    stevel 	getterminaltype();
   2957     0    stevel 
   2958     0    stevel 	if (ioctl(f, I_PUSH, "telmod") < 0)
   2959     0    stevel 		fatalperror(f, "ioctl I_PUSH telmod", errno);
   2960     0    stevel 
   2961     0    stevel 	/*
   2962     0    stevel 	 * Make sure telmod will pass unrecognized IOCTLs to cryptmod
   2963     0    stevel 	 */
   2964     0    stevel 	passthru = 1;
   2965     0    stevel 
   2966     0    stevel 	telnetmod.ic_cmd = CRYPTPASSTHRU;
   2967     0    stevel 	telnetmod.ic_timout = -1;
   2968     0    stevel 	telnetmod.ic_len = sizeof (uchar_t);
   2969     0    stevel 	telnetmod.ic_dp = (char *)&passthru;
   2970     0    stevel 
   2971     0    stevel 	if (ioctl(f, I_STR, &telnetmod) < 0)
   2972     0    stevel 		fatal(f, "ioctl CRPASSTHRU failed\n");
   2973     0    stevel 
   2974     0    stevel 	if (!ncc)
   2975     0    stevel 		netip = netibuf;
   2976     0    stevel 
   2977     0    stevel 	/*
   2978     0    stevel 	 * readstream will do a getmsg till it receives M_PROTO type
   2979     0    stevel 	 * T_DATA_REQ from telnetmodopen().  This signals that all data
   2980     0    stevel 	 * in-flight before telmod was pushed has been received at the
   2981     0    stevel 	 * stream head.
   2982     0    stevel 	 */
   2983     0    stevel 	while ((nsize = readstream(f, netibuf, ncc + netip - netibuf)) > 0) {
   2984     0    stevel 		ncc += nsize;
   2985     0    stevel 	}
   2986     0    stevel 
   2987     0    stevel 	if (nsize < 0) {
   2988     0    stevel 		fatalperror(f, "readstream failed\n", errno);
   2989     0    stevel 	}
   2990     0    stevel 
   2991     0    stevel 	/*
   2992     0    stevel 	 * open logindmux drivers and link them with network and ptm
   2993     0    stevel 	 * file descriptors.
   2994     0    stevel 	 */
   2995     0    stevel 	if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1) {
   2996     0    stevel 		fatalperror(f, "open /dev/logindmux", errno);
   2997     0    stevel 	}
   2998     0    stevel 	if ((netfd = open("/dev/logindmux", O_RDWR)) == -1) {
   2999     0    stevel 		fatalperror(f, "open /dev/logindmux", errno);
   3000     0    stevel 	}
   3001     0    stevel 
   3002     0    stevel 	if (ioctl(ptmfd, I_LINK, p) < 0)
   3003     0    stevel 		fatal(f, "ioctl I_LINK of /dev/ptmx failed\n");
   3004     0    stevel 	if (ioctl(netfd, I_LINK, f) < 0)
   3005     0    stevel 		fatal(f, "ioctl I_LINK of tcp connection failed\n");
   3006     0    stevel 
   3007     0    stevel 	/*
   3008     0    stevel 	 * Figure out the device number of ptm's mux fd, and pass that
   3009     0    stevel 	 * to the net's mux.
   3010     0    stevel 	 */
   3011     0    stevel 	if (fstat(ptmfd, &buf) < 0) {
   3012     0    stevel 		fatalperror(f, "fstat ptmfd failed", errno);
   3013     0    stevel 	}
   3014     0    stevel 	telnetp.dev = buf.st_rdev;
   3015     0    stevel 	telnetp.flag = 0;
   3016     0    stevel 
   3017     0    stevel 	telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
   3018     0    stevel 	telnetmod.ic_timout = -1;
   3019     0    stevel 	telnetmod.ic_len = sizeof (struct protocol_arg);
   3020     0    stevel 	telnetmod.ic_dp = (char *)&telnetp;
   3021     0    stevel 
   3022     0    stevel 	if (ioctl(netfd, I_STR, &telnetmod) < 0)
   3023     0    stevel 		fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");
   3024     0    stevel 
   3025     0    stevel 	/*
   3026     0    stevel 	 * Figure out the device number of the net's mux fd, and pass that
   3027     0    stevel 	 * to the ptm's mux.
   3028     0    stevel 	 */
   3029     0    stevel 	if (fstat(netfd, &buf) < 0) {
   3030     0    stevel 		fatalperror(f, "fstat netfd failed", errno);
   3031     0    stevel 	}
   3032     0    stevel 	telnetp.dev = buf.st_rdev;
   3033     0    stevel 	telnetp.flag = 1;
   3034     0    stevel 
   3035     0    stevel 	telnetmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
   3036     0    stevel 	telnetmod.ic_timout = -1;
   3037     0    stevel 	telnetmod.ic_len = sizeof (struct protocol_arg);
   3038     0    stevel 	telnetmod.ic_dp = (char *)&telnetp;
   3039     0    stevel 
   3040     0    stevel 	if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
   3041     0    stevel 		fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
   3042     0    stevel 
   3043     0    stevel 	net = netfd;
   3044     0    stevel 	master = ptmfd;
   3045     0    stevel 	cryptmod_fd = netfd;
   3046     0    stevel 
   3047     0    stevel 	/*
   3048     0    stevel 	 * Show banner that getty never gave, but
   3049     0    stevel 	 * only if the user did not automatically authenticate.
   3050     0    stevel 	 */
   3051     0    stevel 	if (getenv("USER") == '\0' && auth_status < AUTH_USER)
   3052     0    stevel 		showbanner();
   3053     0    stevel 
   3054     0    stevel 	/*
   3055     0    stevel 	 * If the user automatically authenticated with Kerberos
   3056     0    stevel 	 * we must set the service name that PAM will use.  We
   3057     0    stevel 	 * need to do it BEFORE the child fork so that 'cleanup'
   3058     0    stevel 	 * in the parent can call the PAM cleanup stuff with the
   3059     0    stevel 	 * same PAM service that /bin/login will use to authenticate
   3060     0    stevel 	 * this session.
   3061     0    stevel 	 */
   3062     0    stevel 	if (auth_level >= 0 && auth_status >= AUTH_USER &&
   3063     0    stevel 	    (AuthenticatingUser != NULL) && strlen(AuthenticatingUser)) {
   3064     0    stevel 		(void) strcpy(pam_svc_name, "ktelnet");
   3065     0    stevel 	}
   3066     0    stevel 	/*
   3067     0    stevel 	 * Request to do suppress go ahead.
   3068     0    stevel 	 *
   3069     0    stevel 	 * Send this before sending the TELOPT_ECHO stuff below because
   3070     0    stevel 	 * some clients (MIT KRB5 telnet) have quirky 'kludge mode' support
   3071     0    stevel 	 * that has them turn off local echo mode if SGA is not received first.
   3072     0    stevel 	 * This also has the odd side-effect of causing the client to enable
   3073     0    stevel 	 * encryption and then immediately disable it during the ECHO option
   3074     0    stevel 	 * negotiations.  Its just better to to SGA first now that we support
   3075     0    stevel 	 * encryption.
   3076     0    stevel 	 */
   3077     0    stevel 	if (!myopts[TELOPT_SGA]) {
   3078     0    stevel 	    dooption(TELOPT_SGA);
   3079     0    stevel 	}
   3080     0    stevel 
   3081     0    stevel 	/*
   3082     0    stevel 	 * Pretend we got a DO ECHO from the client if we have not
   3083     0    stevel 	 * yet negotiated the ECHO.
   3084     0    stevel 	 */
   3085     0    stevel 	if (!myopts[TELOPT_ECHO]) {
   3086     0    stevel 	    dooption(TELOPT_ECHO);
   3087     0    stevel 	}
   3088     0    stevel 
   3089     0    stevel 	/*
   3090     0    stevel 	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
   3091     0    stevel 	 * because 4.2 clients are unable to deal with TCP urgent data.
   3092     0    stevel 	 *
   3093     0    stevel 	 * To find out, we send out a "DO ECHO".  If the remote system
   3094     0    stevel 	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
   3095     0    stevel 	 * that fact ("WILL ECHO" ==> that the client will echo what
   3096     0    stevel 	 * WE, the server, sends it; it does NOT mean that the client will
   3097     0    stevel 	 * echo the terminal input).
   3098     0    stevel 	 */
   3099     0    stevel 	send_do(TELOPT_ECHO);
   3100     0    stevel 	remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
   3101     0    stevel 
   3102     0    stevel 	if ((pid = fork()) < 0)
   3103     0    stevel 		fatalperror(netfd, "fork", errno);
   3104     0    stevel 	if (pid)
   3105     0    stevel 		telnet(net, master);
   3106     0    stevel 	/*
   3107     0    stevel 	 * The child process needs to be the session leader
   3108     0    stevel 	 * and have the pty as its controlling tty.  Thus we need
   3109     0    stevel 	 * to re-open the slave side of the pty no without
   3110     0    stevel 	 * the O_NOCTTY flag that we have been careful to
   3111     0    stevel 	 * use up to this point.
   3112     0    stevel 	 */
   3113     0    stevel 	(void) setsid();
   3114     0    stevel 
   3115     0    stevel 	tt = open(line, O_RDWR);
   3116     0    stevel 	if (tt < 0)
   3117     0    stevel 		fatalperror(netfd, line, errno);
   3118     0    stevel 	(void) close(netfd);
   3119     0    stevel 	(void) close(ptmfd);
   3120     0    stevel 	(void) close(f);
   3121     0    stevel 	(void) close(p);
   3122     0    stevel 	(void) close(t);
   3123     0    stevel 	if (tt != 0)
   3124     0    stevel 		(void) dup2(tt, 0);
   3125     0    stevel 	if (tt != 1)
   3126     0    stevel 		(void) dup2(tt, 1);
   3127     0    stevel 	if (tt != 2)
   3128     0    stevel 		(void) dup2(tt, 2);
   3129     0    stevel 	if (tt > 2)
   3130     0    stevel 		(void) close(tt);
   3131     0    stevel 
   3132     0    stevel 	if (terminaltype)
   3133     0    stevel 		(void) local_setenv("TERM", terminaltype+5, 1);
   3134     0    stevel 	/*
   3135     0    stevel 	 * 	-h : pass on name of host.
   3136     0    stevel 	 *		WARNING:  -h is accepted by login if and only if
   3137     0    stevel 	 *			getuid() == 0.
   3138     0    stevel 	 * 	-p : don't clobber the environment (so terminal type stays set).
   3139     0    stevel 	 */
   3140     0    stevel 	{
   3141     0    stevel 		/* System V login expects a utmp entry to already be there */
   3142     0    stevel 		struct utmpx ut;
   3143     0    stevel 		(void) memset((char *)&ut, 0, sizeof (ut));
   3144     0 <