xref: /netbsd/lib/libtelnet/encrypt.c (revision 6550d01e)
1 /*	$NetBSD: encrypt.c,v 1.14 2007/01/17 23:24:22 hubertf 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.14 2007/01/17 23:24:22 hubertf 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     { 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(type)
140 	int type;
141 {
142 	Encryptions *ep = encryptions;
143 
144 	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
145 		return(0);
146 	while (ep->type && ep->type != type)
147 		++ep;
148 	return(ep->type ? ep : 0);
149 }
150 
151 	Encryptions *
152 finddecryption(type)
153 	int type;
154 {
155 	Encryptions *ep = encryptions;
156 
157 	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
158 		return(0);
159 	while (ep->type && ep->type != type)
160 		++ep;
161 	return(ep->type ? ep : 0);
162 }
163 
164 #define	MAXKEYLEN 64
165 
166 static struct key_info {
167 	unsigned char keyid[MAXKEYLEN];
168 	int keylen;
169 	int dir;
170 	int *modep;
171 	Encryptions *(*getcrypt)(int);
172 } ki[2] = {
173 	{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
174 	{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
175 };
176 
177 	void
178 encrypt_init(name, server)
179 	const char *name;
180 	int server;
181 {
182 	Encryptions *ep = encryptions;
183 
184 	Name = name;
185 	Server = server;
186 	i_support_encrypt = i_support_decrypt = 0;
187 	remote_supports_encrypt = remote_supports_decrypt = 0;
188 	encrypt_mode = 0;
189 	decrypt_mode = 0;
190 	encrypt_output = 0;
191 	decrypt_input = 0;
192 #ifdef notdef
193 	encrypt_verbose = !server;
194 #endif
195 
196 	str_suplen = 4;
197 
198 	while (ep->type) {
199 		if (encrypt_debug_mode)
200 			printf(">>>%s: I will support %s\r\n",
201 				Name, ENCTYPE_NAME(ep->type));
202 		i_support_encrypt |= typemask(ep->type);
203 		i_support_decrypt |= typemask(ep->type);
204 		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
205 			if ((str_send[str_suplen++] = ep->type) == IAC)
206 				str_send[str_suplen++] = IAC;
207 		if (ep->init)
208 			(*ep->init)(Server);
209 		++ep;
210 	}
211 	str_send[str_suplen++] = IAC;
212 	str_send[str_suplen++] = SE;
213 }
214 
215 	void
216 encrypt_list_types()
217 {
218 	Encryptions *ep = encryptions;
219 
220 	printf("Valid encryption types:\n");
221 	while (ep->type) {
222 		printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
223 		++ep;
224 	}
225 }
226 
227 	int
228 EncryptEnable(type, mode)
229 	char *type, *mode;
230 {
231 	if (isprefix(type, "help") || isprefix(type, "?")) {
232 		printf("Usage: encrypt enable <type> [input|output]\n");
233 		encrypt_list_types();
234 		return(0);
235 	}
236 	if (EncryptType(type, mode))
237 		return(EncryptStart(mode));
238 	return(0);
239 }
240 
241 	int
242 EncryptDisable(type, mode)
243 	char *type, *mode;
244 {
245 	register Encryptions *ep;
246 	int ret = 0;
247 
248 	if (isprefix(type, "help") || isprefix(type, "?")) {
249 		printf("Usage: encrypt disable <type> [input|output]\n");
250 		encrypt_list_types();
251 	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
252 						sizeof(Encryptions))) == 0) {
253 		printf("%s: invalid encryption type\n", type);
254 	} else if (Ambiguous(ep)) {
255 		printf("Ambiguous type '%s'\n", type);
256 	} else {
257 		if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
258 			if (decrypt_mode == ep->type)
259 				EncryptStopInput();
260 			i_wont_support_decrypt |= typemask(ep->type);
261 			ret = 1;
262 		}
263 		if ((mode == 0) || (isprefix(mode, "output"))) {
264 			if (encrypt_mode == ep->type)
265 				EncryptStopOutput();
266 			i_wont_support_encrypt |= typemask(ep->type);
267 			ret = 1;
268 		}
269 		if (ret == 0)
270 			printf("%s: invalid encryption mode\n", mode);
271 	}
272 	return(ret);
273 }
274 
275 	int
276 EncryptType(type, mode)
277 	char *type;
278 	char *mode;
279 {
280 	register Encryptions *ep;
281 	int ret = 0;
282 
283 	if (isprefix(type, "help") || isprefix(type, "?")) {
284 		printf("Usage: encrypt type <type> [input|output]\n");
285 		encrypt_list_types();
286 	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
287 						sizeof(Encryptions))) == 0) {
288 		printf("%s: invalid encryption type\n", type);
289 	} else if (Ambiguous(ep)) {
290 		printf("Ambiguous type '%s'\n", type);
291 	} else {
292 		if ((mode == 0) || isprefix(mode, "input")) {
293 			decrypt_mode = ep->type;
294 			i_wont_support_decrypt &= ~typemask(ep->type);
295 			ret = 1;
296 		}
297 		if ((mode == 0) || isprefix(mode, "output")) {
298 			encrypt_mode = ep->type;
299 			i_wont_support_encrypt &= ~typemask(ep->type);
300 			ret = 1;
301 		}
302 		if (ret == 0)
303 			printf("%s: invalid encryption mode\n", mode);
304 	}
305 	return(ret);
306 }
307 
308 	int
309 EncryptStart(mode)
310 	char *mode;
311 {
312 	register int ret = 0;
313 	if (mode) {
314 		if (isprefix(mode, "input"))
315 			return(EncryptStartInput());
316 		if (isprefix(mode, "output"))
317 			return(EncryptStartOutput());
318 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
319 			printf("Usage: encrypt start [input|output]\n");
320 			return(0);
321 		}
322 		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
323 		return(0);
324 	}
325 	ret += EncryptStartInput();
326 	ret += EncryptStartOutput();
327 	return(ret);
328 }
329 
330 	int
331 EncryptStartInput()
332 {
333 	if (decrypt_mode) {
334 		encrypt_send_request_start();
335 		return(1);
336 	}
337 	printf("No previous decryption mode, decryption not enabled\r\n");
338 	return(0);
339 }
340 
341 	int
342 EncryptStartOutput()
343 {
344 	if (encrypt_mode) {
345 		encrypt_start_output(encrypt_mode);
346 		return(1);
347 	}
348 	printf("No previous encryption mode, encryption not enabled\r\n");
349 	return(0);
350 }
351 
352 	int
353 EncryptStop(mode)
354 	char *mode;
355 {
356 	int ret = 0;
357 	if (mode) {
358 		if (isprefix(mode, "input"))
359 			return(EncryptStopInput());
360 		if (isprefix(mode, "output"))
361 			return(EncryptStopOutput());
362 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
363 			printf("Usage: encrypt stop [input|output]\n");
364 			return(0);
365 		}
366 		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
367 		return(0);
368 	}
369 	ret += EncryptStopInput();
370 	ret += EncryptStopOutput();
371 	return(ret);
372 }
373 
374 	int
375 EncryptStopInput()
376 {
377 	encrypt_send_request_end();
378 	return(1);
379 }
380 
381 	int
382 EncryptStopOutput()
383 {
384 	encrypt_send_end();
385 	return(1);
386 }
387 
388 	void
389 encrypt_display()
390 {
391 	if (encrypt_output)
392 		printf("Currently encrypting output with %s\r\n",
393 			ENCTYPE_NAME(encrypt_mode));
394 	if (decrypt_input)
395 		printf("Currently decrypting input with %s\r\n",
396 			ENCTYPE_NAME(decrypt_mode));
397 }
398 
399 	int
400 EncryptStatus()
401 {
402 	if (encrypt_output)
403 		printf("Currently encrypting output with %s\r\n",
404 			ENCTYPE_NAME(encrypt_mode));
405 	else if (encrypt_mode) {
406 		printf("Currently output is clear text.\r\n");
407 		printf("Last encryption mode was %s\r\n",
408 			ENCTYPE_NAME(encrypt_mode));
409 	}
410 	if (decrypt_input) {
411 		printf("Currently decrypting input with %s\r\n",
412 			ENCTYPE_NAME(decrypt_mode));
413 	} else if (decrypt_mode) {
414 		printf("Currently input is clear text.\r\n");
415 		printf("Last decryption mode was %s\r\n",
416 			ENCTYPE_NAME(decrypt_mode));
417 	}
418 	return 1;
419 }
420 
421 	void
422 encrypt_send_support()
423 {
424 	if (str_suplen) {
425 		/*
426 		 * If the user has requested that decryption start
427 		 * immediatly, then send a "REQUEST START" before
428 		 * we negotiate the type.
429 		 */
430 		if (!Server && autodecrypt)
431 			encrypt_send_request_start();
432 		telnet_net_write(str_send, str_suplen);
433 		printsub('>', &str_send[2], str_suplen - 2);
434 		str_suplen = 0;
435 	}
436 }
437 
438 	int
439 EncryptDebug(on)
440 	int on;
441 {
442 	if (on < 0)
443 		encrypt_debug_mode ^= 1;
444 	else
445 		encrypt_debug_mode = on;
446 	printf("Encryption debugging %s\r\n",
447 		encrypt_debug_mode ? "enabled" : "disabled");
448 	return(1);
449 }
450 
451 	int
452 EncryptVerbose(on)
453 	int on;
454 {
455 	if (on < 0)
456 		encrypt_verbose ^= 1;
457 	else
458 		encrypt_verbose = on;
459 	printf("Encryption %s verbose\r\n",
460 		encrypt_verbose ? "is" : "is not");
461 	return(1);
462 }
463 
464 	int
465 EncryptAutoEnc(on)
466 	int on;
467 {
468 	encrypt_auto(on);
469 	printf("Automatic encryption of output is %s\r\n",
470 		autoencrypt ? "enabled" : "disabled");
471 	return(1);
472 }
473 
474 	int
475 EncryptAutoDec(on)
476 	int on;
477 {
478 	decrypt_auto(on);
479 	printf("Automatic decryption of input is %s\r\n",
480 		autodecrypt ? "enabled" : "disabled");
481 	return(1);
482 }
483 
484 /*
485  * Called when ENCRYPT SUPPORT is received.
486  */
487 	void
488 encrypt_support(typelist, cnt)
489 	unsigned char *typelist;
490 	int cnt;
491 {
492 	register int type, use_type = 0;
493 	Encryptions *ep;
494 
495 	/*
496 	 * Forget anything the other side has previously told us.
497 	 */
498 	remote_supports_decrypt = 0;
499 
500 	while (cnt-- > 0) {
501 		type = *typelist++;
502 		if (encrypt_debug_mode)
503 			printf(">>>%s: He is supporting %s (%d)\r\n",
504 				Name,
505 				ENCTYPE_NAME(type), type);
506 		if ((type < ENCTYPE_CNT) &&
507 		    (I_SUPPORT_ENCRYPT & typemask(type))) {
508 			remote_supports_decrypt |= typemask(type);
509 			if (use_type == 0)
510 				use_type = type;
511 		}
512 	}
513 	if (use_type) {
514 		ep = findencryption(use_type);
515 		if (!ep)
516 			return;
517 		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
518 		if (encrypt_debug_mode)
519 			printf(">>>%s: (*ep->start)() returned %d\r\n",
520 					Name, type);
521 		if (type < 0)
522 			return;
523 		encrypt_mode = use_type;
524 		if (type == 0)
525 			encrypt_start_output(use_type);
526 	}
527 }
528 
529 	void
530 encrypt_is(data, cnt)
531 	unsigned char *data;
532 	int cnt;
533 {
534 	Encryptions *ep;
535 	register int type, ret;
536 
537 	if (--cnt < 0)
538 		return;
539 	type = *data++;
540 	if (type < ENCTYPE_CNT)
541 		remote_supports_encrypt |= typemask(type);
542 	if (!(ep = finddecryption(type))) {
543 		if (encrypt_debug_mode)
544 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
545 				Name,
546 				ENCTYPE_NAME_OK(type)
547 					? ENCTYPE_NAME(type) : "(unknown)",
548 				type);
549 		return;
550 	}
551 	if (!ep->is) {
552 		if (encrypt_debug_mode)
553 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
554 				Name,
555 				ENCTYPE_NAME_OK(type)
556 					? ENCTYPE_NAME(type) : "(unknown)",
557 				type);
558 		ret = 0;
559 	} else {
560 		ret = (*ep->is)(data, cnt);
561 		if (encrypt_debug_mode)
562 			printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
563 				(ret < 0) ? "FAIL " :
564 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
565 	}
566 	if (ret < 0) {
567 		autodecrypt = 0;
568 	} else {
569 		decrypt_mode = type;
570 		if (ret == 0 && autodecrypt)
571 			encrypt_send_request_start();
572 	}
573 }
574 
575 	void
576 encrypt_reply(data, cnt)
577 	unsigned char *data;
578 	int cnt;
579 {
580 	Encryptions *ep;
581 	register int ret, type;
582 
583 	if (--cnt < 0)
584 		return;
585 	type = *data++;
586 	if (!(ep = findencryption(type))) {
587 		if (encrypt_debug_mode)
588 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
589 				Name,
590 				ENCTYPE_NAME_OK(type)
591 					? ENCTYPE_NAME(type) : "(unknown)",
592 				type);
593 		return;
594 	}
595 	if (!ep->reply) {
596 		if (encrypt_debug_mode)
597 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
598 				Name,
599 				ENCTYPE_NAME_OK(type)
600 					? ENCTYPE_NAME(type) : "(unknown)",
601 				type);
602 		ret = 0;
603 	} else {
604 		ret = (*ep->reply)(data, cnt);
605 		if (encrypt_debug_mode)
606 			printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
607 				data, cnt,
608 				(ret < 0) ? "FAIL " :
609 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
610 	}
611 	if (encrypt_debug_mode)
612 		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
613 	if (ret < 0) {
614 		autoencrypt = 0;
615 	} else {
616 		encrypt_mode = type;
617 		if (ret == 0 && autoencrypt)
618 			encrypt_start_output(type);
619 	}
620 }
621 
622 /*
623  * Called when a ENCRYPT START command is received.
624  */
625 	void
626 encrypt_start(data, cnt)
627 	unsigned char *data;
628 	int cnt;
629 {
630 	Encryptions *ep;
631 
632 	if (!decrypt_mode) {
633 		/*
634 		 * Something is wrong.  We should not get a START
635 		 * command without having already picked our
636 		 * decryption scheme.  Send a REQUEST-END to
637 		 * attempt to clear the channel...
638 		 */
639 		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
640 		encrypt_send_request_end();
641 		return;
642 	}
643 
644 	if ((ep = finddecryption(decrypt_mode)) != NULL) {
645 		decrypt_input = ep->input;
646 		if (encrypt_verbose)
647 			printf("[ Input is now decrypted with type %s ]\r\n",
648 				ENCTYPE_NAME(decrypt_mode));
649 		if (encrypt_debug_mode)
650 			printf(">>>%s: Start to decrypt input with type %s\r\n",
651 				Name, ENCTYPE_NAME(decrypt_mode));
652 	} else {
653 		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
654 				Name,
655 				ENCTYPE_NAME_OK(decrypt_mode)
656 					? ENCTYPE_NAME(decrypt_mode)
657 					: "(unknown)",
658 				decrypt_mode);
659 		encrypt_send_request_end();
660 	}
661 }
662 
663 	void
664 encrypt_session_key(key, server)
665 	Session_Key *key;
666 	int server;
667 {
668 	Encryptions *ep = encryptions;
669 
670 	havesessionkey = 1;
671 
672 	while (ep->type) {
673 		if (ep->session)
674 			(*ep->session)(key, server);
675 #ifdef notdef
676 		if (!encrypt_output && autoencrypt && !server)
677 			encrypt_start_output(ep->type);
678 		if (!decrypt_input && autodecrypt && !server)
679 			encrypt_send_request_start();
680 #endif
681 		++ep;
682 	}
683 }
684 
685 /*
686  * Called when ENCRYPT END is received.
687  */
688 	void
689 encrypt_end()
690 {
691 	decrypt_input = 0;
692 	if (encrypt_debug_mode)
693 		printf(">>>%s: Input is back to clear text\r\n", Name);
694 	if (encrypt_verbose)
695 		printf("[ Input is now clear text ]\r\n");
696 }
697 
698 /*
699  * Called when ENCRYPT REQUEST-END is received.
700  */
701 	void
702 encrypt_request_end()
703 {
704 	encrypt_send_end();
705 }
706 
707 /*
708  * Called when ENCRYPT REQUEST-START is received.  If we receive
709  * this before a type is picked, then that indicates that the
710  * other side wants us to start encrypting data as soon as we
711  * can.
712  */
713 	void
714 encrypt_request_start(data, cnt)
715 	unsigned char *data;
716 	int cnt;
717 {
718 	if (encrypt_mode == 0)  {
719 		if (Server)
720 			autoencrypt = 1;
721 		return;
722 	}
723 	encrypt_start_output(encrypt_mode);
724 }
725 
726 static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
727 
728 	void
729 encrypt_enc_keyid(keyid, len)
730 	unsigned char *keyid;
731 	int len;
732 {
733 	encrypt_keyid(&ki[1], keyid, len);
734 }
735 
736 	void
737 encrypt_dec_keyid(keyid, len)
738 	unsigned char *keyid;
739 	int len;
740 {
741 	encrypt_keyid(&ki[0], keyid, len);
742 }
743 
744 void
745 encrypt_keyid(kp, keyid, len)
746 	struct key_info *kp;
747 	unsigned char *keyid;
748 	int len;
749 {
750 	Encryptions *ep;
751 	int dir = kp->dir;
752 	register int ret = 0;
753 
754 	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
755 		if (len == 0)
756 			return;
757 		kp->keylen = 0;
758 	} else if (len == 0) {
759 		/*
760 		 * Empty option, indicates a failure.
761 		 */
762 		if (kp->keylen == 0)
763 			return;
764 		kp->keylen = 0;
765 		if (ep->keyid)
766 			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
767 
768 	} else if ((len != kp->keylen) ||
769 		   (memcmp(keyid, kp->keyid, len) != 0)) {
770 		/*
771 		 * Length or contents are different
772 		 */
773 		kp->keylen = len;
774 		memmove(kp->keyid, keyid, len);
775 		if (ep->keyid)
776 			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
777 	} else {
778 		if (ep->keyid)
779 			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
780 		if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
781 			encrypt_start_output(*kp->modep);
782 		return;
783 	}
784 
785 	encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
786 }
787 
788 	void
789 encrypt_send_keyid(dir, keyid, keylen, saveit)
790 	int dir;
791 	unsigned char *keyid;
792 	int keylen;
793 	int saveit;
794 {
795 	unsigned char *strp;
796 
797 	str_keyid[3] = (dir == DIR_ENCRYPT)
798 			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
799 	if (saveit) {
800 		struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
801 		memmove(kp->keyid, keyid, keylen);
802 		kp->keylen = keylen;
803 	}
804 
805 	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
806 		if ((*strp++ = *keyid++) == IAC)
807 			*strp++ = IAC;
808 	}
809 	*strp++ = IAC;
810 	*strp++ = SE;
811 	telnet_net_write(str_keyid, strp - str_keyid);
812 	printsub('>', &str_keyid[2], strp - str_keyid - 2);
813 }
814 
815 	void
816 encrypt_auto(on)
817 	int on;
818 {
819 	if (on < 0)
820 		autoencrypt ^= 1;
821 	else
822 		autoencrypt = on ? 1 : 0;
823 }
824 
825 	void
826 decrypt_auto(on)
827 	int on;
828 {
829 	if (on < 0)
830 		autodecrypt ^= 1;
831 	else
832 		autodecrypt = on ? 1 : 0;
833 }
834 
835 	void
836 encrypt_start_output(type)
837 	int type;
838 {
839 	Encryptions *ep;
840 	register unsigned char *p;
841 	register int i;
842 
843 	if (!(ep = findencryption(type))) {
844 		if (encrypt_debug_mode) {
845 			printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
846 				Name,
847 				ENCTYPE_NAME_OK(type)
848 					? ENCTYPE_NAME(type) : "(unknown)",
849 				type);
850 		}
851 		return;
852 	}
853 	if (ep->start) {
854 		i = (*ep->start)(DIR_ENCRYPT, Server);
855 		if (encrypt_debug_mode) {
856 			printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
857 				Name,
858 				(i < 0) ? "failed" :
859 					"initial negotiation in progress",
860 				i, ENCTYPE_NAME(type));
861 		}
862 		if (i)
863 			return;
864 	}
865 	p = str_start + 3;
866 	*p++ = ENCRYPT_START;
867 	for (i = 0; i < ki[0].keylen; ++i) {
868 		if ((*p++ = ki[0].keyid[i]) == IAC)
869 			*p++ = IAC;
870 	}
871 	*p++ = IAC;
872 	*p++ = SE;
873 	telnet_net_write(str_start, p - str_start);
874 	net_encrypt();
875 	printsub('>', &str_start[2], p - &str_start[2]);
876 	/*
877 	 * If we are already encrypting in some mode, then
878 	 * encrypt the ring (which includes our request) in
879 	 * the old mode, mark it all as "clear text" and then
880 	 * switch to the new mode.
881 	 */
882 	encrypt_output = ep->output;
883 	encrypt_mode = type;
884 	if (encrypt_debug_mode)
885 		printf(">>>%s: Started to encrypt output with type %s\r\n",
886 			Name, ENCTYPE_NAME(type));
887 	if (encrypt_verbose)
888 		printf("[ Output is now encrypted with type %s ]\r\n",
889 			ENCTYPE_NAME(type));
890 }
891 
892 	void
893 encrypt_send_end()
894 {
895 	if (!encrypt_output)
896 		return;
897 
898 	str_end[3] = ENCRYPT_END;
899 	telnet_net_write(str_end, sizeof(str_end));
900 	net_encrypt();
901 	printsub('>', &str_end[2], sizeof(str_end) - 2);
902 	/*
903 	 * Encrypt the output buffer now because it will not be done by
904 	 * netflush...
905 	 */
906 	encrypt_output = 0;
907 	if (encrypt_debug_mode)
908 		printf(">>>%s: Output is back to clear text\r\n", Name);
909 	if (encrypt_verbose)
910 		printf("[ Output is now clear text ]\r\n");
911 }
912 
913 	void
914 encrypt_send_request_start()
915 {
916 	register unsigned char *p;
917 	register int i;
918 
919 	p = &str_start[3];
920 	*p++ = ENCRYPT_REQSTART;
921 	for (i = 0; i < ki[1].keylen; ++i) {
922 		if ((*p++ = ki[1].keyid[i]) == IAC)
923 			*p++ = IAC;
924 	}
925 	*p++ = IAC;
926 	*p++ = SE;
927 	telnet_net_write(str_start, p - str_start);
928 	printsub('>', &str_start[2], p - &str_start[2]);
929 	if (encrypt_debug_mode)
930 		printf(">>>%s: Request input to be encrypted\r\n", Name);
931 }
932 
933 	void
934 encrypt_send_request_end()
935 {
936 	str_end[3] = ENCRYPT_REQEND;
937 	telnet_net_write(str_end, sizeof(str_end));
938 	printsub('>', &str_end[2], sizeof(str_end) - 2);
939 
940 	if (encrypt_debug_mode)
941 		printf(">>>%s: Request input to be clear text\r\n", Name);
942 }
943 
944 	void
945 encrypt_wait()
946 {
947 	if (encrypt_debug_mode)
948 		printf(">>>%s: in encrypt_wait\r\n", Name);
949 	if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
950 		return;
951 	while (autoencrypt && !encrypt_output)
952 		if (telnet_spin())
953 			return;
954 }
955 
956 	void
957 encrypt_debug(mode)
958 	int mode;
959 {
960 	encrypt_debug_mode = mode;
961 }
962 
963 	void
964 encrypt_gen_printsub(data, cnt, buf, buflen)
965 	unsigned char *data, *buf;
966 	int cnt, buflen;
967 {
968 	char tbuf[16], *cp;
969 
970 	cnt -= 2;
971 	data += 2;
972 	buf[buflen-1] = '\0';
973 	buf[buflen-2] = '*';
974 	buflen -= 2;
975 	for (; cnt > 0; cnt--, data++) {
976 		snprintf(tbuf, sizeof(tbuf), " %d", *data);
977 		for (cp = tbuf; *cp && buflen > 0; --buflen)
978 			*buf++ = *cp++;
979 		if (buflen <= 0)
980 			return;
981 	}
982 	*buf = '\0';
983 }
984 
985 	void
986 encrypt_printsub(data, cnt, buf, buflen)
987 	unsigned char *data, *buf;
988 	int cnt, buflen;
989 {
990 	Encryptions *ep;
991 	register int type = data[1];
992 
993 	for (ep = encryptions; ep->type && ep->type != type; ep++)
994 		;
995 
996 	if (ep->printsub)
997 		(*ep->printsub)(data, cnt, buf, buflen);
998 	else
999 		encrypt_gen_printsub(data, cnt, buf, buflen);
1000 }
1001 #endif	/* ENCRYPTION */
1002