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