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