xref: /dflybsd-src/lib/libtelnet/encrypt.c (revision 1c6ee455f1b90685088155e497d10d0b8d23a95c)
1068e7061SPeter Avalos /*-
2068e7061SPeter Avalos  * Copyright (c) 1991, 1993
3068e7061SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
4068e7061SPeter Avalos  *
5068e7061SPeter Avalos  * Redistribution and use in source and binary forms, with or without
6068e7061SPeter Avalos  * modification, are permitted provided that the following conditions
7068e7061SPeter Avalos  * are met:
8068e7061SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
9068e7061SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
10068e7061SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
11068e7061SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
12068e7061SPeter Avalos  *    documentation and/or other materials provided with the distribution.
13dc71b7abSJustin C. Sherrill  * 3. Neither the name of the University nor the names of its contributors
14068e7061SPeter Avalos  *    may be used to endorse or promote products derived from this software
15068e7061SPeter Avalos  *    without specific prior written permission.
16068e7061SPeter Avalos  *
17068e7061SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18068e7061SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19068e7061SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20068e7061SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21068e7061SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22068e7061SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23068e7061SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24068e7061SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25068e7061SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26068e7061SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27068e7061SPeter Avalos  * SUCH DAMAGE.
28068e7061SPeter Avalos  *
29068e7061SPeter Avalos  * @(#)encrypt.c	8.2 (Berkeley) 5/30/95
30068e7061SPeter Avalos  * $FreeBSD: src/crypto/telnet/libtelnet/encrypt.c,v 1.3.2.2 2002/04/13 10:59:07 markm Exp $
31068e7061SPeter Avalos  */
32068e7061SPeter Avalos 
33068e7061SPeter Avalos /*
34068e7061SPeter Avalos  * Copyright (C) 1990 by the Massachusetts Institute of Technology
35068e7061SPeter Avalos  *
36068e7061SPeter Avalos  * Export of this software from the United States of America is assumed
37068e7061SPeter Avalos  * to require a specific license from the United States Government.
38068e7061SPeter Avalos  * It is the responsibility of any person or organization contemplating
39068e7061SPeter Avalos  * export to obtain such a license before exporting.
40068e7061SPeter Avalos  *
41068e7061SPeter Avalos  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
42068e7061SPeter Avalos  * distribute this software and its documentation for any purpose and
43068e7061SPeter Avalos  * without fee is hereby granted, provided that the above copyright
44068e7061SPeter Avalos  * notice appear in all copies and that both that copyright notice and
45068e7061SPeter Avalos  * this permission notice appear in supporting documentation, and that
46068e7061SPeter Avalos  * the name of M.I.T. not be used in advertising or publicity pertaining
47068e7061SPeter Avalos  * to distribution of the software without specific, written prior
48068e7061SPeter Avalos  * permission.  M.I.T. makes no representations about the suitability of
49068e7061SPeter Avalos  * this software for any purpose.  It is provided "as is" without express
50068e7061SPeter Avalos  * or implied warranty.
51068e7061SPeter Avalos  */
52068e7061SPeter Avalos 
53068e7061SPeter Avalos #ifdef	ENCRYPTION
54068e7061SPeter Avalos 
55068e7061SPeter Avalos #define	ENCRYPT_NAMES
56068e7061SPeter Avalos #include <arpa/telnet.h>
57068e7061SPeter Avalos #include <stdio.h>
58068e7061SPeter Avalos #include <stdlib.h>
59068e7061SPeter Avalos #include <string.h>
60068e7061SPeter Avalos 
61068e7061SPeter Avalos #include "encrypt.h"
62068e7061SPeter Avalos #include "misc.h"
63068e7061SPeter Avalos 
64*1c6ee455SSascha Wildner /*
65*1c6ee455SSascha Wildner  * These functions pointers point to the current routines
66*1c6ee455SSascha Wildner  * for encrypting and decrypting data.
67*1c6ee455SSascha Wildner  */
68*1c6ee455SSascha Wildner void	(*encrypt_output)(unsigned char *, int);
69*1c6ee455SSascha Wildner int	(*decrypt_input)(int);
70*1c6ee455SSascha Wildner 
71068e7061SPeter Avalos int EncryptType(char *type, char *mode);
72068e7061SPeter Avalos int EncryptStart(char *mode);
73068e7061SPeter Avalos int EncryptStop(char *mode);
74068e7061SPeter Avalos int EncryptStartInput(void);
75068e7061SPeter Avalos int EncryptStartOutput(void);
76068e7061SPeter Avalos int EncryptStopInput(void);
77068e7061SPeter Avalos int EncryptStopOutput(void);
78068e7061SPeter Avalos 
79068e7061SPeter Avalos int encrypt_debug_mode = 0;
80068e7061SPeter Avalos static int decrypt_mode = 0;
81068e7061SPeter Avalos static int encrypt_mode = 0;
82068e7061SPeter Avalos static int encrypt_verbose = 0;
83068e7061SPeter Avalos static int autoencrypt = 0;
84068e7061SPeter Avalos static int autodecrypt = 0;
85068e7061SPeter Avalos static int havesessionkey = 0;
86068e7061SPeter Avalos static int Server = 0;
87068e7061SPeter Avalos static const char *Name = "Noname";
88068e7061SPeter Avalos 
89068e7061SPeter Avalos #define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
90068e7061SPeter Avalos 
91068e7061SPeter Avalos static long i_support_encrypt = 0
92068e7061SPeter Avalos  | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
93068e7061SPeter Avalos  |0;
94068e7061SPeter Avalos static long i_support_decrypt = 0
95068e7061SPeter Avalos  | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
96068e7061SPeter Avalos  |0;
97068e7061SPeter Avalos 
98068e7061SPeter Avalos static long i_wont_support_encrypt = 0;
99068e7061SPeter Avalos static long i_wont_support_decrypt = 0;
100068e7061SPeter Avalos #define	I_SUPPORT_ENCRYPT	(i_support_encrypt & ~i_wont_support_encrypt)
101068e7061SPeter Avalos #define	I_SUPPORT_DECRYPT	(i_support_decrypt & ~i_wont_support_decrypt)
102068e7061SPeter Avalos 
103068e7061SPeter Avalos static long remote_supports_encrypt = 0;
104068e7061SPeter Avalos static long remote_supports_decrypt = 0;
105068e7061SPeter Avalos 
106068e7061SPeter Avalos static Encryptions encryptions[] = {
107068e7061SPeter Avalos     { "DES_CFB64",	ENCTYPE_DES_CFB64,
108068e7061SPeter Avalos 			cfb64_encrypt,
109068e7061SPeter Avalos 			cfb64_decrypt,
110068e7061SPeter Avalos 			cfb64_init,
111068e7061SPeter Avalos 			cfb64_start,
112068e7061SPeter Avalos 			cfb64_is,
113068e7061SPeter Avalos 			cfb64_reply,
114068e7061SPeter Avalos 			cfb64_session,
115068e7061SPeter Avalos 			cfb64_keyid,
116068e7061SPeter Avalos 			cfb64_printsub },
117068e7061SPeter Avalos     { "DES_OFB64",	ENCTYPE_DES_OFB64,
118068e7061SPeter Avalos 			ofb64_encrypt,
119068e7061SPeter Avalos 			ofb64_decrypt,
120068e7061SPeter Avalos 			ofb64_init,
121068e7061SPeter Avalos 			ofb64_start,
122068e7061SPeter Avalos 			ofb64_is,
123068e7061SPeter Avalos 			ofb64_reply,
124068e7061SPeter Avalos 			ofb64_session,
125068e7061SPeter Avalos 			ofb64_keyid,
126068e7061SPeter Avalos 			ofb64_printsub },
127068e7061SPeter Avalos     { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
128068e7061SPeter Avalos };
129068e7061SPeter Avalos 
130068e7061SPeter Avalos static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
131068e7061SPeter Avalos 					 ENCRYPT_SUPPORT };
132068e7061SPeter Avalos static unsigned char str_suplen = 0;
133068e7061SPeter Avalos static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
134068e7061SPeter Avalos static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
135068e7061SPeter Avalos 
136068e7061SPeter Avalos Encryptions *
findencryption(int type)137068e7061SPeter Avalos findencryption(int type)
138068e7061SPeter Avalos {
139068e7061SPeter Avalos 	Encryptions *ep = encryptions;
140068e7061SPeter Avalos 
141068e7061SPeter Avalos 	if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type)))
142068e7061SPeter Avalos 		return(0);
143068e7061SPeter Avalos 	while (ep->type && ep->type != type)
144068e7061SPeter Avalos 		++ep;
145068e7061SPeter Avalos 	return(ep->type ? ep : 0);
146068e7061SPeter Avalos }
147068e7061SPeter Avalos 
148068e7061SPeter Avalos static Encryptions *
finddecryption(int type)149068e7061SPeter Avalos finddecryption(int type)
150068e7061SPeter Avalos {
151068e7061SPeter Avalos 	Encryptions *ep = encryptions;
152068e7061SPeter Avalos 
153068e7061SPeter Avalos 	if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type)))
154068e7061SPeter Avalos 		return(0);
155068e7061SPeter Avalos 	while (ep->type && ep->type != type)
156068e7061SPeter Avalos 		++ep;
157068e7061SPeter Avalos 	return(ep->type ? ep : 0);
158068e7061SPeter Avalos }
159068e7061SPeter Avalos 
160068e7061SPeter Avalos #define	MAXKEYLEN 64
161068e7061SPeter Avalos 
162068e7061SPeter Avalos static struct key_info {
163068e7061SPeter Avalos 	unsigned char keyid[MAXKEYLEN];
164068e7061SPeter Avalos 	int keylen;
165068e7061SPeter Avalos 	int dir;
166068e7061SPeter Avalos 	int *modep;
167068e7061SPeter Avalos 	Encryptions *(*getcrypt)(int);
168068e7061SPeter Avalos } ki[2] = {
169068e7061SPeter Avalos 	{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
170068e7061SPeter Avalos 	{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
171068e7061SPeter Avalos };
172068e7061SPeter Avalos 
173068e7061SPeter Avalos static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len);
174068e7061SPeter Avalos 
175068e7061SPeter Avalos void
encrypt_init(const char * name,int server)176068e7061SPeter Avalos encrypt_init(const char *name, int server)
177068e7061SPeter Avalos {
178068e7061SPeter Avalos 	Encryptions *ep = encryptions;
179068e7061SPeter Avalos 
180068e7061SPeter Avalos 	Name = name;
181068e7061SPeter Avalos 	Server = server;
182068e7061SPeter Avalos 	i_support_encrypt = i_support_decrypt = 0;
183068e7061SPeter Avalos 	remote_supports_encrypt = remote_supports_decrypt = 0;
184068e7061SPeter Avalos 	encrypt_mode = 0;
185068e7061SPeter Avalos 	decrypt_mode = 0;
186678e8cc6SSascha Wildner 	encrypt_output = NULL;
187678e8cc6SSascha Wildner 	decrypt_input = NULL;
188068e7061SPeter Avalos 
189068e7061SPeter Avalos 	str_suplen = 4;
190068e7061SPeter Avalos 
191068e7061SPeter Avalos 	while (ep->type) {
192068e7061SPeter Avalos 		if (encrypt_debug_mode)
193068e7061SPeter Avalos 			printf(">>>%s: I will support %s\r\n",
194068e7061SPeter Avalos 				Name, ENCTYPE_NAME(ep->type));
195068e7061SPeter Avalos 		i_support_encrypt |= typemask(ep->type);
196068e7061SPeter Avalos 		i_support_decrypt |= typemask(ep->type);
197068e7061SPeter Avalos 		if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
198068e7061SPeter Avalos 			if ((str_send[str_suplen++] = ep->type) == IAC)
199068e7061SPeter Avalos 				str_send[str_suplen++] = IAC;
200068e7061SPeter Avalos 		if (ep->init)
201068e7061SPeter Avalos 			(*ep->init)(Server);
202068e7061SPeter Avalos 		++ep;
203068e7061SPeter Avalos 	}
204068e7061SPeter Avalos 	str_send[str_suplen++] = IAC;
205068e7061SPeter Avalos 	str_send[str_suplen++] = SE;
206068e7061SPeter Avalos }
207068e7061SPeter Avalos 
208068e7061SPeter Avalos static void
encrypt_list_types(void)209068e7061SPeter Avalos encrypt_list_types(void)
210068e7061SPeter Avalos {
211068e7061SPeter Avalos 	Encryptions *ep = encryptions;
212068e7061SPeter Avalos 
213068e7061SPeter Avalos 	printf("Valid encryption types:\n");
214068e7061SPeter Avalos 	while (ep->type) {
215068e7061SPeter Avalos 		printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
216068e7061SPeter Avalos 		++ep;
217068e7061SPeter Avalos 	}
218068e7061SPeter Avalos }
219068e7061SPeter Avalos 
220068e7061SPeter Avalos int
EncryptEnable(char * type,char * mode)221068e7061SPeter Avalos EncryptEnable(char *type, char *mode)
222068e7061SPeter Avalos {
223068e7061SPeter Avalos 	if (isprefix(type, "help") || isprefix(type, "?")) {
224068e7061SPeter Avalos 		printf("Usage: encrypt enable <type> [input|output]\n");
225068e7061SPeter Avalos 		encrypt_list_types();
226068e7061SPeter Avalos 		return(0);
227068e7061SPeter Avalos 	}
228068e7061SPeter Avalos 	if (EncryptType(type, mode))
229068e7061SPeter Avalos 		return(EncryptStart(mode));
230068e7061SPeter Avalos 	return(0);
231068e7061SPeter Avalos }
232068e7061SPeter Avalos 
233068e7061SPeter Avalos int
EncryptDisable(char * type,char * mode)234068e7061SPeter Avalos EncryptDisable(char *type, char *mode)
235068e7061SPeter Avalos {
236068e7061SPeter Avalos 	Encryptions *ep;
237068e7061SPeter Avalos 	int ret = 0;
238068e7061SPeter Avalos 
239068e7061SPeter Avalos 	if (isprefix(type, "help") || isprefix(type, "?")) {
240068e7061SPeter Avalos 		printf("Usage: encrypt disable <type> [input|output]\n");
241068e7061SPeter Avalos 		encrypt_list_types();
242068e7061SPeter Avalos 	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
243678e8cc6SSascha Wildner 						sizeof(Encryptions))) == NULL) {
244068e7061SPeter Avalos 		printf("%s: invalid encryption type\n", type);
245068e7061SPeter Avalos 	} else if (Ambiguous((char **)ep)) {
246068e7061SPeter Avalos 		printf("Ambiguous type '%s'\n", type);
247068e7061SPeter Avalos 	} else {
248678e8cc6SSascha Wildner 		if ((mode == NULL) || (isprefix(mode, "input") ? 1 : 0)) {
249068e7061SPeter Avalos 			if (decrypt_mode == ep->type)
250068e7061SPeter Avalos 				EncryptStopInput();
251068e7061SPeter Avalos 			i_wont_support_decrypt |= typemask(ep->type);
252068e7061SPeter Avalos 			ret = 1;
253068e7061SPeter Avalos 		}
254678e8cc6SSascha Wildner 		if ((mode == NULL) || (isprefix(mode, "output"))) {
255068e7061SPeter Avalos 			if (encrypt_mode == ep->type)
256068e7061SPeter Avalos 				EncryptStopOutput();
257068e7061SPeter Avalos 			i_wont_support_encrypt |= typemask(ep->type);
258068e7061SPeter Avalos 			ret = 1;
259068e7061SPeter Avalos 		}
260068e7061SPeter Avalos 		if (ret == 0)
261068e7061SPeter Avalos 			printf("%s: invalid encryption mode\n", mode);
262068e7061SPeter Avalos 	}
263068e7061SPeter Avalos 	return(ret);
264068e7061SPeter Avalos }
265068e7061SPeter Avalos 
266068e7061SPeter Avalos int
EncryptType(char * type,char * mode)267068e7061SPeter Avalos EncryptType(char *type, char *mode)
268068e7061SPeter Avalos {
269068e7061SPeter Avalos 	Encryptions *ep;
270068e7061SPeter Avalos 	int ret = 0;
271068e7061SPeter Avalos 
272068e7061SPeter Avalos 	if (isprefix(type, "help") || isprefix(type, "?")) {
273068e7061SPeter Avalos 		printf("Usage: encrypt type <type> [input|output]\n");
274068e7061SPeter Avalos 		encrypt_list_types();
275068e7061SPeter Avalos 	} else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
276678e8cc6SSascha Wildner 						sizeof(Encryptions))) == NULL) {
277068e7061SPeter Avalos 		printf("%s: invalid encryption type\n", type);
278068e7061SPeter Avalos 	} else if (Ambiguous((char **)ep)) {
279068e7061SPeter Avalos 		printf("Ambiguous type '%s'\n", type);
280068e7061SPeter Avalos 	} else {
281678e8cc6SSascha Wildner 		if ((mode == NULL) || isprefix(mode, "input")) {
282068e7061SPeter Avalos 			decrypt_mode = ep->type;
283068e7061SPeter Avalos 			i_wont_support_decrypt &= ~typemask(ep->type);
284068e7061SPeter Avalos 			ret = 1;
285068e7061SPeter Avalos 		}
286678e8cc6SSascha Wildner 		if ((mode == NULL) || isprefix(mode, "output")) {
287068e7061SPeter Avalos 			encrypt_mode = ep->type;
288068e7061SPeter Avalos 			i_wont_support_encrypt &= ~typemask(ep->type);
289068e7061SPeter Avalos 			ret = 1;
290068e7061SPeter Avalos 		}
291068e7061SPeter Avalos 		if (ret == 0)
292068e7061SPeter Avalos 			printf("%s: invalid encryption mode\n", mode);
293068e7061SPeter Avalos 	}
294068e7061SPeter Avalos 	return(ret);
295068e7061SPeter Avalos }
296068e7061SPeter Avalos 
297068e7061SPeter Avalos int
EncryptStart(char * mode)298068e7061SPeter Avalos EncryptStart(char *mode)
299068e7061SPeter Avalos {
300068e7061SPeter Avalos 	int ret = 0;
301068e7061SPeter Avalos 	if (mode) {
302068e7061SPeter Avalos 		if (isprefix(mode, "input"))
303068e7061SPeter Avalos 			return(EncryptStartInput());
304068e7061SPeter Avalos 		if (isprefix(mode, "output"))
305068e7061SPeter Avalos 			return(EncryptStartOutput());
306068e7061SPeter Avalos 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
307068e7061SPeter Avalos 			printf("Usage: encrypt start [input|output]\n");
308068e7061SPeter Avalos 			return(0);
309068e7061SPeter Avalos 		}
310068e7061SPeter Avalos 		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
311068e7061SPeter Avalos 		return(0);
312068e7061SPeter Avalos 	}
313068e7061SPeter Avalos 	ret += EncryptStartInput();
314068e7061SPeter Avalos 	ret += EncryptStartOutput();
315068e7061SPeter Avalos 	return(ret);
316068e7061SPeter Avalos }
317068e7061SPeter Avalos 
318068e7061SPeter Avalos int
EncryptStartInput(void)319068e7061SPeter Avalos EncryptStartInput(void)
320068e7061SPeter Avalos {
321068e7061SPeter Avalos 	if (decrypt_mode) {
322068e7061SPeter Avalos 		encrypt_send_request_start();
323068e7061SPeter Avalos 		return(1);
324068e7061SPeter Avalos 	}
325068e7061SPeter Avalos 	printf("No previous decryption mode, decryption not enabled\r\n");
326068e7061SPeter Avalos 	return(0);
327068e7061SPeter Avalos }
328068e7061SPeter Avalos 
329068e7061SPeter Avalos int
EncryptStartOutput(void)330068e7061SPeter Avalos EncryptStartOutput(void)
331068e7061SPeter Avalos {
332068e7061SPeter Avalos 	if (encrypt_mode) {
333068e7061SPeter Avalos 		encrypt_start_output(encrypt_mode);
334068e7061SPeter Avalos 		return(1);
335068e7061SPeter Avalos 	}
336068e7061SPeter Avalos 	printf("No previous encryption mode, encryption not enabled\r\n");
337068e7061SPeter Avalos 	return(0);
338068e7061SPeter Avalos }
339068e7061SPeter Avalos 
340068e7061SPeter Avalos int
EncryptStop(char * mode)341068e7061SPeter Avalos EncryptStop(char *mode)
342068e7061SPeter Avalos {
343068e7061SPeter Avalos 	int ret = 0;
344068e7061SPeter Avalos 	if (mode) {
345068e7061SPeter Avalos 		if (isprefix(mode, "input"))
346068e7061SPeter Avalos 			return(EncryptStopInput());
347068e7061SPeter Avalos 		if (isprefix(mode, "output"))
348068e7061SPeter Avalos 			return(EncryptStopOutput());
349068e7061SPeter Avalos 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
350068e7061SPeter Avalos 			printf("Usage: encrypt stop [input|output]\n");
351068e7061SPeter Avalos 			return(0);
352068e7061SPeter Avalos 		}
353068e7061SPeter Avalos 		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
354068e7061SPeter Avalos 		return(0);
355068e7061SPeter Avalos 	}
356068e7061SPeter Avalos 	ret += EncryptStopInput();
357068e7061SPeter Avalos 	ret += EncryptStopOutput();
358068e7061SPeter Avalos 	return(ret);
359068e7061SPeter Avalos }
360068e7061SPeter Avalos 
361068e7061SPeter Avalos int
EncryptStopInput(void)362068e7061SPeter Avalos EncryptStopInput(void)
363068e7061SPeter Avalos {
364068e7061SPeter Avalos 	encrypt_send_request_end();
365068e7061SPeter Avalos 	return(1);
366068e7061SPeter Avalos }
367068e7061SPeter Avalos 
368068e7061SPeter Avalos int
EncryptStopOutput(void)369068e7061SPeter Avalos EncryptStopOutput(void)
370068e7061SPeter Avalos {
371068e7061SPeter Avalos 	encrypt_send_end();
372068e7061SPeter Avalos 	return(1);
373068e7061SPeter Avalos }
374068e7061SPeter Avalos 
375068e7061SPeter Avalos void
encrypt_display(void)376068e7061SPeter Avalos encrypt_display(void)
377068e7061SPeter Avalos {
378068e7061SPeter Avalos 	if (encrypt_output)
379068e7061SPeter Avalos 		printf("Currently encrypting output with %s\r\n",
380068e7061SPeter Avalos 			ENCTYPE_NAME(encrypt_mode));
381068e7061SPeter Avalos 	if (decrypt_input)
382068e7061SPeter Avalos 		printf("Currently decrypting input with %s\r\n",
383068e7061SPeter Avalos 			ENCTYPE_NAME(decrypt_mode));
384068e7061SPeter Avalos }
385068e7061SPeter Avalos 
386068e7061SPeter Avalos int
EncryptStatus(void)387068e7061SPeter Avalos EncryptStatus(void)
388068e7061SPeter Avalos {
389068e7061SPeter Avalos 	if (encrypt_output)
390068e7061SPeter Avalos 		printf("Currently encrypting output with %s\r\n",
391068e7061SPeter Avalos 			ENCTYPE_NAME(encrypt_mode));
392068e7061SPeter Avalos 	else if (encrypt_mode) {
393068e7061SPeter Avalos 		printf("Currently output is clear text.\r\n");
394068e7061SPeter Avalos 		printf("Last encryption mode was %s\r\n",
395068e7061SPeter Avalos 			ENCTYPE_NAME(encrypt_mode));
396068e7061SPeter Avalos 	}
397068e7061SPeter Avalos 	if (decrypt_input) {
398068e7061SPeter Avalos 		printf("Currently decrypting input with %s\r\n",
399068e7061SPeter Avalos 			ENCTYPE_NAME(decrypt_mode));
400068e7061SPeter Avalos 	} else if (decrypt_mode) {
401068e7061SPeter Avalos 		printf("Currently input is clear text.\r\n");
402068e7061SPeter Avalos 		printf("Last decryption mode was %s\r\n",
403068e7061SPeter Avalos 			ENCTYPE_NAME(decrypt_mode));
404068e7061SPeter Avalos 	}
405068e7061SPeter Avalos 	return 1;
406068e7061SPeter Avalos }
407068e7061SPeter Avalos 
408068e7061SPeter Avalos void
encrypt_send_support(void)409068e7061SPeter Avalos encrypt_send_support(void)
410068e7061SPeter Avalos {
411068e7061SPeter Avalos 	if (str_suplen) {
412068e7061SPeter Avalos 		/*
413068e7061SPeter Avalos 		 * If the user has requested that decryption start
414068e7061SPeter Avalos 		 * immediatly, then send a "REQUEST START" before
415068e7061SPeter Avalos 		 * we negotiate the type.
416068e7061SPeter Avalos 		 */
417068e7061SPeter Avalos 		if (!Server && autodecrypt)
418068e7061SPeter Avalos 			encrypt_send_request_start();
419068e7061SPeter Avalos 		net_write(str_send, str_suplen);
420068e7061SPeter Avalos 		printsub('>', &str_send[2], str_suplen - 2);
421068e7061SPeter Avalos 		str_suplen = 0;
422068e7061SPeter Avalos 	}
423068e7061SPeter Avalos }
424068e7061SPeter Avalos 
425068e7061SPeter Avalos int
EncryptDebug(int on)426068e7061SPeter Avalos EncryptDebug(int on)
427068e7061SPeter Avalos {
428068e7061SPeter Avalos 	if (on < 0)
429068e7061SPeter Avalos 		encrypt_debug_mode ^= 1;
430068e7061SPeter Avalos 	else
431068e7061SPeter Avalos 		encrypt_debug_mode = on;
432068e7061SPeter Avalos 	printf("Encryption debugging %s\r\n",
433068e7061SPeter Avalos 		encrypt_debug_mode ? "enabled" : "disabled");
434068e7061SPeter Avalos 	return(1);
435068e7061SPeter Avalos }
436068e7061SPeter Avalos 
437068e7061SPeter Avalos int
EncryptVerbose(int on)438068e7061SPeter Avalos EncryptVerbose(int on)
439068e7061SPeter Avalos {
440068e7061SPeter Avalos 	if (on < 0)
441068e7061SPeter Avalos 		encrypt_verbose ^= 1;
442068e7061SPeter Avalos 	else
443068e7061SPeter Avalos 		encrypt_verbose = on;
444068e7061SPeter Avalos 	printf("Encryption %s verbose\r\n",
445068e7061SPeter Avalos 		encrypt_verbose ? "is" : "is not");
446068e7061SPeter Avalos 	return(1);
447068e7061SPeter Avalos }
448068e7061SPeter Avalos 
449068e7061SPeter Avalos int
EncryptAutoEnc(int on)450068e7061SPeter Avalos EncryptAutoEnc(int on)
451068e7061SPeter Avalos {
452068e7061SPeter Avalos 	encrypt_auto(on);
453068e7061SPeter Avalos 	printf("Automatic encryption of output is %s\r\n",
454068e7061SPeter Avalos 		autoencrypt ? "enabled" : "disabled");
455068e7061SPeter Avalos 	return(1);
456068e7061SPeter Avalos }
457068e7061SPeter Avalos 
458068e7061SPeter Avalos int
EncryptAutoDec(int on)459068e7061SPeter Avalos EncryptAutoDec(int on)
460068e7061SPeter Avalos {
461068e7061SPeter Avalos 	decrypt_auto(on);
462068e7061SPeter Avalos 	printf("Automatic decryption of input is %s\r\n",
463068e7061SPeter Avalos 		autodecrypt ? "enabled" : "disabled");
464068e7061SPeter Avalos 	return(1);
465068e7061SPeter Avalos }
466068e7061SPeter Avalos 
467068e7061SPeter Avalos /*
468068e7061SPeter Avalos  * Called when ENCRYPT SUPPORT is received.
469068e7061SPeter Avalos  */
470068e7061SPeter Avalos void
encrypt_support(unsigned char * typelist,int cnt)471068e7061SPeter Avalos encrypt_support(unsigned char *typelist, int cnt)
472068e7061SPeter Avalos {
473068e7061SPeter Avalos 	int type, use_type = 0;
474068e7061SPeter Avalos 	Encryptions *ep;
475068e7061SPeter Avalos 
476068e7061SPeter Avalos 	/*
477068e7061SPeter Avalos 	 * Forget anything the other side has previously told us.
478068e7061SPeter Avalos 	 */
479068e7061SPeter Avalos 	remote_supports_decrypt = 0;
480068e7061SPeter Avalos 
481068e7061SPeter Avalos 	while (cnt-- > 0) {
482068e7061SPeter Avalos 		type = *typelist++;
483068e7061SPeter Avalos 		if (encrypt_debug_mode)
484068e7061SPeter Avalos 			printf(">>>%s: He is supporting %s (%d)\r\n",
485068e7061SPeter Avalos 				Name,
486068e7061SPeter Avalos 				ENCTYPE_NAME(type), type);
487068e7061SPeter Avalos 		if ((type < ENCTYPE_CNT) &&
488068e7061SPeter Avalos 		    (I_SUPPORT_ENCRYPT & typemask(type))) {
489068e7061SPeter Avalos 			remote_supports_decrypt |= typemask(type);
490068e7061SPeter Avalos 			if (use_type == 0)
491068e7061SPeter Avalos 				use_type = type;
492068e7061SPeter Avalos 		}
493068e7061SPeter Avalos 	}
494068e7061SPeter Avalos 	if (use_type) {
495068e7061SPeter Avalos 		ep = findencryption(use_type);
496068e7061SPeter Avalos 		if (!ep)
497068e7061SPeter Avalos 			return;
498068e7061SPeter Avalos 		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
499068e7061SPeter Avalos 		if (encrypt_debug_mode)
500068e7061SPeter Avalos 			printf(">>>%s: (*ep->start)() returned %d\r\n",
501068e7061SPeter Avalos 					Name, type);
502068e7061SPeter Avalos 		if (type < 0)
503068e7061SPeter Avalos 			return;
504068e7061SPeter Avalos 		encrypt_mode = use_type;
505068e7061SPeter Avalos 		if (type == 0)
506068e7061SPeter Avalos 			encrypt_start_output(use_type);
507068e7061SPeter Avalos 	}
508068e7061SPeter Avalos }
509068e7061SPeter Avalos 
510068e7061SPeter Avalos void
encrypt_is(unsigned char * data,int cnt)511068e7061SPeter Avalos encrypt_is(unsigned char *data, int cnt)
512068e7061SPeter Avalos {
513068e7061SPeter Avalos 	Encryptions *ep;
514068e7061SPeter Avalos 	int type, ret;
515068e7061SPeter Avalos 
516068e7061SPeter Avalos 	if (--cnt < 0)
517068e7061SPeter Avalos 		return;
518068e7061SPeter Avalos 	type = *data++;
519068e7061SPeter Avalos 	if (type < ENCTYPE_CNT)
520068e7061SPeter Avalos 		remote_supports_encrypt |= typemask(type);
521068e7061SPeter Avalos 	if (!(ep = finddecryption(type))) {
522068e7061SPeter Avalos 		if (encrypt_debug_mode)
523068e7061SPeter Avalos 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
524068e7061SPeter Avalos 				Name,
525068e7061SPeter Avalos 				ENCTYPE_NAME_OK(type)
526068e7061SPeter Avalos 					? ENCTYPE_NAME(type) : "(unknown)",
527068e7061SPeter Avalos 				type);
528068e7061SPeter Avalos 		return;
529068e7061SPeter Avalos 	}
530068e7061SPeter Avalos 	if (!ep->is) {
531068e7061SPeter Avalos 		if (encrypt_debug_mode)
532068e7061SPeter Avalos 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
533068e7061SPeter Avalos 				Name,
534068e7061SPeter Avalos 				ENCTYPE_NAME_OK(type)
535068e7061SPeter Avalos 					? ENCTYPE_NAME(type) : "(unknown)",
536068e7061SPeter Avalos 				type);
537068e7061SPeter Avalos 		ret = 0;
538068e7061SPeter Avalos 	} else {
539068e7061SPeter Avalos 		ret = (*ep->is)(data, cnt);
540068e7061SPeter Avalos 		if (encrypt_debug_mode)
541068e7061SPeter Avalos 			printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
542068e7061SPeter Avalos 				(ret < 0) ? "FAIL " :
543068e7061SPeter Avalos 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
544068e7061SPeter Avalos 	}
545068e7061SPeter Avalos 	if (ret < 0) {
546068e7061SPeter Avalos 		autodecrypt = 0;
547068e7061SPeter Avalos 	} else {
548068e7061SPeter Avalos 		decrypt_mode = type;
549068e7061SPeter Avalos 		if (ret == 0 && autodecrypt)
550068e7061SPeter Avalos 			encrypt_send_request_start();
551068e7061SPeter Avalos 	}
552068e7061SPeter Avalos }
553068e7061SPeter Avalos 
554068e7061SPeter Avalos void
encrypt_reply(unsigned char * data,int cnt)555068e7061SPeter Avalos encrypt_reply(unsigned char *data, int cnt)
556068e7061SPeter Avalos {
557068e7061SPeter Avalos 	Encryptions *ep;
558068e7061SPeter Avalos 	int ret, type;
559068e7061SPeter Avalos 
560068e7061SPeter Avalos 	if (--cnt < 0)
561068e7061SPeter Avalos 		return;
562068e7061SPeter Avalos 	type = *data++;
563068e7061SPeter Avalos 	if (!(ep = findencryption(type))) {
564068e7061SPeter Avalos 		if (encrypt_debug_mode)
565068e7061SPeter Avalos 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
566068e7061SPeter Avalos 				Name,
567068e7061SPeter Avalos 				ENCTYPE_NAME_OK(type)
568068e7061SPeter Avalos 					? ENCTYPE_NAME(type) : "(unknown)",
569068e7061SPeter Avalos 				type);
570068e7061SPeter Avalos 		return;
571068e7061SPeter Avalos 	}
572068e7061SPeter Avalos 	if (!ep->reply) {
573068e7061SPeter Avalos 		if (encrypt_debug_mode)
574068e7061SPeter Avalos 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
575068e7061SPeter Avalos 				Name,
576068e7061SPeter Avalos 				ENCTYPE_NAME_OK(type)
577068e7061SPeter Avalos 					? ENCTYPE_NAME(type) : "(unknown)",
578068e7061SPeter Avalos 				type);
579068e7061SPeter Avalos 		ret = 0;
580068e7061SPeter Avalos 	} else {
581068e7061SPeter Avalos 		ret = (*ep->reply)(data, cnt);
582068e7061SPeter Avalos 		if (encrypt_debug_mode)
583068e7061SPeter Avalos 			printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
584068e7061SPeter Avalos 				data, cnt,
585068e7061SPeter Avalos 				(ret < 0) ? "FAIL " :
586068e7061SPeter Avalos 				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
587068e7061SPeter Avalos 	}
588068e7061SPeter Avalos 	if (encrypt_debug_mode)
589068e7061SPeter Avalos 		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
590068e7061SPeter Avalos 	if (ret < 0) {
591068e7061SPeter Avalos 		autoencrypt = 0;
592068e7061SPeter Avalos 	} else {
593068e7061SPeter Avalos 		encrypt_mode = type;
594068e7061SPeter Avalos 		if (ret == 0 && autoencrypt)
595068e7061SPeter Avalos 			encrypt_start_output(type);
596068e7061SPeter Avalos 	}
597068e7061SPeter Avalos }
598068e7061SPeter Avalos 
599068e7061SPeter Avalos /*
600068e7061SPeter Avalos  * Called when a ENCRYPT START command is received.
601068e7061SPeter Avalos  */
602068e7061SPeter Avalos void
encrypt_start(unsigned char * data __unused,int cnt __unused)603068e7061SPeter Avalos encrypt_start(unsigned char *data __unused, int cnt __unused)
604068e7061SPeter Avalos {
605068e7061SPeter Avalos 	Encryptions *ep;
606068e7061SPeter Avalos 
607068e7061SPeter Avalos 	if (!decrypt_mode) {
608068e7061SPeter Avalos 		/*
609068e7061SPeter Avalos 		 * Something is wrong.  We should not get a START
610068e7061SPeter Avalos 		 * command without having already picked our
611068e7061SPeter Avalos 		 * decryption scheme.  Send a REQUEST-END to
612068e7061SPeter Avalos 		 * attempt to clear the channel...
613068e7061SPeter Avalos 		 */
614068e7061SPeter Avalos 		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
615068e7061SPeter Avalos 		encrypt_send_request_end();
616068e7061SPeter Avalos 		return;
617068e7061SPeter Avalos 	}
618068e7061SPeter Avalos 
619068e7061SPeter Avalos 	if ((ep = finddecryption(decrypt_mode))) {
620068e7061SPeter Avalos 		decrypt_input = ep->input;
621068e7061SPeter Avalos 		if (encrypt_verbose)
622068e7061SPeter Avalos 			printf("[ Input is now decrypted with type %s ]\r\n",
623068e7061SPeter Avalos 				ENCTYPE_NAME(decrypt_mode));
624068e7061SPeter Avalos 		if (encrypt_debug_mode)
625068e7061SPeter Avalos 			printf(">>>%s: Start to decrypt input with type %s\r\n",
626068e7061SPeter Avalos 				Name, ENCTYPE_NAME(decrypt_mode));
627068e7061SPeter Avalos 	} else {
628068e7061SPeter Avalos 		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
629068e7061SPeter Avalos 				Name,
630068e7061SPeter Avalos 				ENCTYPE_NAME_OK(decrypt_mode)
631068e7061SPeter Avalos 					? ENCTYPE_NAME(decrypt_mode)
632068e7061SPeter Avalos 					: "(unknown)",
633068e7061SPeter Avalos 				decrypt_mode);
634068e7061SPeter Avalos 		encrypt_send_request_end();
635068e7061SPeter Avalos 	}
636068e7061SPeter Avalos }
637068e7061SPeter Avalos 
638068e7061SPeter Avalos void
encrypt_session_key(Session_Key * key,int server)639068e7061SPeter Avalos encrypt_session_key( Session_Key *key, int server)
640068e7061SPeter Avalos {
641068e7061SPeter Avalos 	Encryptions *ep = encryptions;
642068e7061SPeter Avalos 
643068e7061SPeter Avalos 	havesessionkey = 1;
644068e7061SPeter Avalos 
645068e7061SPeter Avalos 	while (ep->type) {
646068e7061SPeter Avalos 		if (ep->session)
647068e7061SPeter Avalos 			(*ep->session)(key, server);
648068e7061SPeter Avalos 		++ep;
649068e7061SPeter Avalos 	}
650068e7061SPeter Avalos }
651068e7061SPeter Avalos 
652068e7061SPeter Avalos /*
653068e7061SPeter Avalos  * Called when ENCRYPT END is received.
654068e7061SPeter Avalos  */
655068e7061SPeter Avalos void
encrypt_end(void)656068e7061SPeter Avalos encrypt_end(void)
657068e7061SPeter Avalos {
658678e8cc6SSascha Wildner 	decrypt_input = NULL;
659068e7061SPeter Avalos 	if (encrypt_debug_mode)
660068e7061SPeter Avalos 		printf(">>>%s: Input is back to clear text\r\n", Name);
661068e7061SPeter Avalos 	if (encrypt_verbose)
662068e7061SPeter Avalos 		printf("[ Input is now clear text ]\r\n");
663068e7061SPeter Avalos }
664068e7061SPeter Avalos 
665068e7061SPeter Avalos /*
666068e7061SPeter Avalos  * Called when ENCRYPT REQUEST-END is received.
667068e7061SPeter Avalos  */
668068e7061SPeter Avalos void
encrypt_request_end(void)669068e7061SPeter Avalos encrypt_request_end(void)
670068e7061SPeter Avalos {
671068e7061SPeter Avalos 	encrypt_send_end();
672068e7061SPeter Avalos }
673068e7061SPeter Avalos 
674068e7061SPeter Avalos /*
675068e7061SPeter Avalos  * Called when ENCRYPT REQUEST-START is received.  If we receive
676068e7061SPeter Avalos  * this before a type is picked, then that indicates that the
677068e7061SPeter Avalos  * other side wants us to start encrypting data as soon as we
678068e7061SPeter Avalos  * can.
679068e7061SPeter Avalos  */
680068e7061SPeter Avalos void
encrypt_request_start(unsigned char * data __unused,int cnt __unused)681068e7061SPeter Avalos encrypt_request_start(unsigned char *data __unused, int cnt __unused)
682068e7061SPeter Avalos {
683068e7061SPeter Avalos 	if (encrypt_mode == 0)  {
684068e7061SPeter Avalos 		if (Server)
685068e7061SPeter Avalos 			autoencrypt = 1;
686068e7061SPeter Avalos 		return;
687068e7061SPeter Avalos 	}
688068e7061SPeter Avalos 	encrypt_start_output(encrypt_mode);
689068e7061SPeter Avalos }
690068e7061SPeter Avalos 
691068e7061SPeter Avalos static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
692068e7061SPeter Avalos 
693068e7061SPeter Avalos void
encrypt_enc_keyid(unsigned char * keyid,int len)694068e7061SPeter Avalos encrypt_enc_keyid(unsigned char *keyid, int len)
695068e7061SPeter Avalos {
696068e7061SPeter Avalos 	encrypt_keyid(&ki[1], keyid, len);
697068e7061SPeter Avalos }
698068e7061SPeter Avalos 
699068e7061SPeter Avalos void
encrypt_dec_keyid(unsigned char * keyid,int len)700068e7061SPeter Avalos encrypt_dec_keyid(unsigned char *keyid, int len)
701068e7061SPeter Avalos {
702068e7061SPeter Avalos 	encrypt_keyid(&ki[0], keyid, len);
703068e7061SPeter Avalos }
704068e7061SPeter Avalos 
705068e7061SPeter Avalos void
encrypt_keyid(struct key_info * kp,unsigned char * keyid,int len)706068e7061SPeter Avalos encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
707068e7061SPeter Avalos {
708068e7061SPeter Avalos 	Encryptions *ep;
709068e7061SPeter Avalos 	int dir = kp->dir;
710068e7061SPeter Avalos 	int ret = 0;
711068e7061SPeter Avalos 
712e2decfa0SPeter Avalos 	if (len > MAXKEYLEN)
713e2decfa0SPeter Avalos 		len = MAXKEYLEN;
714e2decfa0SPeter Avalos 
715068e7061SPeter Avalos 	if (!(ep = (*kp->getcrypt)(*kp->modep))) {
716068e7061SPeter Avalos 		if (len == 0)
717068e7061SPeter Avalos 			return;
718068e7061SPeter Avalos 		kp->keylen = 0;
719068e7061SPeter Avalos 	} else if (len == 0) {
720068e7061SPeter Avalos 		/*
721068e7061SPeter Avalos 		 * Empty option, indicates a failure.
722068e7061SPeter Avalos 		 */
723068e7061SPeter Avalos 		if (kp->keylen == 0)
724068e7061SPeter Avalos 			return;
725068e7061SPeter Avalos 		kp->keylen = 0;
726068e7061SPeter Avalos 		if (ep->keyid)
727068e7061SPeter Avalos 			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
728068e7061SPeter Avalos 
729068e7061SPeter Avalos 	} else if ((len != kp->keylen) ||
730068e7061SPeter Avalos 		   (memcmp(keyid, kp->keyid, len) != 0)) {
731068e7061SPeter Avalos 		/*
732068e7061SPeter Avalos 		 * Length or contents are different
733068e7061SPeter Avalos 		 */
734068e7061SPeter Avalos 		kp->keylen = len;
735068e7061SPeter Avalos 		memmove(kp->keyid, keyid, len);
736068e7061SPeter Avalos 		if (ep->keyid)
737068e7061SPeter Avalos 			(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
738068e7061SPeter Avalos 	} else {
739068e7061SPeter Avalos 		if (ep->keyid)
740068e7061SPeter Avalos 			ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
741068e7061SPeter Avalos 		if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
742068e7061SPeter Avalos 			encrypt_start_output(*kp->modep);
743068e7061SPeter Avalos 		return;
744068e7061SPeter Avalos 	}
745068e7061SPeter Avalos 
746068e7061SPeter Avalos 	encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
747068e7061SPeter Avalos }
748068e7061SPeter Avalos 
749068e7061SPeter Avalos void
encrypt_send_keyid(int dir,const char * keyid,int keylen,int saveit)750068e7061SPeter Avalos encrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit)
751068e7061SPeter Avalos {
752068e7061SPeter Avalos 	unsigned char *strp;
753068e7061SPeter Avalos 
754068e7061SPeter Avalos 	str_keyid[3] = (dir == DIR_ENCRYPT)
755068e7061SPeter Avalos 			? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
756068e7061SPeter Avalos 	if (saveit) {
757068e7061SPeter Avalos 		struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
758068e7061SPeter Avalos 		memmove(kp->keyid, keyid, keylen);
759068e7061SPeter Avalos 		kp->keylen = keylen;
760068e7061SPeter Avalos 	}
761068e7061SPeter Avalos 
762068e7061SPeter Avalos 	for (strp = &str_keyid[4]; keylen > 0; --keylen) {
763068e7061SPeter Avalos 		if ((*strp++ = *keyid++) == IAC)
764068e7061SPeter Avalos 			*strp++ = IAC;
765068e7061SPeter Avalos 	}
766068e7061SPeter Avalos 	*strp++ = IAC;
767068e7061SPeter Avalos 	*strp++ = SE;
768068e7061SPeter Avalos 	net_write(str_keyid, strp - str_keyid);
769068e7061SPeter Avalos 	printsub('>', &str_keyid[2], strp - str_keyid - 2);
770068e7061SPeter Avalos }
771068e7061SPeter Avalos 
772068e7061SPeter Avalos void
encrypt_auto(int on)773068e7061SPeter Avalos encrypt_auto(int on)
774068e7061SPeter Avalos {
775068e7061SPeter Avalos 	if (on < 0)
776068e7061SPeter Avalos 		autoencrypt ^= 1;
777068e7061SPeter Avalos 	else
778068e7061SPeter Avalos 		autoencrypt = on ? 1 : 0;
779068e7061SPeter Avalos }
780068e7061SPeter Avalos 
781068e7061SPeter Avalos void
decrypt_auto(int on)782068e7061SPeter Avalos decrypt_auto(int on)
783068e7061SPeter Avalos {
784068e7061SPeter Avalos 	if (on < 0)
785068e7061SPeter Avalos 		autodecrypt ^= 1;
786068e7061SPeter Avalos 	else
787068e7061SPeter Avalos 		autodecrypt = on ? 1 : 0;
788068e7061SPeter Avalos }
789068e7061SPeter Avalos 
790068e7061SPeter Avalos void
encrypt_start_output(int type)791068e7061SPeter Avalos encrypt_start_output(int type)
792068e7061SPeter Avalos {
793068e7061SPeter Avalos 	Encryptions *ep;
794068e7061SPeter Avalos 	unsigned char *p;
795068e7061SPeter Avalos 	int i;
796068e7061SPeter Avalos 
797068e7061SPeter Avalos 	if (!(ep = findencryption(type))) {
798068e7061SPeter Avalos 		if (encrypt_debug_mode) {
799068e7061SPeter Avalos 			printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
800068e7061SPeter Avalos 				Name,
801068e7061SPeter Avalos 				ENCTYPE_NAME_OK(type)
802068e7061SPeter Avalos 					? ENCTYPE_NAME(type) : "(unknown)",
803068e7061SPeter Avalos 				type);
804068e7061SPeter Avalos 		}
805068e7061SPeter Avalos 		return;
806068e7061SPeter Avalos 	}
807068e7061SPeter Avalos 	if (ep->start) {
808068e7061SPeter Avalos 		i = (*ep->start)(DIR_ENCRYPT, Server);
809068e7061SPeter Avalos 		if (encrypt_debug_mode) {
810068e7061SPeter Avalos 			printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
811068e7061SPeter Avalos 				Name,
812068e7061SPeter Avalos 				(i < 0) ? "failed" :
813068e7061SPeter Avalos 					"initial negotiation in progress",
814068e7061SPeter Avalos 				i, ENCTYPE_NAME(type));
815068e7061SPeter Avalos 		}
816068e7061SPeter Avalos 		if (i)
817068e7061SPeter Avalos 			return;
818068e7061SPeter Avalos 	}
819068e7061SPeter Avalos 	p = str_start + 3;
820068e7061SPeter Avalos 	*p++ = ENCRYPT_START;
821068e7061SPeter Avalos 	for (i = 0; i < ki[0].keylen; ++i) {
822068e7061SPeter Avalos 		if ((*p++ = ki[0].keyid[i]) == IAC)
823068e7061SPeter Avalos 			*p++ = IAC;
824068e7061SPeter Avalos 	}
825068e7061SPeter Avalos 	*p++ = IAC;
826068e7061SPeter Avalos 	*p++ = SE;
827068e7061SPeter Avalos 	net_write(str_start, p - str_start);
828068e7061SPeter Avalos 	net_encrypt();
829068e7061SPeter Avalos 	printsub('>', &str_start[2], p - &str_start[2]);
830068e7061SPeter Avalos 	/*
831068e7061SPeter Avalos 	 * If we are already encrypting in some mode, then
832068e7061SPeter Avalos 	 * encrypt the ring (which includes our request) in
833068e7061SPeter Avalos 	 * the old mode, mark it all as "clear text" and then
834068e7061SPeter Avalos 	 * switch to the new mode.
835068e7061SPeter Avalos 	 */
836068e7061SPeter Avalos 	encrypt_output = ep->output;
837068e7061SPeter Avalos 	encrypt_mode = type;
838068e7061SPeter Avalos 	if (encrypt_debug_mode)
839068e7061SPeter Avalos 		printf(">>>%s: Started to encrypt output with type %s\r\n",
840068e7061SPeter Avalos 			Name, ENCTYPE_NAME(type));
841068e7061SPeter Avalos 	if (encrypt_verbose)
842068e7061SPeter Avalos 		printf("[ Output is now encrypted with type %s ]\r\n",
843068e7061SPeter Avalos 			ENCTYPE_NAME(type));
844068e7061SPeter Avalos }
845068e7061SPeter Avalos 
846068e7061SPeter Avalos void
encrypt_send_end(void)847068e7061SPeter Avalos encrypt_send_end(void)
848068e7061SPeter Avalos {
849068e7061SPeter Avalos 	if (!encrypt_output)
850068e7061SPeter Avalos 		return;
851068e7061SPeter Avalos 
852068e7061SPeter Avalos 	str_end[3] = ENCRYPT_END;
853068e7061SPeter Avalos 	net_write(str_end, sizeof(str_end));
854068e7061SPeter Avalos 	net_encrypt();
855068e7061SPeter Avalos 	printsub('>', &str_end[2], sizeof(str_end) - 2);
856068e7061SPeter Avalos 	/*
857068e7061SPeter Avalos 	 * Encrypt the output buffer now because it will not be done by
858068e7061SPeter Avalos 	 * netflush...
859068e7061SPeter Avalos 	 */
860678e8cc6SSascha Wildner 	encrypt_output = NULL;
861068e7061SPeter Avalos 	if (encrypt_debug_mode)
862068e7061SPeter Avalos 		printf(">>>%s: Output is back to clear text\r\n", Name);
863068e7061SPeter Avalos 	if (encrypt_verbose)
864068e7061SPeter Avalos 		printf("[ Output is now clear text ]\r\n");
865068e7061SPeter Avalos }
866068e7061SPeter Avalos 
867068e7061SPeter Avalos void
encrypt_send_request_start(void)868068e7061SPeter Avalos encrypt_send_request_start(void)
869068e7061SPeter Avalos {
870068e7061SPeter Avalos 	unsigned char *p;
871068e7061SPeter Avalos 	int i;
872068e7061SPeter Avalos 
873068e7061SPeter Avalos 	p = &str_start[3];
874068e7061SPeter Avalos 	*p++ = ENCRYPT_REQSTART;
875068e7061SPeter Avalos 	for (i = 0; i < ki[1].keylen; ++i) {
876068e7061SPeter Avalos 		if ((*p++ = ki[1].keyid[i]) == IAC)
877068e7061SPeter Avalos 			*p++ = IAC;
878068e7061SPeter Avalos 	}
879068e7061SPeter Avalos 	*p++ = IAC;
880068e7061SPeter Avalos 	*p++ = SE;
881068e7061SPeter Avalos 	net_write(str_start, p - str_start);
882068e7061SPeter Avalos 	printsub('>', &str_start[2], p - &str_start[2]);
883068e7061SPeter Avalos 	if (encrypt_debug_mode)
884068e7061SPeter Avalos 		printf(">>>%s: Request input to be encrypted\r\n", Name);
885068e7061SPeter Avalos }
886068e7061SPeter Avalos 
887068e7061SPeter Avalos void
encrypt_send_request_end(void)888068e7061SPeter Avalos encrypt_send_request_end(void)
889068e7061SPeter Avalos {
890068e7061SPeter Avalos 	str_end[3] = ENCRYPT_REQEND;
891068e7061SPeter Avalos 	net_write(str_end, sizeof(str_end));
892068e7061SPeter Avalos 	printsub('>', &str_end[2], sizeof(str_end) - 2);
893068e7061SPeter Avalos 
894068e7061SPeter Avalos 	if (encrypt_debug_mode)
895068e7061SPeter Avalos 		printf(">>>%s: Request input to be clear text\r\n", Name);
896068e7061SPeter Avalos }
897068e7061SPeter Avalos 
898068e7061SPeter Avalos void
encrypt_wait(void)899068e7061SPeter Avalos encrypt_wait(void)
900068e7061SPeter Avalos {
901068e7061SPeter Avalos 	if (encrypt_debug_mode)
902068e7061SPeter Avalos 		printf(">>>%s: in encrypt_wait\r\n", Name);
903068e7061SPeter Avalos 	if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
904068e7061SPeter Avalos 		return;
905068e7061SPeter Avalos 	while (autoencrypt && !encrypt_output)
906068e7061SPeter Avalos 		if (telnet_spin())
907068e7061SPeter Avalos 			return;
908068e7061SPeter Avalos }
909068e7061SPeter Avalos 
910068e7061SPeter Avalos void
encrypt_gen_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)911068e7061SPeter Avalos encrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
912068e7061SPeter Avalos {
913068e7061SPeter Avalos 	char tbuf[16], *cp;
914068e7061SPeter Avalos 
915068e7061SPeter Avalos 	cnt -= 2;
916068e7061SPeter Avalos 	data += 2;
917068e7061SPeter Avalos 	buf[buflen-1] = '\0';
918068e7061SPeter Avalos 	buf[buflen-2] = '*';
9193598cc14SSascha Wildner 	buflen -= 2;
920068e7061SPeter Avalos 	for (; cnt > 0; cnt--, data++) {
921068e7061SPeter Avalos 		sprintf(tbuf, " %d", *data);
922068e7061SPeter Avalos 		for (cp = tbuf; *cp && buflen > 0; --buflen)
923068e7061SPeter Avalos 			*buf++ = *cp++;
924068e7061SPeter Avalos 		if (buflen <= 0)
925068e7061SPeter Avalos 			return;
926068e7061SPeter Avalos 	}
927068e7061SPeter Avalos 	*buf = '\0';
928068e7061SPeter Avalos }
929068e7061SPeter Avalos 
930068e7061SPeter Avalos void
encrypt_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)931068e7061SPeter Avalos encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
932068e7061SPeter Avalos {
933068e7061SPeter Avalos 	Encryptions *ep;
934068e7061SPeter Avalos 	int type = data[1];
935068e7061SPeter Avalos 
936068e7061SPeter Avalos 	for (ep = encryptions; ep->type && ep->type != type; ep++)
937068e7061SPeter Avalos 		;
938068e7061SPeter Avalos 
939068e7061SPeter Avalos 	if (ep->printsub)
940068e7061SPeter Avalos 		(*ep->printsub)(data, cnt, buf, buflen);
941068e7061SPeter Avalos 	else
942068e7061SPeter Avalos 		encrypt_gen_printsub(data, cnt, buf, buflen);
943068e7061SPeter Avalos }
944068e7061SPeter Avalos #endif	/* ENCRYPTION */
945