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