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