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