129088Smarkm/*-
229088Smarkm * Copyright (c) 1991, 1993
329088Smarkm *	The Regents of the University of California.  All rights reserved.
429088Smarkm *
529088Smarkm * Redistribution and use in source and binary forms, with or without
629088Smarkm * modification, are permitted provided that the following conditions
729088Smarkm * are met:
829088Smarkm * 1. Redistributions of source code must retain the above copyright
929088Smarkm *    notice, this list of conditions and the following disclaimer.
1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1129088Smarkm *    notice, this list of conditions and the following disclaimer in the
1229088Smarkm *    documentation and/or other materials provided with the distribution.
1329088Smarkm * 3. All advertising materials mentioning features or use of this software
1429088Smarkm *    must display the following acknowledgement:
1529088Smarkm *	This product includes software developed by the University of
1629088Smarkm *	California, Berkeley and its contributors.
1729088Smarkm * 4. Neither the name of the University nor the names of its contributors
1829088Smarkm *    may be used to endorse or promote products derived from this software
1929088Smarkm *    without specific prior written permission.
2029088Smarkm *
2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2429088Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3129088Smarkm * SUCH DAMAGE.
3229088Smarkm */
3329088Smarkm
3484305Smarkm#include <sys/cdefs.h>
3587139Smarkm
3684305Smarkm__FBSDID("$FreeBSD$");
3784305Smarkm
3829088Smarkm#ifndef lint
3963248Speter#if 0
4029181Smarkmstatic const char sccsid[] = "@(#)encrypt.c	8.2 (Berkeley) 5/30/95";
4163248Speter#endif
4229088Smarkm#endif /* not lint */
4329088Smarkm
4429088Smarkm/*
4529088Smarkm * Copyright (C) 1990 by the Massachusetts Institute of Technology
4629088Smarkm *
4729088Smarkm * Export of this software from the United States of America is assumed
4829088Smarkm * to require a specific license from the United States Government.
4929088Smarkm * It is the responsibility of any person or organization contemplating
5029088Smarkm * export to obtain such a license before exporting.
5129088Smarkm *
5229088Smarkm * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
5329088Smarkm * distribute this software and its documentation for any purpose and
5429088Smarkm * without fee is hereby granted, provided that the above copyright
5529088Smarkm * notice appear in all copies and that both that copyright notice and
5629088Smarkm * this permission notice appear in supporting documentation, and that
5729088Smarkm * the name of M.I.T. not be used in advertising or publicity pertaining
5829088Smarkm * to distribution of the software without specific, written prior
5929088Smarkm * permission.  M.I.T. makes no representations about the suitability of
6029088Smarkm * this software for any purpose.  It is provided "as is" without express
6129088Smarkm * or implied warranty.
6229088Smarkm */
6329088Smarkm
6429088Smarkm#ifdef	ENCRYPTION
6529088Smarkm
6698884Smarkm#include <sys/types.h>
6729088Smarkm#define	ENCRYPT_NAMES
6887139Smarkm#include <arpa/telnet.h>
6929181Smarkm#include <stdio.h>
7087139Smarkm#include <stdlib.h>
7187139Smarkm#include <string.h>
7229088Smarkm
7329088Smarkm#include "encrypt.h"
7429088Smarkm#include "misc.h"
7529088Smarkm
7629088Smarkm/*
7729088Smarkm * These functions pointers point to the current routines
7829088Smarkm * for encrypting and decrypting data.
7929088Smarkm */
8087155Smarkmvoid	(*encrypt_output)(unsigned char *, int);
8187155Smarkmint	(*decrypt_input)(int);
8229088Smarkm
8329181Smarkmint EncryptType(char *type, char *mode);
8429181Smarkmint EncryptStart(char *mode);
8529181Smarkmint EncryptStop(char *mode);
8629181Smarkmint EncryptStartInput(void);
8729181Smarkmint EncryptStartOutput(void);
8829181Smarkmint EncryptStopInput(void);
8929181Smarkmint EncryptStopOutput(void);
9029181Smarkm
9129088Smarkmint encrypt_debug_mode = 0;
9229088Smarkmstatic int decrypt_mode = 0;
9329088Smarkmstatic int encrypt_mode = 0;
9429088Smarkmstatic int encrypt_verbose = 0;
9529088Smarkmstatic int autoencrypt = 0;
9629088Smarkmstatic int autodecrypt = 0;
9729088Smarkmstatic int havesessionkey = 0;
9829088Smarkmstatic int Server = 0;
9987139Smarkmstatic const char *Name = "Noname";
10029088Smarkm
10129088Smarkm#define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
10229088Smarkm
10398884Smarkmstatic u_long i_support_encrypt = 0
10449887Snsayer | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
10549887Snsayer |0;
10698884Smarkmstatic u_long i_support_decrypt = 0
10749887Snsayer | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
10849887Snsayer |0;
10949887Snsayer
11098884Smarkmstatic u_long i_wont_support_encrypt = 0;
11198884Smarkmstatic u_long i_wont_support_decrypt = 0;
11229088Smarkm#define	I_SUPPORT_ENCRYPT	(i_support_encrypt & ~i_wont_support_encrypt)
11329088Smarkm#define	I_SUPPORT_DECRYPT	(i_support_decrypt & ~i_wont_support_decrypt)
11429088Smarkm
11598884Smarkmstatic u_long remote_supports_encrypt = 0;
11698884Smarkmstatic u_long remote_supports_decrypt = 0;
11729088Smarkm
11829088Smarkmstatic Encryptions encryptions[] = {
11929088Smarkm    { "DES_CFB64",	ENCTYPE_DES_CFB64,
12029088Smarkm			cfb64_encrypt,
12129088Smarkm			cfb64_decrypt,
12229088Smarkm			cfb64_init,
12329088Smarkm			cfb64_start,
12429088Smarkm			cfb64_is,
12529088Smarkm			cfb64_reply,
12629088Smarkm			cfb64_session,
12729088Smarkm			cfb64_keyid,
12829088Smarkm			cfb64_printsub },
12929088Smarkm    { "DES_OFB64",	ENCTYPE_DES_OFB64,
13029088Smarkm			ofb64_encrypt,
13129088Smarkm			ofb64_decrypt,
13229088Smarkm			ofb64_init,
13329088Smarkm			ofb64_start,
13429088Smarkm			ofb64_is,
13529088Smarkm			ofb64_reply,
13629088Smarkm			ofb64_session,
13729088Smarkm			ofb64_keyid,
13829088Smarkm			ofb64_printsub },
13987139Smarkm    { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
14029088Smarkm};
14129088Smarkm
14229088Smarkmstatic unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
14329088Smarkm					 ENCRYPT_SUPPORT };
14429088Smarkmstatic unsigned char str_suplen = 0;
14529088Smarkmstatic unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
14629088Smarkmstatic unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
14729088Smarkm
14887139SmarkmEncryptions *
14987139Smarkmfindencryption(int type)
15029088Smarkm{
15129088Smarkm	Encryptions *ep = encryptions;
15229088Smarkm
15387139Smarkm	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type)))
15429088Smarkm		return(0);
15529088Smarkm	while (ep->type && ep->type != type)
15629088Smarkm		++ep;
15729088Smarkm	return(ep->type ? ep : 0);
15829088Smarkm}
15929088Smarkm
16087139Smarkmstatic Encryptions *
16187139Smarkmfinddecryption(int type)
16229088Smarkm{
16329088Smarkm	Encryptions *ep = encryptions;
16429088Smarkm
16587139Smarkm	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type)))
16629088Smarkm		return(0);
16729088Smarkm	while (ep->type && ep->type != type)
16829088Smarkm		++ep;
16929088Smarkm	return(ep->type ? ep : 0);
17029088Smarkm}
17129088Smarkm
17229088Smarkm#define	MAXKEYLEN 64
17329088Smarkm
17429088Smarkmstatic struct key_info {
17529088Smarkm	unsigned char keyid[MAXKEYLEN];
17629088Smarkm	int keylen;
17729088Smarkm	int dir;
17829088Smarkm	int *modep;
17987139Smarkm	Encryptions *(*getcrypt)(int);
18029088Smarkm} ki[2] = {
18129088Smarkm	{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
18229088Smarkm	{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
18329088Smarkm};
18429088Smarkm
18529181Smarkmstatic void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len);
18629181Smarkm
18787139Smarkmvoid
18887139Smarkmencrypt_init(const char *name, int server)
18929088Smarkm{
19029088Smarkm	Encryptions *ep = encryptions;
19129088Smarkm
19229088Smarkm	Name = name;
19329088Smarkm	Server = server;
19429088Smarkm	i_support_encrypt = i_support_decrypt = 0;
19529088Smarkm	remote_supports_encrypt = remote_supports_decrypt = 0;
19629088Smarkm	encrypt_mode = 0;
19729088Smarkm	decrypt_mode = 0;
19829088Smarkm	encrypt_output = 0;
19929088Smarkm	decrypt_input = 0;
20029088Smarkm
20129088Smarkm	str_suplen = 4;
20229088Smarkm
20329088Smarkm	while (ep->type) {
20429088Smarkm		if (encrypt_debug_mode)
20529088Smarkm			printf(">>>%s: I will support %s\r\n",
20629088Smarkm				Name, ENCTYPE_NAME(ep->type));
20729088Smarkm		i_support_encrypt |= typemask(ep->type);
20829088Smarkm		i_support_decrypt |= typemask(ep->type);
20929088Smarkm		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
21029088Smarkm			if ((str_send[str_suplen++] = ep->type) == IAC)
21129088Smarkm				str_send[str_suplen++] = IAC;
21229088Smarkm		if (ep->init)
21329088Smarkm			(*ep->init)(Server);
21429088Smarkm		++ep;
21529088Smarkm	}
21629088Smarkm	str_send[str_suplen++] = IAC;
21729088Smarkm	str_send[str_suplen++] = SE;
21829088Smarkm}
21929088Smarkm
22087139Smarkmstatic void
22187139Smarkmencrypt_list_types(void)
22229088Smarkm{
22329088Smarkm	Encryptions *ep = encryptions;
22429088Smarkm
22529088Smarkm	printf("Valid encryption types:\n");
22629088Smarkm	while (ep->type) {
22729088Smarkm		printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
22829088Smarkm		++ep;
22929088Smarkm	}
23029088Smarkm}
23129088Smarkm
23287139Smarkmint
23387139SmarkmEncryptEnable(char *type, char *mode)
23429088Smarkm{
23529088Smarkm	if (isprefix(type, "help") || isprefix(type, "?")) {
23629088Smarkm		printf("Usage: encrypt enable <type> [input|output]\n");
23729088Smarkm		encrypt_list_types();
23829088Smarkm		return(0);
23929088Smarkm	}
24029088Smarkm	if (EncryptType(type, mode))
24129088Smarkm		return(EncryptStart(mode));
24229088Smarkm	return(0);
24329088Smarkm}
24429088Smarkm
24587139Smarkmint
24687139SmarkmEncryptDisable(char *type, char *mode)
24729088Smarkm{
24887139Smarkm	Encryptions *ep;
24929088Smarkm	int ret = 0;
25029088Smarkm
25129088Smarkm	if (isprefix(type, "help") || isprefix(type, "?")) {
25229088Smarkm		printf("Usage: encrypt disable <type> [input|output]\n");
25329088Smarkm		encrypt_list_types();
25429181Smarkm	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
25529088Smarkm						sizeof(Encryptions))) == 0) {
25629088Smarkm		printf("%s: invalid encryption type\n", type);
25729181Smarkm	} else if (Ambiguous((char **)ep)) {
25829088Smarkm		printf("Ambiguous type '%s'\n", type);
25929088Smarkm	} else {
26029088Smarkm		if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
26129088Smarkm			if (decrypt_mode == ep->type)
26229088Smarkm				EncryptStopInput();
26329088Smarkm			i_wont_support_decrypt |= typemask(ep->type);
26429088Smarkm			ret = 1;
26529088Smarkm		}
26629088Smarkm		if ((mode == 0) || (isprefix(mode, "output"))) {
26729088Smarkm			if (encrypt_mode == ep->type)
26829088Smarkm				EncryptStopOutput();
26929088Smarkm			i_wont_support_encrypt |= typemask(ep->type);
27029088Smarkm			ret = 1;
27129088Smarkm		}
27229088Smarkm		if (ret == 0)
27329088Smarkm			printf("%s: invalid encryption mode\n", mode);
27429088Smarkm	}
27529088Smarkm	return(ret);
27629088Smarkm}
27729088Smarkm
27887139Smarkmint
27987139SmarkmEncryptType(char *type, char *mode)
28029088Smarkm{
28187139Smarkm	Encryptions *ep;
28229088Smarkm	int ret = 0;
28329088Smarkm
28429088Smarkm	if (isprefix(type, "help") || isprefix(type, "?")) {
28529088Smarkm		printf("Usage: encrypt type <type> [input|output]\n");
28629088Smarkm		encrypt_list_types();
28729181Smarkm	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
28829088Smarkm						sizeof(Encryptions))) == 0) {
28929088Smarkm		printf("%s: invalid encryption type\n", type);
29029181Smarkm	} else if (Ambiguous((char **)ep)) {
29129088Smarkm		printf("Ambiguous type '%s'\n", type);
29229088Smarkm	} else {
29329088Smarkm		if ((mode == 0) || isprefix(mode, "input")) {
29429088Smarkm			decrypt_mode = ep->type;
29529088Smarkm			i_wont_support_decrypt &= ~typemask(ep->type);
29629088Smarkm			ret = 1;
29729088Smarkm		}
29829088Smarkm		if ((mode == 0) || isprefix(mode, "output")) {
29929088Smarkm			encrypt_mode = ep->type;
30029088Smarkm			i_wont_support_encrypt &= ~typemask(ep->type);
30129088Smarkm			ret = 1;
30229088Smarkm		}
30329088Smarkm		if (ret == 0)
30429088Smarkm			printf("%s: invalid encryption mode\n", mode);
30529088Smarkm	}
30629088Smarkm	return(ret);
30729088Smarkm}
30829088Smarkm
30987139Smarkmint
31087139SmarkmEncryptStart(char *mode)
31129088Smarkm{
31287139Smarkm	int ret = 0;
31329088Smarkm	if (mode) {
31429088Smarkm		if (isprefix(mode, "input"))
31529088Smarkm			return(EncryptStartInput());
31629088Smarkm		if (isprefix(mode, "output"))
31729088Smarkm			return(EncryptStartOutput());
31829088Smarkm		if (isprefix(mode, "help") || isprefix(mode, "?")) {
31929088Smarkm			printf("Usage: encrypt start [input|output]\n");
32029088Smarkm			return(0);
32129088Smarkm		}
32229088Smarkm		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
32329088Smarkm		return(0);
32429088Smarkm	}
32529088Smarkm	ret += EncryptStartInput();
32629088Smarkm	ret += EncryptStartOutput();
32729088Smarkm	return(ret);
32829088Smarkm}
32929088Smarkm
33087139Smarkmint
33187139SmarkmEncryptStartInput(void)
33229088Smarkm{
33329088Smarkm	if (decrypt_mode) {
33429088Smarkm		encrypt_send_request_start();
33529088Smarkm		return(1);
33629088Smarkm	}
33729088Smarkm	printf("No previous decryption mode, decryption not enabled\r\n");
33829088Smarkm	return(0);
33929088Smarkm}
34029088Smarkm
34187139Smarkmint
34287139SmarkmEncryptStartOutput(void)
34329088Smarkm{
34429088Smarkm	if (encrypt_mode) {
34529088Smarkm		encrypt_start_output(encrypt_mode);
34629088Smarkm		return(1);
34729088Smarkm	}
34829088Smarkm	printf("No previous encryption mode, encryption not enabled\r\n");
34929088Smarkm	return(0);
35029088Smarkm}
35129088Smarkm
35287139Smarkmint
35387139SmarkmEncryptStop(char *mode)
35429088Smarkm{
35529088Smarkm	int ret = 0;
35629088Smarkm	if (mode) {
35729088Smarkm		if (isprefix(mode, "input"))
35829088Smarkm			return(EncryptStopInput());
35929088Smarkm		if (isprefix(mode, "output"))
36029088Smarkm			return(EncryptStopOutput());
36129088Smarkm		if (isprefix(mode, "help") || isprefix(mode, "?")) {
36229088Smarkm			printf("Usage: encrypt stop [input|output]\n");
36329088Smarkm			return(0);
36429088Smarkm		}
36529088Smarkm		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
36629088Smarkm		return(0);
36729088Smarkm	}
36829088Smarkm	ret += EncryptStopInput();
36929088Smarkm	ret += EncryptStopOutput();
37029088Smarkm	return(ret);
37129088Smarkm}
37229088Smarkm
37387139Smarkmint
37487139SmarkmEncryptStopInput(void)
37529088Smarkm{
37629088Smarkm	encrypt_send_request_end();
37729088Smarkm	return(1);
37829088Smarkm}
37929088Smarkm
38087139Smarkmint
38187139SmarkmEncryptStopOutput(void)
38229088Smarkm{
38329088Smarkm	encrypt_send_end();
38429088Smarkm	return(1);
38529088Smarkm}
38629088Smarkm
38787139Smarkmvoid
38887139Smarkmencrypt_display(void)
38929088Smarkm{
39029088Smarkm	if (encrypt_output)
39129088Smarkm		printf("Currently encrypting output with %s\r\n",
39229088Smarkm			ENCTYPE_NAME(encrypt_mode));
39329088Smarkm	if (decrypt_input)
39429088Smarkm		printf("Currently decrypting input with %s\r\n",
39529088Smarkm			ENCTYPE_NAME(decrypt_mode));
39629088Smarkm}
39729088Smarkm
39887139Smarkmint
39987139SmarkmEncryptStatus(void)
40029088Smarkm{
40129088Smarkm	if (encrypt_output)
40229088Smarkm		printf("Currently encrypting output with %s\r\n",
40329088Smarkm			ENCTYPE_NAME(encrypt_mode));
40429088Smarkm	else if (encrypt_mode) {
40529088Smarkm		printf("Currently output is clear text.\r\n");
40629088Smarkm		printf("Last encryption mode was %s\r\n",
40729088Smarkm			ENCTYPE_NAME(encrypt_mode));
40829088Smarkm	}
40929088Smarkm	if (decrypt_input) {
41029088Smarkm		printf("Currently decrypting input with %s\r\n",
41129088Smarkm			ENCTYPE_NAME(decrypt_mode));
41229088Smarkm	} else if (decrypt_mode) {
41329088Smarkm		printf("Currently input is clear text.\r\n");
41429088Smarkm		printf("Last decryption mode was %s\r\n",
41529088Smarkm			ENCTYPE_NAME(decrypt_mode));
41629088Smarkm	}
41729088Smarkm	return 1;
41829088Smarkm}
41929088Smarkm
42087139Smarkmvoid
42187139Smarkmencrypt_send_support(void)
42229088Smarkm{
42329088Smarkm	if (str_suplen) {
42429088Smarkm		/*
42529088Smarkm		 * If the user has requested that decryption start
42629088Smarkm		 * immediatly, then send a "REQUEST START" before
42729088Smarkm		 * we negotiate the type.
42829088Smarkm		 */
42929088Smarkm		if (!Server && autodecrypt)
43029088Smarkm			encrypt_send_request_start();
43129088Smarkm		net_write(str_send, str_suplen);
43229088Smarkm		printsub('>', &str_send[2], str_suplen - 2);
43329088Smarkm		str_suplen = 0;
43429088Smarkm	}
43529088Smarkm}
43629088Smarkm
43787139Smarkmint
43887139SmarkmEncryptDebug(int on)
43929088Smarkm{
44029088Smarkm	if (on < 0)
44129088Smarkm		encrypt_debug_mode ^= 1;
44229088Smarkm	else
44329088Smarkm		encrypt_debug_mode = on;
44429088Smarkm	printf("Encryption debugging %s\r\n",
44529088Smarkm		encrypt_debug_mode ? "enabled" : "disabled");
44629088Smarkm	return(1);
44729088Smarkm}
44829088Smarkm
44987139Smarkmint
45087139SmarkmEncryptVerbose(int on)
45129088Smarkm{
45229088Smarkm	if (on < 0)
45329088Smarkm		encrypt_verbose ^= 1;
45429088Smarkm	else
45529088Smarkm		encrypt_verbose = on;
45629088Smarkm	printf("Encryption %s verbose\r\n",
45729088Smarkm		encrypt_verbose ? "is" : "is not");
45829088Smarkm	return(1);
45929088Smarkm}
46029088Smarkm
46187139Smarkmint
46287139SmarkmEncryptAutoEnc(int on)
46329088Smarkm{
46429088Smarkm	encrypt_auto(on);
46529088Smarkm	printf("Automatic encryption of output is %s\r\n",
46629088Smarkm		autoencrypt ? "enabled" : "disabled");
46729088Smarkm	return(1);
46829088Smarkm}
46929088Smarkm
47087139Smarkmint
47187139SmarkmEncryptAutoDec(int on)
47229088Smarkm{
47329088Smarkm	decrypt_auto(on);
47429088Smarkm	printf("Automatic decryption of input is %s\r\n",
47529088Smarkm		autodecrypt ? "enabled" : "disabled");
47629088Smarkm	return(1);
47729088Smarkm}
47829088Smarkm
47929088Smarkm/*
48029088Smarkm * Called when ENCRYPT SUPPORT is received.
48129088Smarkm */
48287139Smarkmvoid
48387139Smarkmencrypt_support(unsigned char *typelist, int cnt)
48429088Smarkm{
48587139Smarkm	int type, use_type = 0;
48629088Smarkm	Encryptions *ep;
48729088Smarkm
48829088Smarkm	/*
48929088Smarkm	 * Forget anything the other side has previously told us.
49029088Smarkm	 */
49129088Smarkm	remote_supports_decrypt = 0;
49229088Smarkm
49329088Smarkm	while (cnt-- > 0) {
49429088Smarkm		type = *typelist++;
49529088Smarkm		if (encrypt_debug_mode)
49629088Smarkm			printf(">>>%s: He is supporting %s (%d)\r\n",
49729088Smarkm				Name,
49829088Smarkm				ENCTYPE_NAME(type), type);
49929088Smarkm		if ((type < ENCTYPE_CNT) &&
50029088Smarkm		    (I_SUPPORT_ENCRYPT & typemask(type))) {
50129088Smarkm			remote_supports_decrypt |= typemask(type);
50229088Smarkm			if (use_type == 0)
50329088Smarkm				use_type = type;
50429088Smarkm		}
50529088Smarkm	}
50629088Smarkm	if (use_type) {
50729088Smarkm		ep = findencryption(use_type);
50829088Smarkm		if (!ep)
50929088Smarkm			return;
51029088Smarkm		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
51129088Smarkm		if (encrypt_debug_mode)
51229088Smarkm			printf(">>>%s: (*ep->start)() returned %d\r\n",
51329088Smarkm					Name, type);
51429088Smarkm		if (type < 0)
51529088Smarkm			return;
51629088Smarkm		encrypt_mode = use_type;
51729088Smarkm		if (type == 0)
51829088Smarkm			encrypt_start_output(use_type);
51929088Smarkm	}
52029088Smarkm}
52129088Smarkm
52287139Smarkmvoid
52387139Smarkmencrypt_is(unsigned char *data, int cnt)
52429088Smarkm{
52529088Smarkm	Encryptions *ep;
52687139Smarkm	int type, ret;
52729088Smarkm
52829088Smarkm	if (--cnt < 0)
52929088Smarkm		return;
53029088Smarkm	type = *data++;
53129088Smarkm	if (type < ENCTYPE_CNT)
53229088Smarkm		remote_supports_encrypt |= typemask(type);
53329088Smarkm	if (!(ep = finddecryption(type))) {
53429088Smarkm		if (encrypt_debug_mode)
53529088Smarkm			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
53629088Smarkm				Name,
53729088Smarkm				ENCTYPE_NAME_OK(type)
53829088Smarkm					? ENCTYPE_NAME(type) : "(unknown)",
53929088Smarkm				type);
54029088Smarkm		return;
54129088Smarkm	}
54229088Smarkm	if (!ep->is) {
54329088Smarkm		if (encrypt_debug_mode)
54429088Smarkm			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
54529088Smarkm				Name,
54629088Smarkm				ENCTYPE_NAME_OK(type)
54729088Smarkm					? ENCTYPE_NAME(type) : "(unknown)",
54829088Smarkm				type);
54929088Smarkm		ret = 0;
55029088Smarkm	} else {
55129088Smarkm		ret = (*ep->is)(data, cnt);
55229088Smarkm		if (encrypt_debug_mode)
55329181Smarkm			printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
55429088Smarkm				(ret < 0) ? "FAIL " :
55529088Smarkm				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
55629088Smarkm	}
55729088Smarkm	if (ret < 0) {
55829088Smarkm		autodecrypt = 0;
55929088Smarkm	} else {
56029088Smarkm		decrypt_mode = type;
56129088Smarkm		if (ret == 0 && autodecrypt)
56229088Smarkm			encrypt_send_request_start();
56329088Smarkm	}
56429088Smarkm}
56529088Smarkm
56687139Smarkmvoid
56787139Smarkmencrypt_reply(unsigned char *data, int cnt)
56829088Smarkm{
56929088Smarkm	Encryptions *ep;
57087139Smarkm	int ret, type;
57129088Smarkm
57229088Smarkm	if (--cnt < 0)
57329088Smarkm		return;
57429088Smarkm	type = *data++;
57529088Smarkm	if (!(ep = findencryption(type))) {
57629088Smarkm		if (encrypt_debug_mode)
57729088Smarkm			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
57829088Smarkm				Name,
57929088Smarkm				ENCTYPE_NAME_OK(type)
58029088Smarkm					? ENCTYPE_NAME(type) : "(unknown)",
58129088Smarkm				type);
58229088Smarkm		return;
58329088Smarkm	}
58429088Smarkm	if (!ep->reply) {
58529088Smarkm		if (encrypt_debug_mode)
58629088Smarkm			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
58729088Smarkm				Name,
58829088Smarkm				ENCTYPE_NAME_OK(type)
58929088Smarkm					? ENCTYPE_NAME(type) : "(unknown)",
59029088Smarkm				type);
59129088Smarkm		ret = 0;
59229088Smarkm	} else {
59329088Smarkm		ret = (*ep->reply)(data, cnt);
59429088Smarkm		if (encrypt_debug_mode)
59529181Smarkm			printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
59629088Smarkm				data, cnt,
59729088Smarkm				(ret < 0) ? "FAIL " :
59829088Smarkm				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
59929088Smarkm	}
60029088Smarkm	if (encrypt_debug_mode)
60129088Smarkm		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
60229088Smarkm	if (ret < 0) {
60329088Smarkm		autoencrypt = 0;
60429088Smarkm	} else {
60529088Smarkm		encrypt_mode = type;
60629088Smarkm		if (ret == 0 && autoencrypt)
60729088Smarkm			encrypt_start_output(type);
60829088Smarkm	}
60929088Smarkm}
61029088Smarkm
61129088Smarkm/*
61229088Smarkm * Called when a ENCRYPT START command is received.
61329088Smarkm */
61487139Smarkmvoid
61587139Smarkmencrypt_start(unsigned char *data __unused, int cnt __unused)
61629088Smarkm{
61729088Smarkm	Encryptions *ep;
61829088Smarkm
61929088Smarkm	if (!decrypt_mode) {
62029088Smarkm		/*
62129088Smarkm		 * Something is wrong.  We should not get a START
62229088Smarkm		 * command without having already picked our
62329088Smarkm		 * decryption scheme.  Send a REQUEST-END to
62429088Smarkm		 * attempt to clear the channel...
62529088Smarkm		 */
62629088Smarkm		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
62729088Smarkm		encrypt_send_request_end();
62829088Smarkm		return;
62929088Smarkm	}
63029088Smarkm
63129181Smarkm	if ((ep = finddecryption(decrypt_mode))) {
63229088Smarkm		decrypt_input = ep->input;
63329088Smarkm		if (encrypt_verbose)
63429088Smarkm			printf("[ Input is now decrypted with type %s ]\r\n",
63529088Smarkm				ENCTYPE_NAME(decrypt_mode));
63629088Smarkm		if (encrypt_debug_mode)
63729088Smarkm			printf(">>>%s: Start to decrypt input with type %s\r\n",
63829088Smarkm				Name, ENCTYPE_NAME(decrypt_mode));
63929088Smarkm	} else {
64029088Smarkm		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
64129088Smarkm				Name,
64229088Smarkm				ENCTYPE_NAME_OK(decrypt_mode)
64329088Smarkm					? ENCTYPE_NAME(decrypt_mode)
64429088Smarkm					: "(unknown)",
64529088Smarkm				decrypt_mode);
64629088Smarkm		encrypt_send_request_end();
64729088Smarkm	}
64829088Smarkm}
64929088Smarkm
65087139Smarkmvoid
65187139Smarkmencrypt_session_key( Session_Key *key, int server)
65229088Smarkm{
65329088Smarkm	Encryptions *ep = encryptions;
65429088Smarkm
65529088Smarkm	havesessionkey = 1;
65629088Smarkm
65729088Smarkm	while (ep->type) {
65829088Smarkm		if (ep->session)
65929088Smarkm			(*ep->session)(key, server);
66029088Smarkm		++ep;
66129088Smarkm	}
66229088Smarkm}
66329088Smarkm
66429088Smarkm/*
66529088Smarkm * Called when ENCRYPT END is received.
66629088Smarkm */
66787139Smarkmvoid
66887139Smarkmencrypt_end(void)
66929088Smarkm{
67029088Smarkm	decrypt_input = 0;
67129088Smarkm	if (encrypt_debug_mode)
67229088Smarkm		printf(">>>%s: Input is back to clear text\r\n", Name);
67329088Smarkm	if (encrypt_verbose)
67429088Smarkm		printf("[ Input is now clear text ]\r\n");
67529088Smarkm}
67629088Smarkm
67729088Smarkm/*
67829088Smarkm * Called when ENCRYPT REQUEST-END is received.
67929088Smarkm */
68087139Smarkmvoid
68187139Smarkmencrypt_request_end(void)
68229088Smarkm{
68329088Smarkm	encrypt_send_end();
68429088Smarkm}
68529088Smarkm
68629088Smarkm/*
68729088Smarkm * Called when ENCRYPT REQUEST-START is received.  If we receive
68829088Smarkm * this before a type is picked, then that indicates that the
68929088Smarkm * other side wants us to start encrypting data as soon as we
69029088Smarkm * can.
69129088Smarkm */
69287139Smarkmvoid
69387139Smarkmencrypt_request_start(unsigned char *data __unused, int cnt __unused)
69429088Smarkm{
69529088Smarkm	if (encrypt_mode == 0)  {
69629088Smarkm		if (Server)
69729088Smarkm			autoencrypt = 1;
69829088Smarkm		return;
69929088Smarkm	}
70029088Smarkm	encrypt_start_output(encrypt_mode);
70129088Smarkm}
70229088Smarkm
70329088Smarkmstatic unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
70429088Smarkm
70587139Smarkmvoid
70687139Smarkmencrypt_enc_keyid(unsigned char *keyid, int len)
70729088Smarkm{
70829088Smarkm	encrypt_keyid(&ki[1], keyid, len);
70929088Smarkm}
71029088Smarkm
71187139Smarkmvoid
71287139Smarkmencrypt_dec_keyid(unsigned char *keyid, int len)
71329088Smarkm{
71429088Smarkm	encrypt_keyid(&ki[0], keyid, len);
71529088Smarkm}
71629088Smarkm
71787139Smarkmvoid
71887139Smarkmencrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
71929088Smarkm{
72029088Smarkm	Encryptions *ep;
72129088Smarkm	int dir = kp->dir;
72287139Smarkm	int ret = 0;
72329088Smarkm
724228843Scperciva	if (len > MAXKEYLEN)
725228843Scperciva		len = MAXKEYLEN;
726228843Scperciva
72729088Smarkm	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
72829088Smarkm		if (len == 0)
72929088Smarkm			return;
73029088Smarkm		kp->keylen = 0;
73129088Smarkm	} else if (len == 0) {
73229088Smarkm		/*
73329088Smarkm		 * Empty option, indicates a failure.
73429088Smarkm		 */
73529088Smarkm		if (kp->keylen == 0)
73629088Smarkm			return;
73729088Smarkm		kp->keylen = 0;
73829088Smarkm		if (ep->keyid)
73929088Smarkm			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
74029088Smarkm
74129088Smarkm	} else if ((len != kp->keylen) ||
74229088Smarkm		   (memcmp(keyid, kp->keyid, len) != 0)) {
74329088Smarkm		/*
74429088Smarkm		 * Length or contents are different
74529088Smarkm		 */
74629088Smarkm		kp->keylen = len;
74729088Smarkm		memmove(kp->keyid, keyid, len);
74829088Smarkm		if (ep->keyid)
74929088Smarkm			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
75029088Smarkm	} else {
75129088Smarkm		if (ep->keyid)
75229088Smarkm			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
75329088Smarkm		if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
75429088Smarkm			encrypt_start_output(*kp->modep);
75529088Smarkm		return;
75629088Smarkm	}
75729088Smarkm
75829088Smarkm	encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
75929088Smarkm}
76029088Smarkm
76187139Smarkmvoid
76287139Smarkmencrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit)
76329088Smarkm{
76429088Smarkm	unsigned char *strp;
76529088Smarkm
76629088Smarkm	str_keyid[3] = (dir == DIR_ENCRYPT)
76729088Smarkm			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
76829088Smarkm	if (saveit) {
76929088Smarkm		struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
77029088Smarkm		memmove(kp->keyid, keyid, keylen);
77129088Smarkm		kp->keylen = keylen;
77229088Smarkm	}
77329088Smarkm
77429088Smarkm	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
77529088Smarkm		if ((*strp++ = *keyid++) == IAC)
77629088Smarkm			*strp++ = IAC;
77729088Smarkm	}
77829088Smarkm	*strp++ = IAC;
77929088Smarkm	*strp++ = SE;
78029088Smarkm	net_write(str_keyid, strp - str_keyid);
78129088Smarkm	printsub('>', &str_keyid[2], strp - str_keyid - 2);
78229088Smarkm}
78329088Smarkm
78487139Smarkmvoid
78587139Smarkmencrypt_auto(int on)
78629088Smarkm{
78729088Smarkm	if (on < 0)
78829088Smarkm		autoencrypt ^= 1;
78929088Smarkm	else
79029088Smarkm		autoencrypt = on ? 1 : 0;
79129088Smarkm}
79229088Smarkm
79387139Smarkmvoid
79487139Smarkmdecrypt_auto(int on)
79529088Smarkm{
79629088Smarkm	if (on < 0)
79729088Smarkm		autodecrypt ^= 1;
79829088Smarkm	else
79929088Smarkm		autodecrypt = on ? 1 : 0;
80029088Smarkm}
80129088Smarkm
80287139Smarkmvoid
80387139Smarkmencrypt_start_output(int type)
80429088Smarkm{
80529088Smarkm	Encryptions *ep;
80687139Smarkm	unsigned char *p;
80787139Smarkm	int i;
80829088Smarkm
80929088Smarkm	if (!(ep = findencryption(type))) {
81029088Smarkm		if (encrypt_debug_mode) {
81129088Smarkm			printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
81229088Smarkm				Name,
81329088Smarkm				ENCTYPE_NAME_OK(type)
81429088Smarkm					? ENCTYPE_NAME(type) : "(unknown)",
81529088Smarkm				type);
81629088Smarkm		}
81729088Smarkm		return;
81829088Smarkm	}
81929088Smarkm	if (ep->start) {
82029088Smarkm		i = (*ep->start)(DIR_ENCRYPT, Server);
82129088Smarkm		if (encrypt_debug_mode) {
82229088Smarkm			printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
82329088Smarkm				Name,
82429088Smarkm				(i < 0) ? "failed" :
82529088Smarkm					"initial negotiation in progress",
82629088Smarkm				i, ENCTYPE_NAME(type));
82729088Smarkm		}
82829088Smarkm		if (i)
82929088Smarkm			return;
83029088Smarkm	}
83129088Smarkm	p = str_start + 3;
83229088Smarkm	*p++ = ENCRYPT_START;
83329088Smarkm	for (i = 0; i < ki[0].keylen; ++i) {
83429088Smarkm		if ((*p++ = ki[0].keyid[i]) == IAC)
83529088Smarkm			*p++ = IAC;
83629088Smarkm	}
83729088Smarkm	*p++ = IAC;
83829088Smarkm	*p++ = SE;
83929088Smarkm	net_write(str_start, p - str_start);
84029088Smarkm	net_encrypt();
84129088Smarkm	printsub('>', &str_start[2], p - &str_start[2]);
84229088Smarkm	/*
84329088Smarkm	 * If we are already encrypting in some mode, then
84429088Smarkm	 * encrypt the ring (which includes our request) in
84529088Smarkm	 * the old mode, mark it all as "clear text" and then
84629088Smarkm	 * switch to the new mode.
84729088Smarkm	 */
84829088Smarkm	encrypt_output = ep->output;
84929088Smarkm	encrypt_mode = type;
85029088Smarkm	if (encrypt_debug_mode)
85129088Smarkm		printf(">>>%s: Started to encrypt output with type %s\r\n",
85229088Smarkm			Name, ENCTYPE_NAME(type));
85329088Smarkm	if (encrypt_verbose)
85429088Smarkm		printf("[ Output is now encrypted with type %s ]\r\n",
85529088Smarkm			ENCTYPE_NAME(type));
85629088Smarkm}
85729088Smarkm
85887139Smarkmvoid
85987139Smarkmencrypt_send_end(void)
86029088Smarkm{
86129088Smarkm	if (!encrypt_output)
86229088Smarkm		return;
86329088Smarkm
86429088Smarkm	str_end[3] = ENCRYPT_END;
86529088Smarkm	net_write(str_end, sizeof(str_end));
86629088Smarkm	net_encrypt();
86729088Smarkm	printsub('>', &str_end[2], sizeof(str_end) - 2);
86829088Smarkm	/*
86929088Smarkm	 * Encrypt the output buffer now because it will not be done by
87029088Smarkm	 * netflush...
87129088Smarkm	 */
87229088Smarkm	encrypt_output = 0;
87329088Smarkm	if (encrypt_debug_mode)
87429088Smarkm		printf(">>>%s: Output is back to clear text\r\n", Name);
87529088Smarkm	if (encrypt_verbose)
87629088Smarkm		printf("[ Output is now clear text ]\r\n");
87729088Smarkm}
87829088Smarkm
87987139Smarkmvoid
88087139Smarkmencrypt_send_request_start(void)
88129088Smarkm{
88287139Smarkm	unsigned char *p;
88387139Smarkm	int i;
88429088Smarkm
88529088Smarkm	p = &str_start[3];
88629088Smarkm	*p++ = ENCRYPT_REQSTART;
88729088Smarkm	for (i = 0; i < ki[1].keylen; ++i) {
88829088Smarkm		if ((*p++ = ki[1].keyid[i]) == IAC)
88929088Smarkm			*p++ = IAC;
89029088Smarkm	}
89129088Smarkm	*p++ = IAC;
89229088Smarkm	*p++ = SE;
89329088Smarkm	net_write(str_start, p - str_start);
89429088Smarkm	printsub('>', &str_start[2], p - &str_start[2]);
89529088Smarkm	if (encrypt_debug_mode)
89629088Smarkm		printf(">>>%s: Request input to be encrypted\r\n", Name);
89729088Smarkm}
89829088Smarkm
89987139Smarkmvoid
90087139Smarkmencrypt_send_request_end(void)
90129088Smarkm{
90229088Smarkm	str_end[3] = ENCRYPT_REQEND;
90329088Smarkm	net_write(str_end, sizeof(str_end));
90429088Smarkm	printsub('>', &str_end[2], sizeof(str_end) - 2);
90529088Smarkm
90629088Smarkm	if (encrypt_debug_mode)
90729088Smarkm		printf(">>>%s: Request input to be clear text\r\n", Name);
90829088Smarkm}
90929088Smarkm
91087139Smarkmvoid
91187139Smarkmencrypt_wait(void)
91229088Smarkm{
91329088Smarkm	if (encrypt_debug_mode)
91429088Smarkm		printf(">>>%s: in encrypt_wait\r\n", Name);
91529088Smarkm	if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
91629088Smarkm		return;
91729088Smarkm	while (autoencrypt && !encrypt_output)
91829088Smarkm		if (telnet_spin())
91929088Smarkm			return;
92029088Smarkm}
92129088Smarkm
92287139Smarkmvoid
92387139Smarkmencrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
92429088Smarkm{
92529088Smarkm	char tbuf[16], *cp;
92629088Smarkm
92729088Smarkm	cnt -= 2;
92829088Smarkm	data += 2;
92929088Smarkm	buf[buflen-1] = '\0';
93029088Smarkm	buf[buflen-2] = '*';
93129088Smarkm	buflen -= 2;;
93229088Smarkm	for (; cnt > 0; cnt--, data++) {
93329088Smarkm		sprintf(tbuf, " %d", *data);
93429088Smarkm		for (cp = tbuf; *cp && buflen > 0; --buflen)
93529088Smarkm			*buf++ = *cp++;
93629088Smarkm		if (buflen <= 0)
93729088Smarkm			return;
93829088Smarkm	}
93929088Smarkm	*buf = '\0';
94029088Smarkm}
94129088Smarkm
94287139Smarkmvoid
94387139Smarkmencrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
94429088Smarkm{
94529088Smarkm	Encryptions *ep;
94687139Smarkm	int type = data[1];
94729088Smarkm
94829088Smarkm	for (ep = encryptions; ep->type && ep->type != type; ep++)
94929088Smarkm		;
95029088Smarkm
95129088Smarkm	if (ep->printsub)
95229088Smarkm		(*ep->printsub)(data, cnt, buf, buflen);
95329088Smarkm	else
95429088Smarkm		encrypt_gen_printsub(data, cnt, buf, buflen);
95529088Smarkm}
95629088Smarkm#endif	/* ENCRYPTION */
957