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