Home | History | Annotate | Download | only in telnet
      1 /*
      2  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
      7 
      8 /*
      9  * usr/src/cmd/cmd-inet/usr.bin/telnet/encrypt.c
     10  */
     11 
     12 /*
     13  * Copyright (c) 1991, 1993
     14  *	The Regents of the University of California.  All rights reserved.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  * 1. Redistributions of source code must retain the above copyright
     20  *    notice, this list of conditions and the following disclaimer.
     21  * 2. Redistributions in binary form must reproduce the above copyright
     22  *    notice, this list of conditions and the following disclaimer in the
     23  *    documentation and/or other materials provided with the distribution.
     24  * 3. All advertising materials mentioning features or use of this software
     25  *    must display the following acknowledgement:
     26  *	This product includes software developed by the University of
     27  *	California, Berkeley and its contributors.
     28  * 4. Neither the name of the University nor the names of its contributors
     29  *    may be used to endorse or promote products derived from this software
     30  *    without specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     42  * SUCH DAMAGE.
     43  */
     44 
     45 /* based on @(#)encrypt.c	8.1 (Berkeley) 6/4/93 */
     46 
     47 /*
     48  * Copyright (C) 1990 by the Massachusetts Institute of Technology
     49  *
     50  * Export of this software from the United States of America may
     51  * require a specific license from the United States Government.
     52  * It is the responsibility of any person or organization contemplating
     53  * export to obtain such a license before exporting.
     54  *
     55  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     56  * distribute this software and its documentation for any purpose and
     57  * without fee is hereby granted, provided that the above copyright
     58  * notice appear in all copies and that both that copyright notice and
     59  * this permission notice appear in supporting documentation, and that
     60  * the name of M.I.T. not be used in advertising or publicity pertaining
     61  * to distribution of the software without specific, written prior
     62  * permission.  Furthermore if you modify this software you must label
     63  * your software as modified software and not distribute it in such a
     64  * fashion that it might be confused with the original M.I.T. software.
     65  * M.I.T. makes no representations about the suitability of
     66  * this software for any purpose.  It is provided "as is" without express
     67  * or implied warranty.
     68  */
     69 
     70 #ifdef	lint
     71 static char *encrypt_names[] = {0};
     72 static char *enctype_names[] = {0};
     73 #else	/* lint */
     74 #define	ENCRYPT_NAMES
     75 #endif	/* lint */
     76 #include <arpa/telnet.h>
     77 
     78 #include "externs.h"
     79 
     80 #ifdef	__STDC__
     81 #include <stdlib.h>
     82 #endif
     83 
     84 /*
     85  * These functions pointers point to the current routines
     86  * for encrypting and decrypting data.
     87  */
     88 void	(*encrypt_output)(uchar_t *, int);
     89 int	(*decrypt_input)(int);
     90 static	void encrypt_start_output(int);
     91 static	void encrypt_send_end(void);
     92 static	void encrypt_send_request_start(void);
     93 static	void encrypt_send_request_end(void);
     94 
     95 boolean_t	encrypt_debug_mode = B_FALSE;
     96 
     97 static int decrypt_mode = 0;
     98 static int encrypt_mode = 0;
     99 static boolean_t encrypt_verbose = B_FALSE;
    100 static boolean_t autoencrypt = B_FALSE;
    101 static boolean_t autodecrypt = B_FALSE;
    102 static char *Name = "Noname";
    103 
    104 #define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
    105 #define	SUCCESS		0x00
    106 #define	UNKNOWN		gettext("(unknown)")
    107 
    108 static int i_support_encrypt = typemask(TELOPT_ENCTYPE_DES_CFB64);
    109 static int i_support_decrypt = typemask(TELOPT_ENCTYPE_DES_CFB64);
    110 static int i_wont_support_encrypt = 0;
    111 static int i_wont_support_decrypt = 0;
    112 #define	I_SUPPORT_ENCRYPT	(i_support_encrypt & ~i_wont_support_encrypt)
    113 #define	I_SUPPORT_DECRYPT	(i_support_decrypt & ~i_wont_support_decrypt)
    114 
    115 static int remote_supports_encrypt = 0;
    116 static int remote_supports_decrypt = 0;
    117 
    118 static Encryptions encryptions[] = {
    119 	{ "DES_CFB64",	TELOPT_ENCTYPE_DES_CFB64,
    120 			cfb64_encrypt,
    121 			cfb64_decrypt,
    122 			cfb64_init,
    123 			cfb64_start,
    124 			cfb64_is,
    125 			cfb64_reply,
    126 			cfb64_session,
    127 			cfb64_keyid,
    128 			cfb64_printsub },
    129 	{ 0, },
    130 };
    131 
    132 static uchar_t str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
    133 	ENCRYPT_SUPPORT };
    134 static uchar_t str_suplen = 0;
    135 static uchar_t str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
    136 static uchar_t str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
    137 
    138 static Encryptions *
    139 findencryption(int type)
    140 {
    141 	Encryptions *ep = encryptions;
    142 
    143 	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
    144 		return (NULL);
    145 	for (; (ep->type != NULL) && (ep->type != type); ep++);
    146 	return (ep->type ? ep : NULL);
    147 }
    148 
    149 static Encryptions *
    150 finddecryption(int type)
    151 {
    152 	Encryptions *ep = encryptions;
    153 
    154 	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
    155 		return (NULL);
    156 	while (ep->type && ep->type != type)
    157 		++ep;
    158 	return (ep->type ? ep : NULL);
    159 }
    160 
    161 #define	MAXKEYLEN 64
    162 
    163 static struct key_info {
    164 	uchar_t keyid[MAXKEYLEN];
    165 	int keylen;
    166 	int dir;
    167 	int *modep;
    168 	Encryptions *(*getcrypt)();
    169 } ki[2] = {
    170 	{ { 0 }, 0, TELNET_DIR_ENCRYPT, &encrypt_mode, findencryption },
    171 	{ { 0 }, 0, TELNET_DIR_DECRYPT, &decrypt_mode, finddecryption },
    172 };
    173 #define	KI_ENCRYPT	0
    174 #define	KI_DECRYPT	1
    175 
    176 void
    177 encrypt_init(char *name)
    178 {
    179 	Encryptions *ep = encryptions;
    180 
    181 	Name = name;
    182 	i_support_encrypt = i_support_decrypt = 0;
    183 	remote_supports_encrypt = remote_supports_decrypt = 0;
    184 	encrypt_mode = 0;
    185 	decrypt_mode = 0;
    186 	encrypt_output = 0;
    187 	decrypt_input = 0;
    188 #ifdef notdef
    189 	encrypt_verbose = !server;
    190 #endif
    191 
    192 	str_suplen = 4;
    193 
    194 	while (ep->type) {
    195 		if (encrypt_debug_mode)
    196 			(void) printf(gettext(
    197 				">>>%s: I will support %s\r\n"),
    198 				Name, ENCTYPE_NAME(ep->type));
    199 		i_support_encrypt |= typemask(ep->type);
    200 		i_support_decrypt |= typemask(ep->type);
    201 		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
    202 			if ((str_send[str_suplen++] = ep->type) == IAC)
    203 				str_send[str_suplen++] = IAC;
    204 		if (ep->init)
    205 			(*ep->init)();
    206 		++ep;
    207 	}
    208 	str_send[str_suplen++] = IAC;
    209 	str_send[str_suplen++] = SE;
    210 }
    211 
    212 static void
    213 encrypt_list_types(void)
    214 {
    215 	Encryptions *ep = encryptions;
    216 
    217 	(void) printf(gettext("Valid encryption types:\n"));
    218 	while (ep->type) {
    219 		(void) printf("\t%s (%d)\r\n",
    220 			ENCTYPE_NAME(ep->type), ep->type);
    221 		++ep;
    222 	}
    223 }
    224 
    225 int
    226 EncryptEnable(char *type, char *mode)
    227 {
    228 	if (isprefix(type, "help") || isprefix(type, "?")) {
    229 		(void) printf(gettext(
    230 			"Usage: encrypt enable <type> [input|output]\n"));
    231 		encrypt_list_types();
    232 		return (0);
    233 	}
    234 
    235 	if (EncryptType(type, mode))
    236 		return (EncryptStart(mode));
    237 
    238 	return (0);
    239 }
    240 
    241 int
    242 EncryptDisable(char *type, char *mode)
    243 {
    244 	register Encryptions *ep;
    245 	int ret = 0;
    246 
    247 	if (isprefix(type, "help") || isprefix(type, "?")) {
    248 		(void) printf(gettext(
    249 			"Usage: encrypt disable <type> [input|output]\n"));
    250 		encrypt_list_types();
    251 	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
    252 						sizeof (Encryptions))) == 0) {
    253 		(void) printf(gettext("%s: invalid encryption type\n"), type);
    254 	} else if (Ambiguous(ep)) {
    255 		(void) printf(gettext("Ambiguous type '%s'\n"), type);
    256 	} else {
    257 		if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
    258 			if (decrypt_mode == ep->type)
    259 				(void) EncryptStopInput();
    260 			i_wont_support_decrypt |= typemask(ep->type);
    261 			ret = 1;
    262 		}
    263 		if ((mode == 0) || (isprefix(mode, "output"))) {
    264 			if (encrypt_mode == ep->type)
    265 				(void) EncryptStopOutput();
    266 			i_wont_support_encrypt |= typemask(ep->type);
    267 			ret = 1;
    268 		}
    269 		if (ret == 0)
    270 			(void) printf(gettext(
    271 				"%s: invalid encryption mode\n"), mode);
    272 	}
    273 	return (ret);
    274 }
    275 
    276 int
    277 EncryptType(char *type, char *mode)
    278 {
    279 	register Encryptions *ep;
    280 	int ret = 0;
    281 
    282 	if (isprefix(type, "help") || isprefix(type, "?")) {
    283 		(void) printf(gettext(
    284 			"Usage: encrypt type <type> [input|output]\n"));
    285 		encrypt_list_types();
    286 	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
    287 						sizeof (Encryptions))) == 0) {
    288 		(void) printf(gettext("%s: invalid encryption type\n"), type);
    289 	} else if (Ambiguous(ep)) {
    290 		(void) printf(gettext("Ambiguous type '%s'\n"), type);
    291 	} else {
    292 		if ((mode == 0) || isprefix(mode, "input")) {
    293 			decrypt_mode = ep->type;
    294 			i_wont_support_decrypt &= ~typemask(ep->type);
    295 			ret = 1;
    296 		}
    297 		if ((mode == 0) || isprefix(mode, "output")) {
    298 			encrypt_mode = ep->type;
    299 			i_wont_support_encrypt &= ~typemask(ep->type);
    300 			ret = 1;
    301 		}
    302 		if (ret == 0)
    303 			(void) printf(gettext(
    304 				"%s: invalid encryption mode\n"), mode);
    305 	}
    306 	return (ret);
    307 }
    308 
    309 int
    310 EncryptStart(char *mode)
    311 {
    312 	register int ret = 0;
    313 	if (mode) {
    314 		if (isprefix(mode, "input"))
    315 			return (EncryptStartInput());
    316 		if (isprefix(mode, "output"))
    317 			return (EncryptStartOutput());
    318 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
    319 			(void) printf(gettext(
    320 				"Usage: encrypt start [input|output]\n"));
    321 			return (0);
    322 		}
    323 		(void) printf(gettext(
    324 			"%s: invalid encryption mode 'encrypt start ?' "
    325 			"for help\n"), mode);
    326 		return (0);
    327 	}
    328 	ret += EncryptStartInput();
    329 	ret += EncryptStartOutput();
    330 	return (ret);
    331 }
    332 
    333 int
    334 EncryptStartInput(void)
    335 {
    336 	if (decrypt_mode) {
    337 		encrypt_send_request_start();
    338 		return (1);
    339 	}
    340 	(void) printf(gettext("No previous decryption mode, "
    341 		"decryption not enabled\r\n"));
    342 	return (0);
    343 }
    344 
    345 int
    346 EncryptStartOutput(void)
    347 {
    348 	if (encrypt_mode) {
    349 		encrypt_start_output(encrypt_mode);
    350 		return (1);
    351 	}
    352 	(void) printf(gettext("No previous encryption mode, "
    353 		"encryption not enabled\r\n"));
    354 	return (0);
    355 }
    356 
    357 int
    358 EncryptStop(char *mode)
    359 {
    360 	int ret = 0;
    361 	if (mode) {
    362 		if (isprefix(mode, "input"))
    363 			return (EncryptStopInput());
    364 		if (isprefix(mode, "output"))
    365 			return (EncryptStopOutput());
    366 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
    367 			(void) printf(gettext(
    368 				"Usage: encrypt stop [input|output]\n"));
    369 			return (0);
    370 		}
    371 		(void) printf(gettext(
    372 			"%s: invalid encryption mode 'encrypt stop ?' "
    373 			"for help\n"), mode);
    374 		return (0);
    375 	}
    376 	ret += EncryptStopInput();
    377 	ret += EncryptStopOutput();
    378 	return (ret);
    379 }
    380 
    381 int
    382 EncryptStopInput(void)
    383 {
    384 	encrypt_send_request_end();
    385 	return (1);
    386 }
    387 
    388 int
    389 EncryptStopOutput(void)
    390 {
    391 	encrypt_send_end();
    392 	return (1);
    393 }
    394 
    395 void
    396 encrypt_display(void)
    397 {
    398 	if (encrypt_output)
    399 		(void) printf(gettext(
    400 			"Currently encrypting output with %s\r\n"),
    401 			ENCTYPE_NAME(encrypt_mode));
    402 	if (decrypt_input)
    403 		(void) printf(gettext(
    404 			"Currently decrypting input with %s\r\n"),
    405 			ENCTYPE_NAME(decrypt_mode));
    406 }
    407 
    408 int
    409 EncryptStatus(void)
    410 {
    411 	if (encrypt_output)
    412 		(void) printf(gettext(
    413 			"Currently encrypting output with %s\r\n"),
    414 			ENCTYPE_NAME(encrypt_mode));
    415 	else if (encrypt_mode) {
    416 		(void) printf(gettext("Currently output is clear text.\r\n"));
    417 		(void) printf(gettext("Last encryption mode was %s\r\n"),
    418 			ENCTYPE_NAME(encrypt_mode));
    419 	}
    420 	if (decrypt_input) {
    421 		(void) printf(gettext(
    422 			"Currently decrypting input with %s\r\n"),
    423 			ENCTYPE_NAME(decrypt_mode));
    424 	} else if (decrypt_mode) {
    425 		(void) printf(gettext("Currently input is clear text.\r\n"));
    426 		(void) printf(gettext("Last decryption mode was %s\r\n"),
    427 			ENCTYPE_NAME(decrypt_mode));
    428 	}
    429 	return (1);
    430 }
    431 
    432 void
    433 encrypt_send_support(void)
    434 {
    435 	if (str_suplen) {
    436 		/*
    437 		 * If the user has requested that decryption start
    438 		 * immediatly, then send a "REQUEST START" before
    439 		 * we negotiate the type.
    440 		 */
    441 		if (autodecrypt)
    442 			encrypt_send_request_start();
    443 		(void) net_write(str_send, str_suplen);
    444 		printsub('>', &str_send[2], str_suplen - 2);
    445 		str_suplen = 0;
    446 	}
    447 }
    448 
    449 int
    450 EncryptDebug(int on)
    451 {
    452 	encrypt_debug_mode = (on < 0) ? !encrypt_debug_mode :
    453 		(on > 0) ? B_TRUE : B_FALSE;
    454 	(void) printf(encrypt_debug_mode ?
    455 		gettext("Encryption debugging enabled\r\n") :
    456 		gettext("Encryption debugging disabled\r\n"));
    457 	return (1);
    458 }
    459 
    460 int
    461 EncryptVerbose(int on)
    462 {
    463 	encrypt_verbose = (on < 0) ? !encrypt_verbose :
    464 		(on > 0) ? B_TRUE : B_FALSE;
    465 	(void) printf(encrypt_verbose ?
    466 		gettext("Encryption is verbose\r\n") :
    467 		gettext("Encryption is not verbose\r\n"));
    468 	return (1);
    469 }
    470 
    471 int
    472 EncryptAutoEnc(int on)
    473 {
    474 	encrypt_auto(on);
    475 	(void) printf(autoencrypt ?
    476 		gettext("Automatic encryption of output is enabled\r\n") :
    477 		gettext("Automatic encryption of output is disabled\r\n"));
    478 	return (1);
    479 }
    480 
    481 int
    482 EncryptAutoDec(int on)
    483 {
    484 	decrypt_auto(on);
    485 	(void) printf(autodecrypt ?
    486 		gettext("Automatic decryption of input is enabled\r\n") :
    487 		gettext("Automatic decryption of input is disabled\r\n"));
    488 	return (1);
    489 }
    490 
    491 /*
    492  * Called when ENCRYPT SUPPORT is received.
    493  */
    494 void
    495 encrypt_support(uchar_t *typelist, int cnt)
    496 {
    497 	register int type, use_type = 0;
    498 	Encryptions *ep;
    499 
    500 	/*
    501 	 * Forget anything the other side has previously told us.
    502 	 */
    503 	remote_supports_decrypt = 0;
    504 
    505 	while (cnt-- > 0) {
    506 		type = *typelist++;
    507 		if (encrypt_debug_mode)
    508 			(void) printf(gettext(
    509 				">>>%s: Remote host supports %s (%d)\r\n"),
    510 				Name, ENCTYPE_NAME(type), type);
    511 		if ((type < TELOPT_ENCTYPE_CNT) &&
    512 		    (I_SUPPORT_ENCRYPT & typemask(type))) {
    513 			remote_supports_decrypt |= typemask(type);
    514 			if (use_type == 0)
    515 				use_type = type;
    516 		}
    517 	}
    518 	if (use_type) {
    519 		ep = findencryption(use_type);
    520 		if (!ep)
    521 			return;
    522 		type = ep->start ? (*ep->start)(TELNET_DIR_ENCRYPT) : 0;
    523 		if (encrypt_debug_mode)
    524 			(void) printf(gettext(
    525 				">>>%s: (*ep->start)() returned %d\r\n"),
    526 				Name, type);
    527 		if (type < 0)
    528 			return;
    529 		encrypt_mode = use_type;
    530 		if (type == 0)
    531 			encrypt_start_output(use_type);
    532 	}
    533 }
    534 
    535 void
    536 encrypt_is(uchar_t *data, int cnt)
    537 {
    538 	Encryptions *ep;
    539 	register int type, ret;
    540 
    541 	if (--cnt < 0)
    542 		return;
    543 	type = *data++;
    544 	if (type < TELOPT_ENCTYPE_CNT)
    545 		remote_supports_encrypt |= typemask(type);
    546 	if (!(ep = finddecryption(type))) {
    547 		if (encrypt_debug_mode)
    548 			(void) printf(gettext(
    549 				">>>%s: Can't find type %s (%d) for "
    550 				"initial negotiation\r\n"), Name,
    551 				ENCTYPE_NAME_OK(type) ?
    552 				ENCTYPE_NAME(type) : UNKNOWN, type);
    553 		return;
    554 	}
    555 	if (!ep->is) {
    556 		if (encrypt_debug_mode)
    557 			(void) printf(gettext(
    558 				">>>%s: No initial negotiation needed "
    559 				"for type %s (%d)\r\n"), Name,
    560 				ENCTYPE_NAME_OK(type) ?
    561 				ENCTYPE_NAME(type) : UNKNOWN, type);
    562 		ret = 0;
    563 	} else {
    564 		ret = (*ep->is)(data, cnt);
    565 		if (encrypt_debug_mode)
    566 			(void) printf(gettext(
    567 				"(*ep->is)(%x, %d) returned %s(%d)\n"),
    568 				data, cnt, (ret < 0) ? "FAIL " :
    569 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
    570 	}
    571 	if (ret < 0) {
    572 		autodecrypt = B_FALSE;
    573 	} else {
    574 		decrypt_mode = type;
    575 		if (ret == 0 && autodecrypt)
    576 			encrypt_send_request_start();
    577 	}
    578 }
    579 
    580 void
    581 encrypt_reply(uchar_t *data, int cnt)
    582 {
    583 	Encryptions *ep;
    584 	register int ret, type;
    585 
    586 	if (--cnt < 0)
    587 		return;
    588 	type = *data++;
    589 	if (!(ep = findencryption(type))) {
    590 		if (encrypt_debug_mode)
    591 			(void) printf(gettext(
    592 				">>>%s: Can't find type %s (%d) "
    593 				"for initial negotiation\r\n"), Name,
    594 				ENCTYPE_NAME_OK(type) ?
    595 				ENCTYPE_NAME(type) : UNKNOWN, type);
    596 		return;
    597 	}
    598 	if (!ep->reply) {
    599 		if (encrypt_debug_mode)
    600 			(void) printf(gettext(
    601 				">>>%s: No initial negotiation needed "
    602 				"for type %s (%d)\r\n"), Name,
    603 				ENCTYPE_NAME_OK(type) ?
    604 				ENCTYPE_NAME(type) : UNKNOWN, type);
    605 		ret = 0;
    606 	} else {
    607 		ret = (*ep->reply)(data, cnt);
    608 		if (encrypt_debug_mode)
    609 			(void) printf(gettext(
    610 				"(*ep->reply)(%x, %d) returned %s(%d)\n"),
    611 				data, cnt, (ret < 0) ? "FAIL " :
    612 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
    613 	}
    614 	if (encrypt_debug_mode)
    615 		(void) printf(gettext(
    616 			">>>%s: encrypt_reply returned %d\n"), Name, ret);
    617 	if (ret < 0) {
    618 		autoencrypt = B_FALSE;
    619 	} else {
    620 		encrypt_mode = type;
    621 		if (ret == 0 && autoencrypt)
    622 			encrypt_start_output(type);
    623 	}
    624 }
    625 
    626 /*
    627  * Called when a ENCRYPT START command is received.
    628  */
    629 /* ARGSUSED */
    630 void
    631 encrypt_start(uchar_t *data, int cnt)
    632 {
    633 	Encryptions *ep;
    634 
    635 	if (!decrypt_mode) {
    636 		/*
    637 		 * Something is wrong.  We should not get a START
    638 		 * command without having already picked our
    639 		 * decryption scheme.  Send a REQUEST-END to
    640 		 * attempt to clear the channel...
    641 		 */
    642 		(void) printf(gettext("%s: Warning, cannot decrypt "
    643 			"input stream!!!\r\n"), Name);
    644 		encrypt_send_request_end();
    645 		return;
    646 	}
    647 
    648 	if (ep = finddecryption(decrypt_mode)) {
    649 		decrypt_input = ep->input;
    650 		if (encrypt_verbose)
    651 			(void) printf(gettext(
    652 			    "[ Input is now decrypted with type %s ]\r\n"),
    653 			    ENCTYPE_NAME(decrypt_mode));
    654 		if (encrypt_debug_mode)
    655 			(void) printf(gettext(
    656 			    ">>>%s: Start to decrypt input with type %s\r\n"),
    657 			    Name, ENCTYPE_NAME(decrypt_mode));
    658 	} else {
    659 		(void) printf(gettext(
    660 			    "%s: Warning, cannot decrypt type %s (%d)!!!\r\n"),
    661 			    Name, ENCTYPE_NAME_OK(decrypt_mode) ?
    662 			    ENCTYPE_NAME(decrypt_mode) : UNKNOWN,
    663 			    decrypt_mode);
    664 		encrypt_send_request_end();
    665 	}
    666 }
    667 
    668 void
    669 encrypt_session_key(Session_Key *key)
    670 {
    671 	Encryptions *ep = encryptions;
    672 
    673 	while (ep->type) {
    674 		if (ep->session)
    675 			(*ep->session)(key);
    676 #ifdef notdef
    677 		if (!encrypt_output && autoencrypt)
    678 			encrypt_start_output(ep->type);
    679 		if (!decrypt_input && autodecrypt)
    680 			encrypt_send_request_start();
    681 #endif
    682 		++ep;
    683 	}
    684 }
    685 
    686 /*
    687  * Called when ENCRYPT END is received.
    688  */
    689 void
    690 encrypt_end(void)
    691 {
    692 	decrypt_input = 0;
    693 	if (encrypt_debug_mode)
    694 		(void) printf(gettext(
    695 			">>>%s: Input is back to clear text\r\n"), Name);
    696 	if (encrypt_verbose)
    697 		(void) printf(gettext("[ Input is now clear text ]\r\n"));
    698 }
    699 
    700 /*
    701  * Called when ENCRYPT REQUEST-END is received.
    702  */
    703 void
    704 encrypt_request_end(void)
    705 {
    706 	encrypt_send_end();
    707 }
    708 
    709 /*
    710  * Called when ENCRYPT REQUEST-START is received.  If we receive
    711  * this before a type is picked, then that indicates that the
    712  * other side wants us to start encrypting data as soon as we
    713  * can.
    714  */
    715 /* ARGSUSED */
    716 void
    717 encrypt_request_start(uchar_t *data, int cnt)
    718 {
    719 	if (encrypt_mode == 0)
    720 		return;
    721 	encrypt_start_output(encrypt_mode);
    722 }
    723 
    724 static	uchar_t str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
    725 static	void encrypt_keyid(struct key_info *, uchar_t *, int);
    726 
    727 void
    728 encrypt_enc_keyid(uchar_t *keyid, int len)
    729 {
    730 	encrypt_keyid(&ki[KI_DECRYPT], keyid, len);
    731 }
    732 
    733 void
    734 encrypt_dec_keyid(uchar_t *keyid, int len)
    735 {
    736 	encrypt_keyid(&ki[KI_ENCRYPT], keyid, len);
    737 }
    738 
    739 static void
    740 encrypt_keyid(struct key_info *kp, uchar_t *keyid, int len)
    741 {
    742 	Encryptions *ep;
    743 	int dir = kp->dir;
    744 	register int ret = 0;
    745 
    746 	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
    747 		if (len == 0)
    748 			return;
    749 		kp->keylen = 0;
    750 	} else if (len == 0) {
    751 		/*
    752 		 * Empty option, indicates a failure.
    753 		 */
    754 		if (kp->keylen == 0)
    755 			return;
    756 		kp->keylen = 0;
    757 		if (ep->keyid)
    758 			(void) (*ep->keyid)(dir, kp->keyid, &kp->keylen);
    759 
    760 	} else if ((len != kp->keylen) ||
    761 		(memcmp(keyid, kp->keyid, len) != 0)) {
    762 		/*
    763 		 * Length or contents are different
    764 		 */
    765 		kp->keylen = len;
    766 		(void) memcpy(kp->keyid, keyid, len);
    767 		if (ep->keyid)
    768 			(void) (*ep->keyid)(dir, kp->keyid, &kp->keylen);
    769 	} else {
    770 		if (ep->keyid)
    771 			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
    772 		if ((ret == 0) && (dir == TELNET_DIR_ENCRYPT) && autoencrypt)
    773 			encrypt_start_output(*kp->modep);
    774 		return;
    775 	}
    776 
    777 	encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
    778 }
    779 
    780 void
    781 encrypt_send_keyid(int dir, uchar_t *keyid, int keylen, int saveit)
    782 {
    783 	uchar_t *strp;
    784 
    785 	str_keyid[3] = (dir == TELNET_DIR_ENCRYPT)
    786 			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
    787 	if (saveit) {
    788 		struct key_info *kp = &ki[(dir == TELNET_DIR_ENCRYPT) ? 0 : 1];
    789 		(void) memcpy(kp->keyid, keyid, keylen);
    790 		kp->keylen = keylen;
    791 	}
    792 
    793 	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
    794 		if ((*strp++ = *keyid++) == IAC)
    795 			*strp++ = IAC;
    796 	}
    797 	*strp++ = IAC;
    798 	*strp++ = SE;
    799 	(void) net_write(str_keyid, strp - str_keyid);
    800 	printsub('>', &str_keyid[2], strp - str_keyid - 2);
    801 }
    802 
    803 void
    804 encrypt_auto(int on)
    805 {
    806 	autoencrypt = (on < 0) ? !autoencrypt :
    807 		(on > 0) ? B_TRUE : B_FALSE;
    808 }
    809 
    810 void
    811 decrypt_auto(int on)
    812 {
    813 	autodecrypt = (on < 0) ? !autodecrypt :
    814 		(on > 0) ? B_TRUE : B_FALSE;
    815 }
    816 
    817 static void
    818 encrypt_start_output(int type)
    819 {
    820 	Encryptions *ep;
    821 	register uchar_t *p;
    822 	register int i;
    823 
    824 	if (!(ep = findencryption(type))) {
    825 		if (encrypt_debug_mode) {
    826 		    (void) printf(gettext(
    827 			">>>%s: Can't encrypt with type %s (%d)\r\n"),
    828 			Name, ENCTYPE_NAME_OK(type) ?
    829 			ENCTYPE_NAME(type) : UNKNOWN, type);
    830 		}
    831 		return;
    832 	}
    833 	if (ep->start) {
    834 		i = (*ep->start)(TELNET_DIR_ENCRYPT);
    835 		if (encrypt_debug_mode) {
    836 		    (void) printf(gettext(
    837 			">>>%s: Encrypt start: %s (%d) %s\r\n"),
    838 			Name, (i < 0) ?
    839 			gettext("failed") :
    840 			gettext("initial negotiation in progress"),
    841 			i, ENCTYPE_NAME(type));
    842 		}
    843 		if (i)
    844 			return;
    845 	}
    846 	p = str_start + 3;
    847 	*p++ = ENCRYPT_START;
    848 	for (i = 0; i < ki[KI_ENCRYPT].keylen; ++i) {
    849 		if ((*p++ = ki[KI_ENCRYPT].keyid[i]) == IAC)
    850 			*p++ = IAC;
    851 	}
    852 	*p++ = IAC;
    853 	*p++ = SE;
    854 	(void) net_write(str_start, p - str_start);
    855 	net_encrypt();
    856 	printsub('>', &str_start[2], p - &str_start[2]);
    857 	/*
    858 	 * If we are already encrypting in some mode, then
    859 	 * encrypt the ring (which includes our request) in
    860 	 * the old mode, mark it all as "clear text" and then
    861 	 * switch to the new mode.
    862 	 */
    863 	encrypt_output = ep->output;
    864 	encrypt_mode = type;
    865 	if (encrypt_debug_mode)
    866 	    (void) printf(gettext(
    867 		">>>%s: Started to encrypt output with type %s\r\n"),
    868 		Name, ENCTYPE_NAME(type));
    869 	if (encrypt_verbose)
    870 	    (void) printf(gettext(
    871 		"[ Output is now encrypted with type %s ]\r\n"),
    872 		ENCTYPE_NAME(type));
    873 }
    874 
    875 static void
    876 encrypt_send_end(void)
    877 {
    878 	if (!encrypt_output)
    879 		return;
    880 
    881 	str_end[3] = ENCRYPT_END;
    882 	(void) net_write(str_end, sizeof (str_end));
    883 	net_encrypt();
    884 	printsub('>', &str_end[2], sizeof (str_end) - 2);
    885 	/*
    886 	 * Encrypt the output buffer now because it will not be done by
    887 	 * netflush...
    888 	 */
    889 	encrypt_output = 0;
    890 	if (encrypt_debug_mode)
    891 	    (void) printf(gettext(
    892 		">>>%s: Output is back to clear text\r\n"), Name);
    893 	if (encrypt_verbose)
    894 	    (void) printf(gettext("[ Output is now clear text ]\r\n"));
    895 }
    896 
    897 static void
    898 encrypt_send_request_start(void)
    899 {
    900 	register uchar_t *p;
    901 	register int i;
    902 
    903 	p = &str_start[3];
    904 	*p++ = ENCRYPT_REQSTART;
    905 	for (i = 0; i < ki[KI_DECRYPT].keylen; ++i) {
    906 		if ((*p++ = ki[KI_DECRYPT].keyid[i]) == IAC)
    907 			*p++ = IAC;
    908 	}
    909 	*p++ = IAC;
    910 	*p++ = SE;
    911 	(void) net_write(str_start, p - str_start);
    912 	printsub('>', &str_start[2], p - &str_start[2]);
    913 	if (encrypt_debug_mode)
    914 	    (void) printf(gettext(
    915 		">>>%s: Request input to be encrypted\r\n"), Name);
    916 }
    917 
    918 static void
    919 encrypt_send_request_end(void)
    920 {
    921 	str_end[3] = ENCRYPT_REQEND;
    922 	(void) net_write(str_end, sizeof (str_end));
    923 	printsub('>', &str_end[2], sizeof (str_end) - 2);
    924 
    925 	if (encrypt_debug_mode)
    926 	    (void) printf(gettext(
    927 		">>>%s: Request input to be clear text\r\n"), Name);
    928 }
    929 
    930 boolean_t
    931 encrypt_is_encrypting(void)
    932 {
    933 	return (encrypt_output && decrypt_input ? B_TRUE : B_FALSE);
    934 }
    935 
    936 static void
    937 encrypt_gen_printsub(uchar_t *data, int cnt, uchar_t *buf, int buflen)
    938 {
    939 	char lbuf[ENCR_LBUF_BUFSIZ], *cp;
    940 
    941 	if (cnt < 2 || buflen < 2)
    942 		return;
    943 	cnt -= 2;
    944 	data += 2;
    945 	buf[buflen-1] = '\0';
    946 	buf[buflen-2] = '*';
    947 	buflen -= 2;
    948 	for (; cnt > 0; cnt--, data++) {
    949 		(void) snprintf(lbuf, ENCR_LBUF_BUFSIZ, " %d", *data);
    950 		for (cp = lbuf; *cp && buflen > 0; --buflen)
    951 			*buf++ = *cp++;
    952 		if (buflen <= 0)
    953 			return;
    954 	}
    955 	*buf = '\0';
    956 }
    957 
    958 void
    959 encrypt_printsub(uchar_t *data, int cnt, uchar_t *buf, int buflen)
    960 {
    961 	Encryptions *ep;
    962 	register int type = data[1];
    963 
    964 	for (ep = encryptions; ep->type && ep->type != type; ep++)
    965 		;
    966 
    967 	if (ep->printsub)
    968 		(*ep->printsub)(data, cnt, buf, buflen);
    969 	else
    970 		encrypt_gen_printsub(data, cnt, buf, buflen);
    971 }
    972