xref: /csrg-svn/lib/libtelnet/encrypt.c (revision 69784)
146801Sdab /*-
261382Sbostic  * Copyright (c) 1991, 1993
361382Sbostic  *	The Regents of the University of California.  All rights reserved.
446801Sdab  *
546801Sdab  * %sccs.include.redist.c%
646801Sdab  */
746801Sdab 
846801Sdab #ifndef lint
9*69784Sdab static char sccsid[] = "@(#)encrypt.c	8.2 (Berkeley) 05/30/95";
1046801Sdab #endif /* not lint */
1146801Sdab 
1246801Sdab /*
1346801Sdab  * Copyright (C) 1990 by the Massachusetts Institute of Technology
1446801Sdab  *
1546801Sdab  * Export of this software from the United States of America is assumed
1646801Sdab  * to require a specific license from the United States Government.
1746801Sdab  * It is the responsibility of any person or organization contemplating
1846801Sdab  * export to obtain such a license before exporting.
1946801Sdab  *
2046801Sdab  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
2146801Sdab  * distribute this software and its documentation for any purpose and
2246801Sdab  * without fee is hereby granted, provided that the above copyright
2346801Sdab  * notice appear in all copies and that both that copyright notice and
2446801Sdab  * this permission notice appear in supporting documentation, and that
2546801Sdab  * the name of M.I.T. not be used in advertising or publicity pertaining
2646801Sdab  * to distribution of the software without specific, written prior
2746801Sdab  * permission.  M.I.T. makes no representations about the suitability of
2846801Sdab  * this software for any purpose.  It is provided "as is" without express
2946801Sdab  * or implied warranty.
3046801Sdab  */
3146801Sdab 
3260150Sdab #ifdef	ENCRYPTION
3346801Sdab 
3446801Sdab #define	ENCRYPT_NAMES
3546801Sdab #include <arpa/telnet.h>
3646801Sdab 
3746801Sdab #include "encrypt.h"
3846801Sdab #include "misc.h"
3946801Sdab 
4046801Sdab #ifdef	__STDC__
4146801Sdab #include <stdlib.h>
4246801Sdab #endif
4346801Sdab #ifdef	NO_STRING_H
4446801Sdab #include <strings.h>
4546801Sdab #else
4646801Sdab #include <string.h>
4746801Sdab #endif
4846801Sdab 
4946801Sdab /*
5046801Sdab  * These functions pointers point to the current routines
5146801Sdab  * for encrypting and decrypting data.
5246801Sdab  */
5346801Sdab void	(*encrypt_output) P((unsigned char *, int));
5446801Sdab int	(*decrypt_input) P((int));
5546801Sdab 
5646801Sdab int encrypt_debug_mode = 0;
5746801Sdab static int decrypt_mode = 0;
5846801Sdab static int encrypt_mode = 0;
5946801Sdab static int encrypt_verbose = 0;
6046801Sdab static int autoencrypt = 0;
6146801Sdab static int autodecrypt = 0;
6246801Sdab static int havesessionkey = 0;
6346801Sdab static int Server = 0;
6446801Sdab static char *Name = "Noname";
6546801Sdab 
6646801Sdab #define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
6746801Sdab 
6847612Sdab static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64)
6947612Sdab 				| typemask(ENCTYPE_DES_OFB64);
7047612Sdab static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64)
7147612Sdab 				| typemask(ENCTYPE_DES_OFB64);
7247612Sdab static long i_wont_support_encrypt = 0;
7347612Sdab static long i_wont_support_decrypt = 0;
7447612Sdab #define	I_SUPPORT_ENCRYPT	(i_support_encrypt & ~i_wont_support_encrypt)
7547612Sdab #define	I_SUPPORT_DECRYPT	(i_support_decrypt & ~i_wont_support_decrypt)
7647612Sdab 
7746801Sdab static long remote_supports_encrypt = 0;
7846801Sdab static long remote_supports_decrypt = 0;
7946801Sdab 
8046801Sdab static Encryptions encryptions[] = {
8160150Sdab #ifdef	DES_ENCRYPTION
8247612Sdab     { "DES_CFB64",	ENCTYPE_DES_CFB64,
83*69784Sdab 			cfb64_encrypt,
8447612Sdab 			cfb64_decrypt,
8547612Sdab 			cfb64_init,
8647612Sdab 			cfb64_start,
8747612Sdab 			cfb64_is,
8847612Sdab 			cfb64_reply,
8947612Sdab 			cfb64_session,
9047612Sdab 			cfb64_keyid,
9147612Sdab 			cfb64_printsub },
9247612Sdab     { "DES_OFB64",	ENCTYPE_DES_OFB64,
93*69784Sdab 			ofb64_encrypt,
9447612Sdab 			ofb64_decrypt,
9547612Sdab 			ofb64_init,
9647612Sdab 			ofb64_start,
9747612Sdab 			ofb64_is,
9847612Sdab 			ofb64_reply,
9947612Sdab 			ofb64_session,
10047612Sdab 			ofb64_keyid,
10147612Sdab 			ofb64_printsub },
10260150Sdab #endif	/* DES_ENCRYPTION */
10346801Sdab     { 0, },
10446801Sdab };
10546801Sdab 
10646801Sdab static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
10747612Sdab 					 ENCRYPT_SUPPORT };
10846801Sdab static unsigned char str_suplen = 0;
10947612Sdab static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
11046801Sdab static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
11146801Sdab 
11246801Sdab 	Encryptions *
findencryption(type)11346801Sdab findencryption(type)
11446801Sdab 	int type;
11546801Sdab {
11646801Sdab 	Encryptions *ep = encryptions;
11746801Sdab 
11847612Sdab 	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
11946801Sdab 		return(0);
12046801Sdab 	while (ep->type && ep->type != type)
12146801Sdab 		++ep;
12246801Sdab 	return(ep->type ? ep : 0);
12346801Sdab }
12446801Sdab 
12546801Sdab 	Encryptions *
finddecryption(type)12646801Sdab finddecryption(type)
12746801Sdab 	int type;
12846801Sdab {
12946801Sdab 	Encryptions *ep = encryptions;
13046801Sdab 
13147612Sdab 	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
13246801Sdab 		return(0);
13346801Sdab 	while (ep->type && ep->type != type)
13446801Sdab 		++ep;
13546801Sdab 	return(ep->type ? ep : 0);
13646801Sdab }
13746801Sdab 
13847612Sdab #define	MAXKEYLEN 64
13947612Sdab 
14047612Sdab static struct key_info {
14147612Sdab 	unsigned char keyid[MAXKEYLEN];
14247612Sdab 	int keylen;
14347612Sdab 	int dir;
14447612Sdab 	int *modep;
14547612Sdab 	Encryptions *(*getcrypt)();
14647612Sdab } ki[2] = {
14747612Sdab 	{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
14847612Sdab 	{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
14947612Sdab };
15047612Sdab 
15146801Sdab 	void
encrypt_init(name,server)15246801Sdab encrypt_init(name, server)
15346801Sdab 	char *name;
15446801Sdab 	int server;
15546801Sdab {
15646801Sdab 	Encryptions *ep = encryptions;
15746801Sdab 
15846801Sdab 	Name = name;
15946801Sdab 	Server = server;
16046801Sdab 	i_support_encrypt = i_support_decrypt = 0;
16146801Sdab 	remote_supports_encrypt = remote_supports_decrypt = 0;
16246801Sdab 	encrypt_mode = 0;
16346801Sdab 	decrypt_mode = 0;
16446801Sdab 	encrypt_output = 0;
16546801Sdab 	decrypt_input = 0;
16646801Sdab #ifdef notdef
16746801Sdab 	encrypt_verbose = !server;
16846801Sdab #endif
16946801Sdab 
17046801Sdab 	str_suplen = 4;
17146801Sdab 
17246801Sdab 	while (ep->type) {
17346801Sdab 		if (encrypt_debug_mode)
17446801Sdab 			printf(">>>%s: I will support %s\r\n",
17546801Sdab 				Name, ENCTYPE_NAME(ep->type));
17646801Sdab 		i_support_encrypt |= typemask(ep->type);
17746801Sdab 		i_support_decrypt |= typemask(ep->type);
17847612Sdab 		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
17947612Sdab 			if ((str_send[str_suplen++] = ep->type) == IAC)
18047612Sdab 				str_send[str_suplen++] = IAC;
18146801Sdab 		if (ep->init)
18246801Sdab 			(*ep->init)(Server);
18346801Sdab 		++ep;
18446801Sdab 	}
18546801Sdab 	str_send[str_suplen++] = IAC;
18646801Sdab 	str_send[str_suplen++] = SE;
18746801Sdab }
18846801Sdab 
18946801Sdab 	void
encrypt_list_types()19046801Sdab encrypt_list_types()
19146801Sdab {
19246801Sdab 	Encryptions *ep = encryptions;
19346801Sdab 
19446801Sdab 	printf("Valid encryption types:\n");
19546801Sdab 	while (ep->type) {
19647612Sdab 		printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
19746801Sdab 		++ep;
19846801Sdab 	}
19946801Sdab }
20046801Sdab 
20146801Sdab 	int
EncryptEnable(type,mode)20246801Sdab EncryptEnable(type, mode)
20346801Sdab 	char *type, *mode;
20446801Sdab {
20546801Sdab 	if (isprefix(type, "help") || isprefix(type, "?")) {
20646801Sdab 		printf("Usage: encrypt enable <type> [input|output]\n");
20746801Sdab 		encrypt_list_types();
20846801Sdab 		return(0);
20946801Sdab 	}
21046801Sdab 	if (EncryptType(type, mode))
21146801Sdab 		return(EncryptStart(mode));
21246801Sdab 	return(0);
21346801Sdab }
21446801Sdab 
21546801Sdab 	int
EncryptDisable(type,mode)21647612Sdab EncryptDisable(type, mode)
21747612Sdab 	char *type, *mode;
21847612Sdab {
21947612Sdab 	register Encryptions *ep;
22047612Sdab 	int ret = 0;
22147612Sdab 
22247612Sdab 	if (isprefix(type, "help") || isprefix(type, "?")) {
22347612Sdab 		printf("Usage: encrypt disable <type> [input|output]\n");
22447612Sdab 		encrypt_list_types();
22547612Sdab 	} else if ((ep = (Encryptions *)genget(type, encryptions,
22647612Sdab 						sizeof(Encryptions))) == 0) {
22747612Sdab 		printf("%s: invalid encryption type\n", type);
22847612Sdab 	} else if (Ambiguous(ep)) {
22947612Sdab 		printf("Ambiguous type '%s'\n", type);
23047612Sdab 	} else {
23147612Sdab 		if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
23247612Sdab 			if (decrypt_mode == ep->type)
23347612Sdab 				EncryptStopInput();
23447612Sdab 			i_wont_support_decrypt |= typemask(ep->type);
23547612Sdab 			ret = 1;
23647612Sdab 		}
23747612Sdab 		if ((mode == 0) || (isprefix(mode, "output"))) {
23847612Sdab 			if (encrypt_mode == ep->type)
23947612Sdab 				EncryptStopOutput();
24047612Sdab 			i_wont_support_encrypt |= typemask(ep->type);
24147612Sdab 			ret = 1;
24247612Sdab 		}
24347612Sdab 		if (ret == 0)
24447612Sdab 			printf("%s: invalid encryption mode\n", mode);
24547612Sdab 	}
24647612Sdab 	return(ret);
24747612Sdab }
24847612Sdab 
24947612Sdab 	int
EncryptType(type,mode)25046801Sdab EncryptType(type, mode)
25146801Sdab 	char *type;
25246801Sdab 	char *mode;
25346801Sdab {
25446801Sdab 	register Encryptions *ep;
25547612Sdab 	int ret = 0;
25646801Sdab 
25746801Sdab 	if (isprefix(type, "help") || isprefix(type, "?")) {
25846801Sdab 		printf("Usage: encrypt type <type> [input|output]\n");
25946801Sdab 		encrypt_list_types();
26047612Sdab 	} else if ((ep = (Encryptions *)genget(type, encryptions,
26147612Sdab 						sizeof(Encryptions))) == 0) {
26246801Sdab 		printf("%s: invalid encryption type\n", type);
26347612Sdab 	} else if (Ambiguous(ep)) {
26446801Sdab 		printf("Ambiguous type '%s'\n", type);
26547612Sdab 	} else {
26647612Sdab 		if ((mode == 0) || isprefix(mode, "input")) {
26746801Sdab 			decrypt_mode = ep->type;
26847612Sdab 			i_wont_support_decrypt &= ~typemask(ep->type);
26947612Sdab 			ret = 1;
27047612Sdab 		}
27147612Sdab 		if ((mode == 0) || isprefix(mode, "output")) {
27246801Sdab 			encrypt_mode = ep->type;
27347612Sdab 			i_wont_support_encrypt &= ~typemask(ep->type);
27447612Sdab 			ret = 1;
27547612Sdab 		}
27647612Sdab 		if (ret == 0)
27746801Sdab 			printf("%s: invalid encryption mode\n", mode);
27847612Sdab 	}
27947612Sdab 	return(ret);
28046801Sdab }
28146801Sdab 
28246801Sdab 	int
EncryptStart(mode)28346801Sdab EncryptStart(mode)
28446801Sdab 	char *mode;
28546801Sdab {
28646801Sdab 	register int ret = 0;
28746801Sdab 	if (mode) {
28846801Sdab 		if (isprefix(mode, "input"))
28946801Sdab 			return(EncryptStartInput());
29046801Sdab 		if (isprefix(mode, "output"))
29146801Sdab 			return(EncryptStartOutput());
29246801Sdab 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
29346801Sdab 			printf("Usage: encrypt start [input|output]\n");
29446801Sdab 			return(0);
29546801Sdab 		}
29646801Sdab 		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
29746801Sdab 		return(0);
29846801Sdab 	}
29946801Sdab 	ret += EncryptStartInput();
30046801Sdab 	ret += EncryptStartOutput();
30146801Sdab 	return(ret);
30246801Sdab }
30346801Sdab 
30446801Sdab 	int
EncryptStartInput()30546801Sdab EncryptStartInput()
30646801Sdab {
30746801Sdab 	if (decrypt_mode) {
30846801Sdab 		encrypt_send_request_start();
30946801Sdab 		return(1);
31046801Sdab 	}
31146801Sdab 	printf("No previous decryption mode, decryption not enabled\r\n");
31246801Sdab 	return(0);
31346801Sdab }
31446801Sdab 
31546801Sdab 	int
EncryptStartOutput()31646801Sdab EncryptStartOutput()
31746801Sdab {
31846801Sdab 	if (encrypt_mode) {
31946801Sdab 		encrypt_start_output(encrypt_mode);
32046801Sdab 		return(1);
32146801Sdab 	}
32246801Sdab 	printf("No previous encryption mode, encryption not enabled\r\n");
32346801Sdab 	return(0);
32446801Sdab }
32546801Sdab 
32646801Sdab 	int
EncryptStop(mode)32746801Sdab EncryptStop(mode)
32846801Sdab 	char *mode;
32946801Sdab {
33046801Sdab 	int ret = 0;
33146801Sdab 	if (mode) {
33246801Sdab 		if (isprefix(mode, "input"))
33346801Sdab 			return(EncryptStopInput());
33446801Sdab 		if (isprefix(mode, "output"))
33546801Sdab 			return(EncryptStopOutput());
33646801Sdab 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
33746801Sdab 			printf("Usage: encrypt stop [input|output]\n");
33846801Sdab 			return(0);
33946801Sdab 		}
34046801Sdab 		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
34146801Sdab 		return(0);
34246801Sdab 	}
34346801Sdab 	ret += EncryptStopInput();
34446801Sdab 	ret += EncryptStopOutput();
34546801Sdab 	return(ret);
34646801Sdab }
34746801Sdab 
34846801Sdab 	int
EncryptStopInput()34946801Sdab EncryptStopInput()
35046801Sdab {
35146801Sdab 	encrypt_send_request_end();
35246801Sdab 	return(1);
35346801Sdab }
35446801Sdab 
35546801Sdab 	int
EncryptStopOutput()35646801Sdab EncryptStopOutput()
35746801Sdab {
35846801Sdab 	encrypt_send_end();
35946801Sdab 	return(1);
36046801Sdab }
36146801Sdab 
36246801Sdab 	void
encrypt_display()36346801Sdab encrypt_display()
36446801Sdab {
36546801Sdab 	if (encrypt_output)
36646801Sdab 		printf("Currently encrypting output with %s\r\n",
36746801Sdab 			ENCTYPE_NAME(encrypt_mode));
36846801Sdab 	if (decrypt_input)
36946801Sdab 		printf("Currently decrypting input with %s\r\n",
37046801Sdab 			ENCTYPE_NAME(decrypt_mode));
37146801Sdab }
37246801Sdab 
37346801Sdab 	int
EncryptStatus()37446801Sdab EncryptStatus()
37546801Sdab {
37646801Sdab 	if (encrypt_output)
37746801Sdab 		printf("Currently encrypting output with %s\r\n",
37846801Sdab 			ENCTYPE_NAME(encrypt_mode));
37946801Sdab 	else if (encrypt_mode) {
38046801Sdab 		printf("Currently output is clear text.\r\n");
38146801Sdab 		printf("Last encryption mode was %s\r\n",
38246801Sdab 			ENCTYPE_NAME(encrypt_mode));
38346801Sdab 	}
38446801Sdab 	if (decrypt_input) {
38546801Sdab 		printf("Currently decrypting input with %s\r\n",
38646801Sdab 			ENCTYPE_NAME(decrypt_mode));
38746801Sdab 	} else if (decrypt_mode) {
38846801Sdab 		printf("Currently input is clear text.\r\n");
38946801Sdab 		printf("Last decryption mode was %s\r\n",
39046801Sdab 			ENCTYPE_NAME(decrypt_mode));
39146801Sdab 	}
39246801Sdab 	return 1;
39346801Sdab }
39446801Sdab 
39546801Sdab 	void
encrypt_send_support()39646801Sdab encrypt_send_support()
39746801Sdab {
39846801Sdab 	if (str_suplen) {
39946801Sdab 		/*
40046801Sdab 		 * If the user has requested that decryption start
40146801Sdab 		 * immediatly, then send a "REQUEST START" before
40246801Sdab 		 * we negotiate the type.
40346801Sdab 		 */
40446801Sdab 		if (!Server && autodecrypt)
40546801Sdab 			encrypt_send_request_start();
40646801Sdab 		net_write(str_send, str_suplen);
40746801Sdab 		printsub('>', &str_send[2], str_suplen - 2);
40846801Sdab 		str_suplen = 0;
40946801Sdab 	}
41046801Sdab }
41146801Sdab 
41246801Sdab 	int
EncryptDebug(on)41347612Sdab EncryptDebug(on)
41447612Sdab 	int on;
41546801Sdab {
41647612Sdab 	if (on < 0)
41747612Sdab 		encrypt_debug_mode ^= 1;
41847612Sdab 	else
41947612Sdab 		encrypt_debug_mode = on;
42046801Sdab 	printf("Encryption debugging %s\r\n",
42146801Sdab 		encrypt_debug_mode ? "enabled" : "disabled");
42246801Sdab 	return(1);
42346801Sdab }
42446801Sdab 
42546801Sdab 	int
EncryptVerbose(on)42647612Sdab EncryptVerbose(on)
42747612Sdab 	int on;
42846801Sdab {
42947612Sdab 	if (on < 0)
43047612Sdab 		encrypt_verbose ^= 1;
43147612Sdab 	else
43247612Sdab 		encrypt_verbose = on;
43346801Sdab 	printf("Encryption %s verbose\r\n",
43446801Sdab 		encrypt_verbose ? "is" : "is not");
43546801Sdab 	return(1);
43646801Sdab }
43746801Sdab 
43846801Sdab 	int
EncryptAutoEnc(on)43947612Sdab EncryptAutoEnc(on)
44047612Sdab 	int on;
44146801Sdab {
44247612Sdab 	encrypt_auto(on);
44347612Sdab 	printf("Automatic encryption of output is %s\r\n",
44446801Sdab 		autoencrypt ? "enabled" : "disabled");
44546801Sdab 	return(1);
44646801Sdab }
44746801Sdab 
44847612Sdab 	int
EncryptAutoDec(on)44947612Sdab EncryptAutoDec(on)
45047612Sdab 	int on;
45147612Sdab {
45247612Sdab 	decrypt_auto(on);
45347612Sdab 	printf("Automatic decryption of input is %s\r\n",
45447612Sdab 		autodecrypt ? "enabled" : "disabled");
45547612Sdab 	return(1);
45647612Sdab }
45746801Sdab 
45846801Sdab /*
45946801Sdab  * Called when ENCRYPT SUPPORT is received.
46046801Sdab  */
46146801Sdab 	void
encrypt_support(typelist,cnt)46246801Sdab encrypt_support(typelist, cnt)
46346801Sdab 	unsigned char *typelist;
46446801Sdab 	int cnt;
46546801Sdab {
46646801Sdab 	register int type, use_type = 0;
46746801Sdab 	Encryptions *ep;
46846801Sdab 
46946801Sdab 	/*
47046801Sdab 	 * Forget anything the other side has previously told us.
47146801Sdab 	 */
47246801Sdab 	remote_supports_decrypt = 0;
47346801Sdab 
47446801Sdab 	while (cnt-- > 0) {
47546801Sdab 		type = *typelist++;
47646801Sdab 		if (encrypt_debug_mode)
47746801Sdab 			printf(">>>%s: He is supporting %s (%d)\r\n",
47846801Sdab 				Name,
47946801Sdab 				ENCTYPE_NAME(type), type);
48046801Sdab 		if ((type < ENCTYPE_CNT) &&
48147612Sdab 		    (I_SUPPORT_ENCRYPT & typemask(type))) {
48246801Sdab 			remote_supports_decrypt |= typemask(type);
48346801Sdab 			if (use_type == 0)
48446801Sdab 				use_type = type;
48546801Sdab 		}
48646801Sdab 	}
48746801Sdab 	if (use_type) {
48846801Sdab 		ep = findencryption(use_type);
48946801Sdab 		if (!ep)
49046801Sdab 			return;
49146801Sdab 		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
49246801Sdab 		if (encrypt_debug_mode)
49346801Sdab 			printf(">>>%s: (*ep->start)() returned %d\r\n",
49446801Sdab 					Name, type);
49546801Sdab 		if (type < 0)
49646801Sdab 			return;
49747612Sdab 		encrypt_mode = use_type;
49846801Sdab 		if (type == 0)
49946801Sdab 			encrypt_start_output(use_type);
50046801Sdab 	}
50146801Sdab }
50246801Sdab 
50346801Sdab 	void
encrypt_is(data,cnt)50446801Sdab encrypt_is(data, cnt)
50546801Sdab 	unsigned char *data;
50646801Sdab 	int cnt;
50746801Sdab {
50846801Sdab 	Encryptions *ep;
50946801Sdab 	register int type, ret;
51046801Sdab 
51146801Sdab 	if (--cnt < 0)
51246801Sdab 		return;
51346801Sdab 	type = *data++;
51446801Sdab 	if (type < ENCTYPE_CNT)
51546801Sdab 		remote_supports_encrypt |= typemask(type);
51646801Sdab 	if (!(ep = finddecryption(type))) {
51746801Sdab 		if (encrypt_debug_mode)
51846801Sdab 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
51946801Sdab 				Name,
52047612Sdab 				ENCTYPE_NAME_OK(type)
52147612Sdab 					? ENCTYPE_NAME(type) : "(unknown)",
52247612Sdab 				type);
52346801Sdab 		return;
52446801Sdab 	}
52546801Sdab 	if (!ep->is) {
52646801Sdab 		if (encrypt_debug_mode)
52746801Sdab 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
52846801Sdab 				Name,
52947612Sdab 				ENCTYPE_NAME_OK(type)
53047612Sdab 					? ENCTYPE_NAME(type) : "(unknown)",
53147612Sdab 				type);
53246801Sdab 		ret = 0;
53346801Sdab 	} else {
53446801Sdab 		ret = (*ep->is)(data, cnt);
53547612Sdab 		if (encrypt_debug_mode)
53647612Sdab 			printf("(*ep->is)(%x, %d) returned %s(%d)\n", data, cnt,
53747612Sdab 				(ret < 0) ? "FAIL " :
53847612Sdab 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
53946801Sdab 	}
54046801Sdab 	if (ret < 0) {
54146801Sdab 		autodecrypt = 0;
54246801Sdab 	} else {
54346801Sdab 		decrypt_mode = type;
54446801Sdab 		if (ret == 0 && autodecrypt)
54546801Sdab 			encrypt_send_request_start();
54646801Sdab 	}
54746801Sdab }
54846801Sdab 
54946801Sdab 	void
encrypt_reply(data,cnt)55046801Sdab encrypt_reply(data, cnt)
55146801Sdab 	unsigned char *data;
55246801Sdab 	int cnt;
55346801Sdab {
55446801Sdab 	Encryptions *ep;
55546801Sdab 	register int ret, type;
55646801Sdab 
55746801Sdab 	if (--cnt < 0)
55846801Sdab 		return;
55946801Sdab 	type = *data++;
56046801Sdab 	if (!(ep = findencryption(type))) {
56146801Sdab 		if (encrypt_debug_mode)
56246801Sdab 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
56346801Sdab 				Name,
56447612Sdab 				ENCTYPE_NAME_OK(type)
56547612Sdab 					? ENCTYPE_NAME(type) : "(unknown)",
56647612Sdab 				type);
56746801Sdab 		return;
56846801Sdab 	}
56946801Sdab 	if (!ep->reply) {
57046801Sdab 		if (encrypt_debug_mode)
57146801Sdab 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
57246801Sdab 				Name,
57347612Sdab 				ENCTYPE_NAME_OK(type)
57447612Sdab 					? ENCTYPE_NAME(type) : "(unknown)",
57547612Sdab 				type);
57646801Sdab 		ret = 0;
57746801Sdab 	} else {
57846801Sdab 		ret = (*ep->reply)(data, cnt);
57947612Sdab 		if (encrypt_debug_mode)
58047612Sdab 			printf("(*ep->reply)(%x, %d) returned %s(%d)\n",
58147612Sdab 				data, cnt,
58247612Sdab 				(ret < 0) ? "FAIL " :
58347612Sdab 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
58446801Sdab 	}
58546801Sdab 	if (encrypt_debug_mode)
58646801Sdab 		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
58746801Sdab 	if (ret < 0) {
58846801Sdab 		autoencrypt = 0;
58946801Sdab 	} else {
59046801Sdab 		encrypt_mode = type;
59146801Sdab 		if (ret == 0 && autoencrypt)
59246801Sdab 			encrypt_start_output(type);
59346801Sdab 	}
59446801Sdab }
59546801Sdab 
59646801Sdab /*
59746801Sdab  * Called when a ENCRYPT START command is received.
59846801Sdab  */
59946801Sdab 	void
encrypt_start(data,cnt)60047612Sdab encrypt_start(data, cnt)
60147612Sdab 	unsigned char *data;
60247612Sdab 	int cnt;
60346801Sdab {
60446801Sdab 	Encryptions *ep;
60546801Sdab 
60646801Sdab 	if (!decrypt_mode) {
60746801Sdab 		/*
60846801Sdab 		 * Something is wrong.  We should not get a START
60946801Sdab 		 * command without having already picked our
61046801Sdab 		 * decryption scheme.  Send a REQUEST-END to
61146801Sdab 		 * attempt to clear the channel...
61246801Sdab 		 */
61346801Sdab 		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
61446801Sdab 		encrypt_send_request_end();
61546801Sdab 		return;
61646801Sdab 	}
61746801Sdab 
61846801Sdab 	if (ep = finddecryption(decrypt_mode)) {
61946801Sdab 		decrypt_input = ep->input;
62046801Sdab 		if (encrypt_verbose)
62146801Sdab 			printf("[ Input is now decrypted with type %s ]\r\n",
62246801Sdab 				ENCTYPE_NAME(decrypt_mode));
62346801Sdab 		if (encrypt_debug_mode)
62446801Sdab 			printf(">>>%s: Start to decrypt input with type %s\r\n",
62546801Sdab 				Name, ENCTYPE_NAME(decrypt_mode));
62646801Sdab 	} else {
62746801Sdab 		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
62847612Sdab 				Name,
62947612Sdab 				ENCTYPE_NAME_OK(decrypt_mode)
63047612Sdab 					? ENCTYPE_NAME(decrypt_mode)
63147612Sdab 					: "(unknown)",
63247612Sdab 				decrypt_mode);
63346801Sdab 		encrypt_send_request_end();
63446801Sdab 	}
63546801Sdab }
63646801Sdab 
63746801Sdab 	void
encrypt_session_key(key,server)63846801Sdab encrypt_session_key(key, server)
63946801Sdab 	Session_Key *key;
64046801Sdab 	int server;
64146801Sdab {
64246801Sdab 	Encryptions *ep = encryptions;
64346801Sdab 
64446801Sdab 	havesessionkey = 1;
64546801Sdab 
64646801Sdab 	while (ep->type) {
64746801Sdab 		if (ep->session)
64846801Sdab 			(*ep->session)(key, server);
64957214Sdab #ifdef notdef
65057214Sdab 		if (!encrypt_output && autoencrypt && !server)
65157214Sdab 			encrypt_start_output(ep->type);
65257214Sdab 		if (!decrypt_input && autodecrypt && !server)
65357214Sdab 			encrypt_send_request_start();
65457214Sdab #endif
65546801Sdab 		++ep;
65646801Sdab 	}
65746801Sdab }
65846801Sdab 
65946801Sdab /*
66046801Sdab  * Called when ENCRYPT END is received.
66146801Sdab  */
66246801Sdab 	void
encrypt_end()66346801Sdab encrypt_end()
66446801Sdab {
66546801Sdab 	decrypt_input = 0;
66646801Sdab 	if (encrypt_debug_mode)
66746801Sdab 		printf(">>>%s: Input is back to clear text\r\n", Name);
66846801Sdab 	if (encrypt_verbose)
66946801Sdab 		printf("[ Input is now clear text ]\r\n");
67046801Sdab }
67146801Sdab 
67246801Sdab /*
67346801Sdab  * Called when ENCRYPT REQUEST-END is received.
67446801Sdab  */
67546801Sdab 	void
encrypt_request_end()67646801Sdab encrypt_request_end()
67746801Sdab {
67846801Sdab 	encrypt_send_end();
67946801Sdab }
68046801Sdab 
68146801Sdab /*
68246801Sdab  * Called when ENCRYPT REQUEST-START is received.  If we receive
68346801Sdab  * this before a type is picked, then that indicates that the
68446801Sdab  * other side wants us to start encrypting data as soon as we
685*69784Sdab  * can.
68646801Sdab  */
68746801Sdab 	void
encrypt_request_start(data,cnt)68847612Sdab encrypt_request_start(data, cnt)
68947612Sdab 	unsigned char *data;
69047612Sdab 	int cnt;
69146801Sdab {
69247612Sdab 	if (encrypt_mode == 0)  {
69347612Sdab 		if (Server)
69447612Sdab 			autoencrypt = 1;
69546801Sdab 		return;
69646801Sdab 	}
69746801Sdab 	encrypt_start_output(encrypt_mode);
69846801Sdab }
69946801Sdab 
70047612Sdab static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
70147612Sdab 
encrypt_enc_keyid(keyid,len)70247612Sdab encrypt_enc_keyid(keyid, len)
70347612Sdab 	unsigned char *keyid;
70447612Sdab 	int len;
70547612Sdab {
70647612Sdab 	encrypt_keyid(&ki[1], keyid, len);
70747612Sdab }
70847612Sdab 
encrypt_dec_keyid(keyid,len)70947612Sdab encrypt_dec_keyid(keyid, len)
71047612Sdab 	unsigned char *keyid;
71147612Sdab 	int len;
71247612Sdab {
71347612Sdab 	encrypt_keyid(&ki[0], keyid, len);
71447612Sdab }
71547612Sdab 
71647612Sdab encrypt_keyid(kp, keyid, len)
71747612Sdab 	struct key_info *kp;
71847612Sdab 	unsigned char *keyid;
71947612Sdab 	int len;
72047612Sdab {
72147612Sdab 	Encryptions *ep;
72247612Sdab 	unsigned char *strp, *cp;
72347612Sdab 	int dir = kp->dir;
72447612Sdab 	register int ret = 0;
72547612Sdab 
72647612Sdab 	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
72747612Sdab 		if (len == 0)
72847612Sdab 			return;
72947612Sdab 		kp->keylen = 0;
73047612Sdab 	} else if (len == 0) {
73147612Sdab 		/*
73247612Sdab 		 * Empty option, indicates a failure.
73347612Sdab 		 */
73447612Sdab 		if (kp->keylen == 0)
73547612Sdab 			return;
73647612Sdab 		kp->keylen = 0;
73747612Sdab 		if (ep->keyid)
73847612Sdab 			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
73947612Sdab 
740*69784Sdab 	} else if ((len != kp->keylen) ||
741*69784Sdab 		   (memcmp(keyid, kp->keyid, len) != 0)) {
74247612Sdab 		/*
74347612Sdab 		 * Length or contents are different
74447612Sdab 		 */
74547612Sdab 		kp->keylen = len;
746*69784Sdab 		memmove(kp->keyid, keyid, len);
74747612Sdab 		if (ep->keyid)
74847612Sdab 			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
74947612Sdab 	} else {
75047612Sdab 		if (ep->keyid)
75147612Sdab 			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
75247612Sdab 		if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
75347612Sdab 			encrypt_start_output(*kp->modep);
75447612Sdab 		return;
75547612Sdab 	}
75647612Sdab 
75747612Sdab 	encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
75847612Sdab }
75947612Sdab 
76046801Sdab 	void
encrypt_send_keyid(dir,keyid,keylen,saveit)76147612Sdab encrypt_send_keyid(dir, keyid, keylen, saveit)
76247612Sdab 	int dir;
76347612Sdab 	unsigned char *keyid;
76447612Sdab 	int keylen;
76547612Sdab 	int saveit;
76646801Sdab {
76747612Sdab 	unsigned char *strp;
76847612Sdab 
76947612Sdab 	str_keyid[3] = (dir == DIR_ENCRYPT)
77047612Sdab 			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
77147612Sdab 	if (saveit) {
77247612Sdab 		struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
773*69784Sdab 		memmove(kp->keyid, keyid, keylen);
77447612Sdab 		kp->keylen = keylen;
77547612Sdab 	}
77647612Sdab 
77747612Sdab 	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
77847612Sdab 		if ((*strp++ = *keyid++) == IAC)
77947612Sdab 			*strp++ = IAC;
78047612Sdab 	}
78147612Sdab 	*strp++ = IAC;
78247612Sdab 	*strp++ = SE;
78347612Sdab 	net_write(str_keyid, strp - str_keyid);
78447612Sdab 	printsub('>', &str_keyid[2], strp - str_keyid - 2);
78546801Sdab }
78646801Sdab 
78746801Sdab 	void
encrypt_auto(on)78847612Sdab encrypt_auto(on)
78947612Sdab 	int on;
79047612Sdab {
79147612Sdab 	if (on < 0)
79247612Sdab 		autoencrypt ^= 1;
79347612Sdab 	else
79447612Sdab 		autoencrypt = on ? 1 : 0;
79547612Sdab }
79647612Sdab 
79747612Sdab 	void
decrypt_auto(on)79847612Sdab decrypt_auto(on)
79947612Sdab 	int on;
80047612Sdab {
80147612Sdab 	if (on < 0)
80247612Sdab 		autodecrypt ^= 1;
80347612Sdab 	else
80447612Sdab 		autodecrypt = on ? 1 : 0;
80547612Sdab }
80647612Sdab 
80747612Sdab 	void
encrypt_start_output(type)80846801Sdab encrypt_start_output(type)
80946801Sdab 	int type;
81046801Sdab {
81146801Sdab 	Encryptions *ep;
81247612Sdab 	register unsigned char *p;
81347612Sdab 	register int i;
81446801Sdab 
81546801Sdab 	if (!(ep = findencryption(type))) {
81646801Sdab 		if (encrypt_debug_mode) {
81747612Sdab 			printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
81846801Sdab 				Name,
81947612Sdab 				ENCTYPE_NAME_OK(type)
82047612Sdab 					? ENCTYPE_NAME(type) : "(unknown)",
82147612Sdab 				type);
82246801Sdab 		}
82346801Sdab 		return;
82446801Sdab 	}
82546801Sdab 	if (ep->start) {
82647612Sdab 		i = (*ep->start)(DIR_ENCRYPT, Server);
82747612Sdab 		if (encrypt_debug_mode) {
82847612Sdab 			printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
829*69784Sdab 				Name,
83047612Sdab 				(i < 0) ? "failed" :
83147612Sdab 					"initial negotiation in progress",
83247612Sdab 				i, ENCTYPE_NAME(type));
83347612Sdab 		}
83447612Sdab 		if (i)
83546801Sdab 			return;
83646801Sdab 	}
83747612Sdab 	p = str_start + 3;
83847612Sdab 	*p++ = ENCRYPT_START;
83947612Sdab 	for (i = 0; i < ki[0].keylen; ++i) {
84047612Sdab 		if ((*p++ = ki[0].keyid[i]) == IAC)
84147612Sdab 			*p++ = IAC;
84247612Sdab 	}
84347612Sdab 	*p++ = IAC;
84447612Sdab 	*p++ = SE;
84547612Sdab 	net_write(str_start, p - str_start);
84646801Sdab 	net_encrypt();
84747612Sdab 	printsub('>', &str_start[2], p - &str_start[2]);
84846801Sdab 	/*
84946801Sdab 	 * If we are already encrypting in some mode, then
85046801Sdab 	 * encrypt the ring (which includes our request) in
85146801Sdab 	 * the old mode, mark it all as "clear text" and then
85246801Sdab 	 * switch to the new mode.
85346801Sdab 	 */
85446801Sdab 	encrypt_output = ep->output;
85546801Sdab 	encrypt_mode = type;
85646801Sdab 	if (encrypt_debug_mode)
85746801Sdab 		printf(">>>%s: Started to encrypt output with type %s\r\n",
85846801Sdab 			Name, ENCTYPE_NAME(type));
85946801Sdab 	if (encrypt_verbose)
86046801Sdab 		printf("[ Output is now encrypted with type %s ]\r\n",
86146801Sdab 			ENCTYPE_NAME(type));
86246801Sdab }
86346801Sdab 
86446801Sdab 	void
encrypt_send_end()86546801Sdab encrypt_send_end()
86646801Sdab {
86746801Sdab 	if (!encrypt_output)
86846801Sdab 		return;
86946801Sdab 
87046801Sdab 	str_end[3] = ENCRYPT_END;
87146801Sdab 	net_write(str_end, sizeof(str_end));
87246801Sdab 	net_encrypt();
87346801Sdab 	printsub('>', &str_end[2], sizeof(str_end) - 2);
87446801Sdab 	/*
87546801Sdab 	 * Encrypt the output buffer now because it will not be done by
87646801Sdab 	 * netflush...
87746801Sdab 	 */
87846801Sdab 	encrypt_output = 0;
87946801Sdab 	if (encrypt_debug_mode)
88046801Sdab 		printf(">>>%s: Output is back to clear text\r\n", Name);
88146801Sdab 	if (encrypt_verbose)
88246801Sdab 		printf("[ Output is now clear text ]\r\n");
88346801Sdab }
88446801Sdab 
88546801Sdab 	void
encrypt_send_request_start()88646801Sdab encrypt_send_request_start()
88746801Sdab {
88847612Sdab 	register unsigned char *p;
88947612Sdab 	register int i;
89046801Sdab 
89147612Sdab 	p = &str_start[3];
89247612Sdab 	*p++ = ENCRYPT_REQSTART;
89347612Sdab 	for (i = 0; i < ki[1].keylen; ++i) {
89447612Sdab 		if ((*p++ = ki[1].keyid[i]) == IAC)
89547612Sdab 			*p++ = IAC;
89646801Sdab 	}
89747612Sdab 	*p++ = IAC;
89847612Sdab 	*p++ = SE;
89947612Sdab 	net_write(str_start, p - str_start);
90047612Sdab 	printsub('>', &str_start[2], p - &str_start[2]);
90146801Sdab 	if (encrypt_debug_mode)
90246801Sdab 		printf(">>>%s: Request input to be encrypted\r\n", Name);
90346801Sdab }
90446801Sdab 
90546801Sdab 	void
encrypt_send_request_end()90646801Sdab encrypt_send_request_end()
90746801Sdab {
90846801Sdab 	str_end[3] = ENCRYPT_REQEND;
90946801Sdab 	net_write(str_end, sizeof(str_end));
91046801Sdab 	printsub('>', &str_end[2], sizeof(str_end) - 2);
91146801Sdab 
91246801Sdab 	if (encrypt_debug_mode)
91346801Sdab 		printf(">>>%s: Request input to be clear text\r\n", Name);
91446801Sdab }
91546801Sdab 
91646801Sdab 	void
encrypt_wait()91746801Sdab encrypt_wait()
91846801Sdab {
91946801Sdab 	register int encrypt, decrypt;
92046801Sdab 	if (encrypt_debug_mode)
92146801Sdab 		printf(">>>%s: in encrypt_wait\r\n", Name);
92247612Sdab 	if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
92346801Sdab 		return;
92446801Sdab 	while (autoencrypt && !encrypt_output)
92546801Sdab 		if (telnet_spin())
92646801Sdab 			return;
92746801Sdab }
92846801Sdab 
92946801Sdab 	void
encrypt_debug(mode)93046801Sdab encrypt_debug(mode)
93146801Sdab 	int mode;
93246801Sdab {
93346801Sdab 	encrypt_debug_mode = mode;
93446801Sdab }
93546801Sdab 
93646801Sdab 	void
encrypt_gen_printsub(data,cnt,buf,buflen)93746801Sdab encrypt_gen_printsub(data, cnt, buf, buflen)
93846801Sdab 	unsigned char *data, *buf;
93946801Sdab 	int cnt, buflen;
94046801Sdab {
94146801Sdab 	char tbuf[16], *cp;
94246801Sdab 
94346801Sdab 	cnt -= 2;
94446801Sdab 	data += 2;
94546801Sdab 	buf[buflen-1] = '\0';
94646801Sdab 	buf[buflen-2] = '*';
94746801Sdab 	buflen -= 2;;
94846801Sdab 	for (; cnt > 0; cnt--, data++) {
94946801Sdab 		sprintf(tbuf, " %d", *data);
95046801Sdab 		for (cp = tbuf; *cp && buflen > 0; --buflen)
95146801Sdab 			*buf++ = *cp++;
95246801Sdab 		if (buflen <= 0)
95346801Sdab 			return;
95446801Sdab 	}
95546801Sdab 	*buf = '\0';
95646801Sdab }
95746801Sdab 
95846801Sdab 	void
encrypt_printsub(data,cnt,buf,buflen)95946801Sdab encrypt_printsub(data, cnt, buf, buflen)
96046801Sdab 	unsigned char *data, *buf;
96146801Sdab 	int cnt, buflen;
96246801Sdab {
96346801Sdab 	Encryptions *ep;
96446801Sdab 	register int type = data[1];
96546801Sdab 
96646801Sdab 	for (ep = encryptions; ep->type && ep->type != type; ep++)
96746801Sdab 		;
96846801Sdab 
96946801Sdab 	if (ep->printsub)
97046801Sdab 		(*ep->printsub)(data, cnt, buf, buflen);
97146801Sdab 	else
97246801Sdab 		encrypt_gen_printsub(data, cnt, buf, buflen);
97346801Sdab }
97460150Sdab #endif	/* ENCRYPTION */
975