xref: /csrg-svn/lib/libtelnet/encrypt.c (revision 46801)
1*46801Sdab /*-
2*46801Sdab  * Copyright (c) 1991 The Regents of the University of California.
3*46801Sdab  * All rights reserved.
4*46801Sdab  *
5*46801Sdab  * %sccs.include.redist.c%
6*46801Sdab  */
7*46801Sdab 
8*46801Sdab #ifndef lint
9*46801Sdab static char sccsid[] = "@(#)encrypt.c	5.1 (Berkeley) 02/28/91";
10*46801Sdab #endif /* not lint */
11*46801Sdab 
12*46801Sdab /*
13*46801Sdab  * Copyright (C) 1990 by the Massachusetts Institute of Technology
14*46801Sdab  *
15*46801Sdab  * Export of this software from the United States of America is assumed
16*46801Sdab  * to require a specific license from the United States Government.
17*46801Sdab  * It is the responsibility of any person or organization contemplating
18*46801Sdab  * export to obtain such a license before exporting.
19*46801Sdab  *
20*46801Sdab  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
21*46801Sdab  * distribute this software and its documentation for any purpose and
22*46801Sdab  * without fee is hereby granted, provided that the above copyright
23*46801Sdab  * notice appear in all copies and that both that copyright notice and
24*46801Sdab  * this permission notice appear in supporting documentation, and that
25*46801Sdab  * the name of M.I.T. not be used in advertising or publicity pertaining
26*46801Sdab  * to distribution of the software without specific, written prior
27*46801Sdab  * permission.  M.I.T. makes no representations about the suitability of
28*46801Sdab  * this software for any purpose.  It is provided "as is" without express
29*46801Sdab  * or implied warranty.
30*46801Sdab  */
31*46801Sdab 
32*46801Sdab #if	defined(ENCRYPT)
33*46801Sdab 
34*46801Sdab #define	ENCRYPT_NAMES
35*46801Sdab #include <arpa/telnet.h>
36*46801Sdab 
37*46801Sdab #include "encrypt.h"
38*46801Sdab #include "misc.h"
39*46801Sdab 
40*46801Sdab #ifdef	__STDC__
41*46801Sdab #include <stdlib.h>
42*46801Sdab #endif
43*46801Sdab #ifdef	NO_STRING_H
44*46801Sdab #include <strings.h>
45*46801Sdab #else
46*46801Sdab #include <string.h>
47*46801Sdab #endif
48*46801Sdab 
49*46801Sdab /*
50*46801Sdab  * These functions pointers point to the current routines
51*46801Sdab  * for encrypting and decrypting data.
52*46801Sdab  */
53*46801Sdab void	(*encrypt_output) P((unsigned char *, int));
54*46801Sdab int	(*decrypt_input) P((int));
55*46801Sdab 
56*46801Sdab int encrypt_debug_mode = 0;
57*46801Sdab static int decrypt_mode = 0;
58*46801Sdab static int encrypt_mode = 0;
59*46801Sdab static int encrypt_verbose = 0;
60*46801Sdab static int autoencrypt = 0;
61*46801Sdab static int autodecrypt = 0;
62*46801Sdab static int havesessionkey = 0;
63*46801Sdab static int encrypt_mark = 0;
64*46801Sdab static int decrypt_mark = 0;
65*46801Sdab static int Server = 0;
66*46801Sdab static char *Name = "Noname";
67*46801Sdab 
68*46801Sdab #define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
69*46801Sdab 
70*46801Sdab static long i_support_encrypt = typemask(ENCTYPE_KRBDES);
71*46801Sdab static long i_support_decrypt = typemask(ENCTYPE_KRBDES);
72*46801Sdab static long remote_supports_encrypt = 0;
73*46801Sdab static long remote_supports_decrypt = 0;
74*46801Sdab 
75*46801Sdab static Encryptions encryptions[] = {
76*46801Sdab #if	defined(KRBDES_ENCRYPT)
77*46801Sdab     { "KRBDES",		ENCTYPE_KRBDES,
78*46801Sdab 			krbdes_encrypt,
79*46801Sdab 			krbdes_decrypt,
80*46801Sdab 			krbdes_init,
81*46801Sdab 			krbdes_start,
82*46801Sdab 			krbdes_is,
83*46801Sdab 			krbdes_reply,
84*46801Sdab 			krbdes_session,
85*46801Sdab 			krbdes_printsub },
86*46801Sdab #endif
87*46801Sdab     { 0, },
88*46801Sdab };
89*46801Sdab 
90*46801Sdab static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
91*46801Sdab 					 ENCRYPT_SUPPORT, };
92*46801Sdab static unsigned char str_suplen = 0;
93*46801Sdab static unsigned char str_start[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
94*46801Sdab static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
95*46801Sdab 
96*46801Sdab 	Encryptions *
97*46801Sdab findencryption(type)
98*46801Sdab 	int type;
99*46801Sdab {
100*46801Sdab 	Encryptions *ep = encryptions;
101*46801Sdab 
102*46801Sdab 	if (!(i_support_encrypt & remote_supports_decrypt & typemask(type)))
103*46801Sdab 		return(0);
104*46801Sdab 	while (ep->type && ep->type != type)
105*46801Sdab 		++ep;
106*46801Sdab 	return(ep->type ? ep : 0);
107*46801Sdab }
108*46801Sdab 
109*46801Sdab 	Encryptions *
110*46801Sdab finddecryption(type)
111*46801Sdab 	int type;
112*46801Sdab {
113*46801Sdab 	Encryptions *ep = encryptions;
114*46801Sdab 
115*46801Sdab 	if (!(i_support_decrypt & remote_supports_encrypt & typemask(type)))
116*46801Sdab 		return(0);
117*46801Sdab 	while (ep->type && ep->type != type)
118*46801Sdab 		++ep;
119*46801Sdab 	return(ep->type ? ep : 0);
120*46801Sdab }
121*46801Sdab 
122*46801Sdab 	void
123*46801Sdab encrypt_init(name, server)
124*46801Sdab 	char *name;
125*46801Sdab 	int server;
126*46801Sdab {
127*46801Sdab 	Encryptions *ep = encryptions;
128*46801Sdab 
129*46801Sdab 	Name = name;
130*46801Sdab 	Server = server;
131*46801Sdab 	i_support_encrypt = i_support_decrypt = 0;
132*46801Sdab 	remote_supports_encrypt = remote_supports_decrypt = 0;
133*46801Sdab 	encrypt_mode = 0;
134*46801Sdab 	decrypt_mode = 0;
135*46801Sdab 	encrypt_output = 0;
136*46801Sdab 	decrypt_input = 0;
137*46801Sdab #ifdef notdef
138*46801Sdab 	encrypt_verbose = !server;
139*46801Sdab #endif
140*46801Sdab 
141*46801Sdab 	str_suplen = 4;
142*46801Sdab 
143*46801Sdab 	while (ep->type) {
144*46801Sdab 		if (encrypt_debug_mode)
145*46801Sdab 			printf(">>>%s: I will support %s\r\n",
146*46801Sdab 				Name, ENCTYPE_NAME(ep->type));
147*46801Sdab 		i_support_encrypt |= typemask(ep->type);
148*46801Sdab 		i_support_decrypt |= typemask(ep->type);
149*46801Sdab 		if ((str_send[str_suplen++] = ep->type) == IAC)
150*46801Sdab 			str_send[str_suplen++] = IAC;
151*46801Sdab 		if (ep->init)
152*46801Sdab 			(*ep->init)(Server);
153*46801Sdab 		++ep;
154*46801Sdab 	}
155*46801Sdab 	str_send[str_suplen++] = IAC;
156*46801Sdab 	str_send[str_suplen++] = SE;
157*46801Sdab }
158*46801Sdab 
159*46801Sdab 	void
160*46801Sdab encrypt_list_types()
161*46801Sdab {
162*46801Sdab 	Encryptions *ep = encryptions;
163*46801Sdab 
164*46801Sdab 	printf("Valid encryption types:\n");
165*46801Sdab 	while (ep->type) {
166*46801Sdab 		printf("\t%s\n\n", ENCTYPE_NAME(ep->type));
167*46801Sdab 		++ep;
168*46801Sdab 	}
169*46801Sdab }
170*46801Sdab 
171*46801Sdab 	int
172*46801Sdab EncryptEnable(type, mode)
173*46801Sdab 	char *type, *mode;
174*46801Sdab {
175*46801Sdab 	if (isprefix(type, "help") || isprefix(type, "?")) {
176*46801Sdab 		printf("Usage: encrypt enable <type> [input|output]\n");
177*46801Sdab 		encrypt_list_types();
178*46801Sdab 		return(0);
179*46801Sdab 	}
180*46801Sdab 	if (EncryptType(type, mode))
181*46801Sdab 		return(EncryptStart(mode));
182*46801Sdab 	return(0);
183*46801Sdab }
184*46801Sdab 
185*46801Sdab 	int
186*46801Sdab EncryptType(type, mode)
187*46801Sdab 	char *type;
188*46801Sdab 	char *mode;
189*46801Sdab {
190*46801Sdab 	register Encryptions *ep;
191*46801Sdab 
192*46801Sdab 	if (isprefix(type, "help") || isprefix(type, "?")) {
193*46801Sdab 		printf("Usage: encrypt type <type> [input|output]\n");
194*46801Sdab 		encrypt_list_types();
195*46801Sdab 		return(0);
196*46801Sdab 	}
197*46801Sdab 
198*46801Sdab 	ep = (Encryptions *)genget(type, encryptions, sizeof(Encryptions));
199*46801Sdab 
200*46801Sdab 	if (ep == 0) {
201*46801Sdab 		printf("%s: invalid encryption type\n", type);
202*46801Sdab 		return(0);
203*46801Sdab 	}
204*46801Sdab 	if (Ambiguous(ep)) {
205*46801Sdab 		printf("Ambiguous type '%s'\n", type);
206*46801Sdab 		return(0);
207*46801Sdab 	}
208*46801Sdab 
209*46801Sdab 	if (mode) {
210*46801Sdab 		if (isprefix(mode, "input"))
211*46801Sdab 			decrypt_mode = ep->type;
212*46801Sdab 		else if (isprefix(mode, "output"))
213*46801Sdab 			encrypt_mode = ep->type;
214*46801Sdab 		else {
215*46801Sdab 			printf("%s: invalid encryption mode\n", mode);
216*46801Sdab 			return(0);
217*46801Sdab 		}
218*46801Sdab 	} else
219*46801Sdab 		decrypt_mode = encrypt_mode = ep->type;
220*46801Sdab 	return(1);
221*46801Sdab }
222*46801Sdab 
223*46801Sdab 	int
224*46801Sdab EncryptStart(mode)
225*46801Sdab 	char *mode;
226*46801Sdab {
227*46801Sdab 	register int ret = 0;
228*46801Sdab 	if (mode) {
229*46801Sdab 		if (isprefix(mode, "input"))
230*46801Sdab 			return(EncryptStartInput());
231*46801Sdab 		if (isprefix(mode, "output"))
232*46801Sdab 			return(EncryptStartOutput());
233*46801Sdab 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
234*46801Sdab 			printf("Usage: encrypt start [input|output]\n");
235*46801Sdab 			return(0);
236*46801Sdab 		}
237*46801Sdab 		printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
238*46801Sdab 		return(0);
239*46801Sdab 	}
240*46801Sdab 	ret += EncryptStartInput();
241*46801Sdab 	ret += EncryptStartOutput();
242*46801Sdab 	return(ret);
243*46801Sdab }
244*46801Sdab 
245*46801Sdab 	int
246*46801Sdab EncryptStartInput()
247*46801Sdab {
248*46801Sdab 	if (decrypt_mode) {
249*46801Sdab 		encrypt_send_request_start();
250*46801Sdab 		return(1);
251*46801Sdab 	}
252*46801Sdab 	printf("No previous decryption mode, decryption not enabled\r\n");
253*46801Sdab 	return(0);
254*46801Sdab }
255*46801Sdab 
256*46801Sdab 	int
257*46801Sdab EncryptStartOutput()
258*46801Sdab {
259*46801Sdab 	if (encrypt_mode) {
260*46801Sdab 		encrypt_start_output(encrypt_mode);
261*46801Sdab 		return(1);
262*46801Sdab 	}
263*46801Sdab 	printf("No previous encryption mode, encryption not enabled\r\n");
264*46801Sdab 	return(0);
265*46801Sdab }
266*46801Sdab 
267*46801Sdab 	int
268*46801Sdab EncryptStop(mode)
269*46801Sdab 	char *mode;
270*46801Sdab {
271*46801Sdab 	int ret = 0;
272*46801Sdab 	if (mode) {
273*46801Sdab 		if (isprefix(mode, "input"))
274*46801Sdab 			return(EncryptStopInput());
275*46801Sdab 		if (isprefix(mode, "output"))
276*46801Sdab 			return(EncryptStopOutput());
277*46801Sdab 		if (isprefix(mode, "help") || isprefix(mode, "?")) {
278*46801Sdab 			printf("Usage: encrypt stop [input|output]\n");
279*46801Sdab 			return(0);
280*46801Sdab 		}
281*46801Sdab 		printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
282*46801Sdab 		return(0);
283*46801Sdab 	}
284*46801Sdab 	ret += EncryptStopInput();
285*46801Sdab 	ret += EncryptStopOutput();
286*46801Sdab 	return(ret);
287*46801Sdab }
288*46801Sdab 
289*46801Sdab 	int
290*46801Sdab EncryptStopInput()
291*46801Sdab {
292*46801Sdab 	encrypt_send_request_end();
293*46801Sdab 	return(1);
294*46801Sdab }
295*46801Sdab 
296*46801Sdab 	int
297*46801Sdab EncryptStopOutput()
298*46801Sdab {
299*46801Sdab 	encrypt_send_end();
300*46801Sdab 	return(1);
301*46801Sdab }
302*46801Sdab 
303*46801Sdab 	void
304*46801Sdab encrypt_display()
305*46801Sdab {
306*46801Sdab 	if (encrypt_output)
307*46801Sdab 		printf("Currently encrypting output with %s\r\n",
308*46801Sdab 			ENCTYPE_NAME(encrypt_mode));
309*46801Sdab 	if (decrypt_input)
310*46801Sdab 		printf("Currently decrypting input with %s\r\n",
311*46801Sdab 			ENCTYPE_NAME(decrypt_mode));
312*46801Sdab }
313*46801Sdab 
314*46801Sdab 	int
315*46801Sdab EncryptStatus()
316*46801Sdab {
317*46801Sdab 	if (encrypt_output)
318*46801Sdab 		printf("Currently encrypting output with %s\r\n",
319*46801Sdab 			ENCTYPE_NAME(encrypt_mode));
320*46801Sdab 	else if (encrypt_mode) {
321*46801Sdab 		printf("Currently output is clear text.\r\n");
322*46801Sdab 		printf("Last encryption mode was %s\r\n",
323*46801Sdab 			ENCTYPE_NAME(encrypt_mode));
324*46801Sdab 	}
325*46801Sdab 	if (decrypt_input) {
326*46801Sdab 		printf("Currently decrypting input with %s\r\n",
327*46801Sdab 			ENCTYPE_NAME(decrypt_mode));
328*46801Sdab 	} else if (decrypt_mode) {
329*46801Sdab 		printf("Currently input is clear text.\r\n");
330*46801Sdab 		printf("Last decryption mode was %s\r\n",
331*46801Sdab 			ENCTYPE_NAME(decrypt_mode));
332*46801Sdab 	}
333*46801Sdab 	return 1;
334*46801Sdab }
335*46801Sdab 
336*46801Sdab 	void
337*46801Sdab encrypt_send_support()
338*46801Sdab {
339*46801Sdab 	if (str_suplen) {
340*46801Sdab 		/*
341*46801Sdab 		 * If the user has requested that decryption start
342*46801Sdab 		 * immediatly, then send a "REQUEST START" before
343*46801Sdab 		 * we negotiate the type.
344*46801Sdab 		 */
345*46801Sdab 		if (!Server && autodecrypt)
346*46801Sdab 			encrypt_send_request_start();
347*46801Sdab 		net_write(str_send, str_suplen);
348*46801Sdab 		printsub('>', &str_send[2], str_suplen - 2);
349*46801Sdab 		str_suplen = 0;
350*46801Sdab 	}
351*46801Sdab }
352*46801Sdab 
353*46801Sdab 	int
354*46801Sdab EncryptTogDebug()
355*46801Sdab {
356*46801Sdab 	encrypt_debug_mode ^= 1;
357*46801Sdab 	printf("Encryption debugging %s\r\n",
358*46801Sdab 		encrypt_debug_mode ? "enabled" : "disabled");
359*46801Sdab 	return(1);
360*46801Sdab }
361*46801Sdab 
362*46801Sdab 	int
363*46801Sdab EncryptTogVerbose()
364*46801Sdab {
365*46801Sdab 	encrypt_verbose ^= 1;
366*46801Sdab 	printf("Encryption %s verbose\r\n",
367*46801Sdab 		encrypt_verbose ? "is" : "is not");
368*46801Sdab 	return(1);
369*46801Sdab }
370*46801Sdab 
371*46801Sdab 	int
372*46801Sdab EncryptTogAuto()
373*46801Sdab {
374*46801Sdab 	autoencrypt ^= 1;
375*46801Sdab 	autodecrypt ^= 1;
376*46801Sdab 	printf("Automatic encryption of data is %s\r\n",
377*46801Sdab 		autoencrypt ? "enabled" : "disabled");
378*46801Sdab 	return(1);
379*46801Sdab }
380*46801Sdab 
381*46801Sdab 
382*46801Sdab /*
383*46801Sdab  * Called when ENCRYPT SUPPORT is received.
384*46801Sdab  */
385*46801Sdab 	void
386*46801Sdab encrypt_support(typelist, cnt)
387*46801Sdab 	unsigned char *typelist;
388*46801Sdab 	int cnt;
389*46801Sdab {
390*46801Sdab 	register int type, use_type = 0;
391*46801Sdab 	Encryptions *ep;
392*46801Sdab 
393*46801Sdab 	/*
394*46801Sdab 	 * Forget anything the other side has previously told us.
395*46801Sdab 	 */
396*46801Sdab 	remote_supports_decrypt = 0;
397*46801Sdab 
398*46801Sdab 	while (cnt-- > 0) {
399*46801Sdab 		type = *typelist++;
400*46801Sdab 		if (encrypt_debug_mode)
401*46801Sdab 			printf(">>>%s: He is supporting %s (%d)\r\n",
402*46801Sdab 				Name,
403*46801Sdab 				ENCTYPE_NAME(type), type);
404*46801Sdab 		if ((type < ENCTYPE_CNT) &&
405*46801Sdab 		    (i_support_encrypt & typemask(type))) {
406*46801Sdab 			remote_supports_decrypt |= typemask(type);
407*46801Sdab 			if (use_type == 0)
408*46801Sdab 				use_type = type;
409*46801Sdab 		}
410*46801Sdab 	}
411*46801Sdab 	if (use_type) {
412*46801Sdab 		ep = findencryption(use_type);
413*46801Sdab 		if (!ep)
414*46801Sdab 			return;
415*46801Sdab 		type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
416*46801Sdab 		if (encrypt_debug_mode)
417*46801Sdab 			printf(">>>%s: (*ep->start)() returned %d\r\n",
418*46801Sdab 					Name, type);
419*46801Sdab 		if (type < 0)
420*46801Sdab 			return;
421*46801Sdab 		encrypt_mode = type;
422*46801Sdab 		if (type == 0)
423*46801Sdab 			encrypt_start_output(use_type);
424*46801Sdab 	}
425*46801Sdab }
426*46801Sdab 
427*46801Sdab 	void
428*46801Sdab encrypt_is(data, cnt)
429*46801Sdab 	unsigned char *data;
430*46801Sdab 	int cnt;
431*46801Sdab {
432*46801Sdab 	Encryptions *ep;
433*46801Sdab 	register int type, ret;
434*46801Sdab 
435*46801Sdab 	if (--cnt < 0)
436*46801Sdab 		return;
437*46801Sdab 	type = *data++;
438*46801Sdab 	if (type < ENCTYPE_CNT)
439*46801Sdab 		remote_supports_encrypt |= typemask(type);
440*46801Sdab 	if (!(ep = finddecryption(type))) {
441*46801Sdab 		if (encrypt_debug_mode)
442*46801Sdab 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
443*46801Sdab 				Name,
444*46801Sdab 				ENCTYPE_NAME(data[-1]), data[1]);
445*46801Sdab 		return;
446*46801Sdab 	}
447*46801Sdab 	if (!ep->is) {
448*46801Sdab 		if (encrypt_debug_mode)
449*46801Sdab 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
450*46801Sdab 				Name,
451*46801Sdab 				ENCTYPE_NAME(type), type);
452*46801Sdab 		ret = 0;
453*46801Sdab 	} else {
454*46801Sdab 		ret = (*ep->is)(data, cnt);
455*46801Sdab /*@*/		if (encrypt_debug_mode)
456*46801Sdab /*@*/			printf("(*ep->is)(%x, %d) returned %s(%d)\n", data, cnt,
457*46801Sdab /*@*/				(ret < 0) ? "FAIL " :
458*46801Sdab /*@*/				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
459*46801Sdab 	}
460*46801Sdab 	if (ret < 0) {
461*46801Sdab 		autodecrypt = 0;
462*46801Sdab 	} else {
463*46801Sdab 		decrypt_mode = type;
464*46801Sdab 		if (ret == 0 && autodecrypt)
465*46801Sdab 			encrypt_send_request_start();
466*46801Sdab 	}
467*46801Sdab }
468*46801Sdab 
469*46801Sdab 	void
470*46801Sdab encrypt_reply(data, cnt)
471*46801Sdab 	unsigned char *data;
472*46801Sdab 	int cnt;
473*46801Sdab {
474*46801Sdab 	Encryptions *ep;
475*46801Sdab 	register int ret, type;
476*46801Sdab 
477*46801Sdab 	if (--cnt < 0)
478*46801Sdab 		return;
479*46801Sdab 	type = *data++;
480*46801Sdab 	if (!(ep = findencryption(type))) {
481*46801Sdab 		if (encrypt_debug_mode)
482*46801Sdab 			printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
483*46801Sdab 				Name,
484*46801Sdab 				ENCTYPE_NAME(data[-1]), data[1]);
485*46801Sdab 		return;
486*46801Sdab 	}
487*46801Sdab 	if (!ep->reply) {
488*46801Sdab 		if (encrypt_debug_mode)
489*46801Sdab 			printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
490*46801Sdab 				Name,
491*46801Sdab 				ENCTYPE_NAME(data[-1]), data[1]);
492*46801Sdab 		ret = 0;
493*46801Sdab 	} else {
494*46801Sdab 		ret = (*ep->reply)(data, cnt);
495*46801Sdab /*@*/		if (encrypt_debug_mode)
496*46801Sdab /*@*/			printf("(*ep->reply)(%x, %d) returned %s(%d)\n",
497*46801Sdab /*@*/				data, cnt,
498*46801Sdab /*@*/				(ret < 0) ? "FAIL " :
499*46801Sdab /*@*/				(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
500*46801Sdab 	}
501*46801Sdab 	if (encrypt_debug_mode)
502*46801Sdab 		printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
503*46801Sdab 	if (ret < 0) {
504*46801Sdab 		autoencrypt = 0;
505*46801Sdab 	} else {
506*46801Sdab 		encrypt_mode = type;
507*46801Sdab 		if (ret == 0 && autoencrypt)
508*46801Sdab 			encrypt_start_output(type);
509*46801Sdab 	}
510*46801Sdab }
511*46801Sdab 
512*46801Sdab /*
513*46801Sdab  * Called when a ENCRYPT START command is received.
514*46801Sdab  */
515*46801Sdab 	void
516*46801Sdab encrypt_start()
517*46801Sdab {
518*46801Sdab 	Encryptions *ep;
519*46801Sdab 
520*46801Sdab 	if (!decrypt_mode) {
521*46801Sdab 		/*
522*46801Sdab 		 * Something is wrong.  We should not get a START
523*46801Sdab 		 * command without having already picked our
524*46801Sdab 		 * decryption scheme.  Send a REQUEST-END to
525*46801Sdab 		 * attempt to clear the channel...
526*46801Sdab 		 */
527*46801Sdab 		printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
528*46801Sdab 		encrypt_send_request_end();
529*46801Sdab 		return;
530*46801Sdab 	}
531*46801Sdab 
532*46801Sdab 	if (ep = finddecryption(decrypt_mode)) {
533*46801Sdab 		decrypt_input = ep->input;
534*46801Sdab 		if (encrypt_verbose)
535*46801Sdab 			printf("[ Input is now decrypted with type %s ]\r\n",
536*46801Sdab 				ENCTYPE_NAME(decrypt_mode));
537*46801Sdab 		if (encrypt_debug_mode)
538*46801Sdab 			printf(">>>%s: Start to decrypt input with type %s\r\n",
539*46801Sdab 				Name, ENCTYPE_NAME(decrypt_mode));
540*46801Sdab 	} else {
541*46801Sdab 		printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
542*46801Sdab 				Name, ENCTYPE_NAME(decrypt_mode), decrypt_mode);
543*46801Sdab 		encrypt_send_request_end();
544*46801Sdab 	}
545*46801Sdab }
546*46801Sdab 
547*46801Sdab 	void
548*46801Sdab encrypt_session_key(key, server)
549*46801Sdab 	Session_Key *key;
550*46801Sdab 	int server;
551*46801Sdab {
552*46801Sdab 	Encryptions *ep = encryptions;
553*46801Sdab 
554*46801Sdab 	havesessionkey = 1;
555*46801Sdab 
556*46801Sdab 	while (ep->type) {
557*46801Sdab 		if (ep->session)
558*46801Sdab 			(*ep->session)(key, server);
559*46801Sdab 		if (!encrypt_output && autoencrypt && !server)
560*46801Sdab 			encrypt_start_output(ep->type);
561*46801Sdab 		if (!decrypt_input && autodecrypt && !server)
562*46801Sdab 			encrypt_send_request_start();
563*46801Sdab 		++ep;
564*46801Sdab 	}
565*46801Sdab }
566*46801Sdab 
567*46801Sdab /*
568*46801Sdab  * Called when ENCRYPT END is received.
569*46801Sdab  */
570*46801Sdab 	void
571*46801Sdab encrypt_end()
572*46801Sdab {
573*46801Sdab 	decrypt_input = 0;
574*46801Sdab 	if (encrypt_debug_mode)
575*46801Sdab 		printf(">>>%s: Input is back to clear text\r\n", Name);
576*46801Sdab 	if (encrypt_verbose)
577*46801Sdab 		printf("[ Input is now clear text ]\r\n");
578*46801Sdab }
579*46801Sdab 
580*46801Sdab /*
581*46801Sdab  * Called when ENCRYPT REQUEST-END is received.
582*46801Sdab  */
583*46801Sdab 	void
584*46801Sdab encrypt_request_end()
585*46801Sdab {
586*46801Sdab 	encrypt_send_end();
587*46801Sdab }
588*46801Sdab 
589*46801Sdab /*
590*46801Sdab  * Called when ENCRYPT REQUEST-START is received.  If we receive
591*46801Sdab  * this before a type is picked, then that indicates that the
592*46801Sdab  * other side wants us to start encrypting data as soon as we
593*46801Sdab  * can.
594*46801Sdab  */
595*46801Sdab 	void
596*46801Sdab encrypt_request_start()
597*46801Sdab {
598*46801Sdab 	if (!encrypt_mode && Server) {
599*46801Sdab 		autoencrypt = 1;
600*46801Sdab 		return;
601*46801Sdab 	}
602*46801Sdab 	encrypt_start_output(encrypt_mode);
603*46801Sdab }
604*46801Sdab 
605*46801Sdab 	void
606*46801Sdab encrypt_auto()
607*46801Sdab {
608*46801Sdab 	autoencrypt = 1;
609*46801Sdab 	autodecrypt = 1;
610*46801Sdab }
611*46801Sdab 
612*46801Sdab 	void
613*46801Sdab encrypt_start_output(type)
614*46801Sdab 	int type;
615*46801Sdab {
616*46801Sdab 	Encryptions *ep;
617*46801Sdab 	register int ret;
618*46801Sdab 
619*46801Sdab 	if (!(ep = findencryption(type))) {
620*46801Sdab 		if (encrypt_debug_mode) {
621*46801Sdab 			printf(">>>%s: Marking type %s for later encryption use\r\n",
622*46801Sdab 				Name,
623*46801Sdab 				ENCTYPE_NAME(type));
624*46801Sdab 		}
625*46801Sdab 		encrypt_mark |= typemask(type);
626*46801Sdab 		return;
627*46801Sdab 	}
628*46801Sdab 	if (ep->start) {
629*46801Sdab 		ret = (*ep->start)(DIR_ENCRYPT, Server);
630*46801Sdab 		if (ret) {
631*46801Sdab 			if (encrypt_debug_mode) {
632*46801Sdab 				if (ret < 0)
633*46801Sdab 					printf(">>>%s: Start failed for %s\r\n",
634*46801Sdab 						Name, ENCTYPE_NAME(type));
635*46801Sdab 				else
636*46801Sdab 					printf(">>>%s: Start: initial negotiation in progress%s\r\n",
637*46801Sdab 						Name, ENCTYPE_NAME(type));
638*46801Sdab 			}
639*46801Sdab 
640*46801Sdab 			return;
641*46801Sdab 		}
642*46801Sdab 	}
643*46801Sdab 	str_start[3] = ENCRYPT_START;
644*46801Sdab 	net_write(str_start, sizeof(str_start));
645*46801Sdab 	net_encrypt();
646*46801Sdab 	printsub('>', &str_start[2], sizeof(str_start) - 2);
647*46801Sdab 	/*
648*46801Sdab 	 * If we are already encrypting in some mode, then
649*46801Sdab 	 * encrypt the ring (which includes our request) in
650*46801Sdab 	 * the old mode, mark it all as "clear text" and then
651*46801Sdab 	 * switch to the new mode.
652*46801Sdab 	 */
653*46801Sdab 	encrypt_output = ep->output;
654*46801Sdab 	encrypt_mode = type;
655*46801Sdab 	if (encrypt_debug_mode)
656*46801Sdab 		printf(">>>%s: Started to encrypt output with type %s\r\n",
657*46801Sdab 			Name, ENCTYPE_NAME(type));
658*46801Sdab 	if (encrypt_verbose)
659*46801Sdab 		printf("[ Output is now encrypted with type %s ]\r\n",
660*46801Sdab 			ENCTYPE_NAME(type));
661*46801Sdab }
662*46801Sdab 
663*46801Sdab 	void
664*46801Sdab encrypt_send_end()
665*46801Sdab {
666*46801Sdab 	if (!encrypt_output)
667*46801Sdab 		return;
668*46801Sdab 
669*46801Sdab 	str_end[3] = ENCRYPT_END;
670*46801Sdab 	net_write(str_end, sizeof(str_end));
671*46801Sdab 	net_encrypt();
672*46801Sdab 	printsub('>', &str_end[2], sizeof(str_end) - 2);
673*46801Sdab 	/*
674*46801Sdab 	 * Encrypt the output buffer now because it will not be done by
675*46801Sdab 	 * netflush...
676*46801Sdab 	 */
677*46801Sdab 	encrypt_output = 0;
678*46801Sdab 	if (encrypt_debug_mode)
679*46801Sdab 		printf(">>>%s: Output is back to clear text\r\n", Name);
680*46801Sdab 	if (encrypt_verbose)
681*46801Sdab 		printf("[ Output is now clear text ]\r\n");
682*46801Sdab }
683*46801Sdab 
684*46801Sdab 	void
685*46801Sdab encrypt_send_request_start()
686*46801Sdab {
687*46801Sdab #ifdef notdef
688*46801Sdab 	Encryptions *ep;
689*46801Sdab 
690*46801Sdab 	if (!(ep = findencryption(type))) {
691*46801Sdab 		if (encrypt_debug_mode) {
692*46801Sdab 			printf(">>>%s: Marking type %s for later decryption use\r\n",
693*46801Sdab 				Name,
694*46801Sdab 				ENCTYPE_NAME(type));
695*46801Sdab 		}
696*46801Sdab 		decrypt_mark |= typemask(type);
697*46801Sdab 		return;
698*46801Sdab 	}
699*46801Sdab 
700*46801Sdab 	if (ep->start && (*ep->start)(DIR_DECRYPT, Server)) {
701*46801Sdab 		if (encrypt_debug_mode) {
702*46801Sdab 			printf(">>>%s: Request failed for %s\r\n",
703*46801Sdab 				Name,
704*46801Sdab 				ENCTYPE_NAME(type));
705*46801Sdab 		}
706*46801Sdab 		return;
707*46801Sdab 	}
708*46801Sdab #endif
709*46801Sdab 
710*46801Sdab 	str_start[3] = ENCRYPT_REQSTART;
711*46801Sdab 	net_write(str_start, sizeof(str_start));
712*46801Sdab 	printsub('>', &str_start[2], sizeof(str_start) - 2);
713*46801Sdab 	if (encrypt_debug_mode)
714*46801Sdab 		printf(">>>%s: Request input to be encrypted\r\n", Name);
715*46801Sdab }
716*46801Sdab 
717*46801Sdab 	void
718*46801Sdab encrypt_send_request_end()
719*46801Sdab {
720*46801Sdab 	str_end[3] = ENCRYPT_REQEND;
721*46801Sdab 	net_write(str_end, sizeof(str_end));
722*46801Sdab 	printsub('>', &str_end[2], sizeof(str_end) - 2);
723*46801Sdab 
724*46801Sdab 	if (encrypt_debug_mode)
725*46801Sdab 		printf(">>>%s: Request input to be clear text\r\n", Name);
726*46801Sdab }
727*46801Sdab 
728*46801Sdab 	void
729*46801Sdab encrypt_wait()
730*46801Sdab {
731*46801Sdab 	register int encrypt, decrypt;
732*46801Sdab 	if (encrypt_debug_mode)
733*46801Sdab 		printf(">>>%s: in encrypt_wait\r\n", Name);
734*46801Sdab 	if (!havesessionkey || !(i_support_encrypt & remote_supports_decrypt))
735*46801Sdab 		return;
736*46801Sdab 	while (autoencrypt && !encrypt_output)
737*46801Sdab 		if (telnet_spin())
738*46801Sdab 			return;
739*46801Sdab }
740*46801Sdab 
741*46801Sdab 	void
742*46801Sdab encrypt_debug(mode)
743*46801Sdab 	int mode;
744*46801Sdab {
745*46801Sdab 	encrypt_debug_mode = mode;
746*46801Sdab }
747*46801Sdab 
748*46801Sdab 	void
749*46801Sdab encrypt_gen_printsub(data, cnt, buf, buflen)
750*46801Sdab 	unsigned char *data, *buf;
751*46801Sdab 	int cnt, buflen;
752*46801Sdab {
753*46801Sdab 	char tbuf[16], *cp;
754*46801Sdab 
755*46801Sdab 	cnt -= 2;
756*46801Sdab 	data += 2;
757*46801Sdab 	buf[buflen-1] = '\0';
758*46801Sdab 	buf[buflen-2] = '*';
759*46801Sdab 	buflen -= 2;;
760*46801Sdab 	for (; cnt > 0; cnt--, data++) {
761*46801Sdab 		sprintf(tbuf, " %d", *data);
762*46801Sdab 		for (cp = tbuf; *cp && buflen > 0; --buflen)
763*46801Sdab 			*buf++ = *cp++;
764*46801Sdab 		if (buflen <= 0)
765*46801Sdab 			return;
766*46801Sdab 	}
767*46801Sdab 	*buf = '\0';
768*46801Sdab }
769*46801Sdab 
770*46801Sdab 	void
771*46801Sdab encrypt_printsub(data, cnt, buf, buflen)
772*46801Sdab 	unsigned char *data, *buf;
773*46801Sdab 	int cnt, buflen;
774*46801Sdab {
775*46801Sdab 	Encryptions *ep;
776*46801Sdab 	register int type = data[1];
777*46801Sdab 
778*46801Sdab 	for (ep = encryptions; ep->type && ep->type != type; ep++)
779*46801Sdab 		;
780*46801Sdab 
781*46801Sdab 	if (ep->printsub)
782*46801Sdab 		(*ep->printsub)(data, cnt, buf, buflen);
783*46801Sdab 	else
784*46801Sdab 		encrypt_gen_printsub(data, cnt, buf, buflen);
785*46801Sdab }
786*46801Sdab #endif
787